use crate::prelude::*;
use crate::util::bench::Stopwatch;
use crate::wad::chunk::ChunkName;
use crate::wad::data::Endianness;
use crate::wad::elements::GMChunk;
use crate::wad::serialize::builder::DataBuilder;
use crate::wad::serialize::builder::LastChunk;
impl DataBuilder<'_> {
pub fn write_chunk_name(&mut self, name: ChunkName) {
let mut bytes = name.as_bytes();
if self.gm_data.meta.endianness == Endianness::Big {
bytes.reverse();
}
self.write_bytes(&bytes);
}
pub fn build_chunk<T: GMChunk>(&mut self, element: &T) -> Result<()> {
let name: ChunkName = T::NAME;
if !element.exists() {
return Ok(());
}
let stopwatch = Stopwatch::start();
self.write_chunk_name(name);
self.write_u32(0xDEAD_C0DE); let start_pos: u32 = self.len();
let length_pos = start_pos - 4;
element
.serialize(self)
.with_context(|| format!("serializing chunk '{name}'"))?;
let padding_start_pos = self.len();
let ver = &self.gm_data.general_info.version;
if ver.major >= 2 || (ver.major == 1 && ver.build >= 9999) {
self.align(self.gm_data.meta.chunk_padding);
}
self.last_chunk = LastChunk { length_pos, padding_start_pos };
let chunk_length: u32 = self.len() - start_pos;
self.overwrite_u32(chunk_length, length_pos)
.expect("Chunk length overwrite position out of bounds");
log::trace!("Building chunk '{name}' took {stopwatch}");
Ok(())
}
pub fn remove_last_chunk_padding(&mut self) {
let last = self.last_chunk.clone();
let chunk_length = last.padding_start_pos - last.length_pos - 4;
self.raw_data.truncate(last.padding_start_pos as usize);
self.overwrite_u32(chunk_length, last.length_pos).unwrap();
}
}