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(
19 feature = "tracing",
20 tracing::instrument(level = "debug", skip(writer, rim))
21)]
22pub fn write_rim<W: Write>(writer: &mut W, rim: &Rim) -> Result<(), RimBinaryError> {
23 let entry_count = u32::try_from(rim.resources.len())
24 .map_err(|_| RimBinaryError::ValueOverflow("entry_count"))?;
25 let keys_offset = u32::try_from(FILE_HEADER_SIZE)
26 .map_err(|_| RimBinaryError::ValueOverflow("keys_offset"))?;
27 let mut next_data_offset = keys_offset
28 .checked_add(
29 entry_count
30 .checked_mul(
31 u32::try_from(KEY_ENTRY_SIZE)
32 .map_err(|_| RimBinaryError::ValueOverflow("KEY_ENTRY_SIZE"))?,
33 )
34 .ok_or(RimBinaryError::ValueOverflow("data_offset"))?,
35 )
36 .ok_or(RimBinaryError::ValueOverflow("data_offset"))?;
37
38 writer.write_all(&RIM_MAGIC)?;
39 writer.write_all(&RIM_VERSION_V10)?;
40 write_u32(writer, rim.reserved_0x08)?;
41 write_u32(writer, entry_count)?;
42 write_u32(writer, keys_offset)?;
43 write_u32(writer, rim.reserved_0x14)?;
44 writer.write_all(&rim.reserved_0x18)?;
45
46 for (index, resource) in rim.resources.iter().enumerate() {
47 writer.write_all(&resource.resref.to_padded())?;
50 write_u32(writer, u32::from(resource.resource_type.raw_id()))?;
51 write_u32(
52 writer,
53 u32::try_from(index).map_err(|_| RimBinaryError::ValueOverflow("resource_id"))?,
54 )?;
55 write_u32(writer, next_data_offset)?;
56 let data_len = u32::try_from(resource.data.len())
57 .map_err(|_| RimBinaryError::ValueOverflow("resource_size"))?;
58 write_u32(writer, data_len)?;
59 next_data_offset = next_data_offset
60 .checked_add(data_len)
61 .ok_or(RimBinaryError::ValueOverflow("data_offset"))?;
62 }
63
64 for resource in &rim.resources {
65 writer.write_all(&resource.data)?;
66 }
67
68 crate::trace_debug!(resource_count = rim.resources.len(), "wrote rim to writer");
69 Ok(())
70}
71
72#[cfg_attr(feature = "tracing", tracing::instrument(level = "debug", skip(rim)))]
79pub fn write_rim_to_vec(rim: &Rim) -> Result<Vec<u8>, RimBinaryError> {
80 let mut cursor = Cursor::new(Vec::new());
81 write_rim(&mut cursor, rim)?;
82 let bytes = cursor.into_inner();
83 crate::trace_debug!(bytes_len = bytes.len(), "serialized rim to vec");
84 Ok(bytes)
85}