rakata_formats/rim/
writer.rs1use std::io::{Cursor, Write};
4
5use crate::binary::write_u32;
6
7use super::{Rim, RimBinaryError, FILE_HEADER_SIZE, KEY_ENTRY_SIZE, RIM_MAGIC, RIM_VERSION_V10};
8
9#[cfg_attr(
11 feature = "tracing",
12 tracing::instrument(level = "debug", skip(writer, rim))
13)]
14pub fn write_rim<W: Write>(writer: &mut W, rim: &Rim) -> Result<(), RimBinaryError> {
15 let entry_count = u32::try_from(rim.resources.len())
16 .map_err(|_| RimBinaryError::ValueOverflow("entry_count"))?;
17 let keys_offset = u32::try_from(FILE_HEADER_SIZE)
18 .map_err(|_| RimBinaryError::ValueOverflow("keys_offset"))?;
19 let mut next_data_offset = keys_offset
20 .checked_add(
21 entry_count
22 .checked_mul(
23 u32::try_from(KEY_ENTRY_SIZE)
24 .map_err(|_| RimBinaryError::ValueOverflow("KEY_ENTRY_SIZE"))?,
25 )
26 .ok_or(RimBinaryError::ValueOverflow("data_offset"))?,
27 )
28 .ok_or(RimBinaryError::ValueOverflow("data_offset"))?;
29
30 writer.write_all(&RIM_MAGIC)?;
31 writer.write_all(&RIM_VERSION_V10)?;
32 write_u32(writer, rim.reserved_0x08)?;
33 write_u32(writer, entry_count)?;
34 write_u32(writer, keys_offset)?;
35 write_u32(writer, rim.reserved_0x14)?;
36 writer.write_all(&rim.reserved_0x18)?;
37
38 for (index, resource) in rim.resources.iter().enumerate() {
39 let resref_bytes = resource.resref.as_str().as_bytes();
42 let mut key_resref = [0_u8; 16];
43 key_resref[..resref_bytes.len()].copy_from_slice(resref_bytes);
44 writer.write_all(&key_resref)?;
45 write_u32(writer, u32::from(resource.resource_type.raw_id()))?;
46 write_u32(
47 writer,
48 u32::try_from(index).map_err(|_| RimBinaryError::ValueOverflow("resource_id"))?,
49 )?;
50 write_u32(writer, next_data_offset)?;
51 let data_len = u32::try_from(resource.data.len())
52 .map_err(|_| RimBinaryError::ValueOverflow("resource_size"))?;
53 write_u32(writer, data_len)?;
54 next_data_offset = next_data_offset
55 .checked_add(data_len)
56 .ok_or(RimBinaryError::ValueOverflow("data_offset"))?;
57 }
58
59 for resource in &rim.resources {
60 writer.write_all(&resource.data)?;
61 }
62
63 crate::trace_debug!(resource_count = rim.resources.len(), "wrote rim to writer");
64 Ok(())
65}
66
67#[cfg_attr(feature = "tracing", tracing::instrument(level = "debug", skip(rim)))]
69pub fn write_rim_to_vec(rim: &Rim) -> Result<Vec<u8>, RimBinaryError> {
70 let mut cursor = Cursor::new(Vec::new());
71 write_rim(&mut cursor, rim)?;
72 let bytes = cursor.into_inner();
73 crate::trace_debug!(bytes_len = bytes.len(), "serialized rim to vec");
74 Ok(bytes)
75}