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_bytes();
43 let mut key_resref = [0_u8; 16];
44 key_resref[..resref_bytes.len()].copy_from_slice(resref_bytes);
45 writer.write_all(&key_resref)?;
46 write_u32(writer, u32::from(resource.resource_type.raw_id()))?;
47 write_u32(
48 writer,
49 u32::try_from(index).map_err(|_| RimBinaryError::ValueOverflow("resource_id"))?,
50 )?;
51 write_u32(writer, next_data_offset)?;
52 let data_len = u32::try_from(resource.data.len())
53 .map_err(|_| RimBinaryError::ValueOverflow("resource_size"))?;
54 write_u32(writer, data_len)?;
55 next_data_offset = next_data_offset
56 .checked_add(data_len)
57 .ok_or(RimBinaryError::ValueOverflow("data_offset"))?;
58 }
59
60 for resource in &rim.resources {
61 writer.write_all(&resource.data)?;
62 }
63
64 crate::trace_debug!(resource_count = rim.resources.len(), "wrote rim to writer");
65 Ok(())
66}
67
68#[cfg_attr(feature = "tracing", tracing::instrument(level = "debug", skip(rim)))]
70pub fn write_rim_to_vec(rim: &Rim) -> Result<Vec<u8>, RimBinaryError> {
71 let mut cursor = Cursor::new(Vec::new());
72 write_rim(&mut cursor, rim)?;
73 let bytes = cursor.into_inner();
74 crate::trace_debug!(bytes_len = bytes.len(), "serialized rim to vec");
75 Ok(bytes)
76}