diff --git a/repak/src/entry.rs b/repak/src/entry.rs index f9a335e..95e2d28 100644 --- a/repak/src/entry.rs +++ b/repak/src/entry.rs @@ -135,98 +135,38 @@ impl Entry { version: super::Version, location: EntryLocation, ) -> Result<(), super::Error> { - if version >= super::Version::V10 && location == EntryLocation::Index { - let mut compression_block_size = (self.compression_block_size >> 11) & 0x3f; - if (compression_block_size << 11) != self.compression_block_size { - compression_block_size = 0x3f; - } - let compression_blocks_count = if self.compression.is_some() { - self.blocks.as_ref().unwrap().len() as u32 - } else { - 0 - }; - let is_size_32_bit_safe = self.compressed <= u32::MAX as u64; - let is_uncompressed_size_32_bit_safe = self.uncompressed <= u32::MAX as u64; - let is_offset_32_bit_safe = self.offset <= u32::MAX as u64; - - let flags = (compression_block_size) - | (compression_blocks_count << 6) - | ((self.is_encrypted() as u32) << 22) - | (self.compression.map_or(0, |n| n + 1) << 23) - | ((is_size_32_bit_safe as u32) << 29) - | ((is_uncompressed_size_32_bit_safe as u32) << 30) - | ((is_offset_32_bit_safe as u32) << 31); - - writer.write_u32::(flags)?; - - if compression_block_size == 0x3f { - writer.write_u32::(self.compression_block_size)?; - } - - if is_offset_32_bit_safe { - writer.write_u32::(self.offset as u32)?; - } else { - writer.write_u64::(self.offset)?; - } - - if is_uncompressed_size_32_bit_safe { - writer.write_u32::(self.uncompressed as u32)? - } else { - writer.write_u64::(self.uncompressed)? - } - - if self.compression.is_some() { - if is_size_32_bit_safe { - writer.write_u32::(self.compressed as u32)?; - } else { - writer.write_u64::(self.compressed)?; - } - - assert!(self.blocks.is_some()); - let blocks = self.blocks.as_ref().unwrap(); - if blocks.len() > 1 || self.is_encrypted() { - for b in blocks { - let block_size = b.end - b.start; - writer.write_u32::(block_size.try_into().unwrap())?; - } - } - } - - Ok(()) - } else { - writer.write_u64::(match location { - EntryLocation::Data => 0, - EntryLocation::Index => self.offset, - })?; - writer.write_u64::(self.compressed)?; - writer.write_u64::(self.uncompressed)?; - let compression = self.compression.map_or(0, |n| n + 1); - match version { - Version::V8A => writer.write_u8(compression.try_into().unwrap())?, - _ => writer.write_u32::(compression)?, - } - - if version.version_major() == VersionMajor::Initial { - writer.write_u64::(self.timestamp.unwrap_or_default())?; - } - if let Some(hash) = self.hash { - writer.write_all(&hash)?; - } else { - panic!("hash missing"); - } - if version.version_major() >= VersionMajor::CompressionEncryption { - if let Some(blocks) = &self.blocks { - writer.write_u32::(blocks.len() as u32)?; - for block in blocks { - block.write(writer)?; - } - } - writer.write_u8(self.flags)?; - writer.write_u32::(self.compression_block_size)?; - } - - Ok(()) + writer.write_u64::(match location { + EntryLocation::Data => 0, + EntryLocation::Index => self.offset, + })?; + writer.write_u64::(self.compressed)?; + writer.write_u64::(self.uncompressed)?; + let compression = self.compression.map_or(0, |n| n + 1); + match version { + Version::V8A => writer.write_u8(compression.try_into().unwrap())?, + _ => writer.write_u32::(compression)?, } + + if version.version_major() == VersionMajor::Initial { + writer.write_u64::(self.timestamp.unwrap_or_default())?; + } + if let Some(hash) = self.hash { + writer.write_all(&hash)?; + } else { + panic!("hash missing"); + } + if version.version_major() >= VersionMajor::CompressionEncryption { + if let Some(blocks) = &self.blocks { + writer.write_u32::(blocks.len() as u32)?; + for block in blocks { + block.write(writer)?; + } + } + writer.write_u8(self.flags)?; + writer.write_u32::(self.compression_block_size)?; + } + + Ok(()) } pub fn read_encoded( @@ -264,11 +204,7 @@ impl Entry { _ => var_int(29)?, }; - let offset_base = - match version.version_major() >= VersionMajor::RelativeChunkOffsets { - true => 0, - false => offset, - } + Entry::get_serialized_size(version, compression, compression_block_count); + let offset_base = Entry::get_serialized_size(version, compression, compression_block_count); let blocks = if compression_block_count == 1 && !encrypted { Some(vec![Block { @@ -310,6 +246,66 @@ impl Entry { }) } + pub fn write_encoded(&self, writer: &mut W) -> Result<(), super::Error> { + let mut compression_block_size = (self.compression_block_size >> 11) & 0x3f; + if (compression_block_size << 11) != self.compression_block_size { + compression_block_size = 0x3f; + } + let compression_blocks_count = if self.compression.is_some() { + self.blocks.as_ref().unwrap().len() as u32 + } else { + 0 + }; + let is_size_32_bit_safe = self.compressed <= u32::MAX as u64; + let is_uncompressed_size_32_bit_safe = self.uncompressed <= u32::MAX as u64; + let is_offset_32_bit_safe = self.offset <= u32::MAX as u64; + + let flags = (compression_block_size) + | (compression_blocks_count << 6) + | ((self.is_encrypted() as u32) << 22) + | (self.compression.map_or(0, |n| n + 1) << 23) + | ((is_size_32_bit_safe as u32) << 29) + | ((is_uncompressed_size_32_bit_safe as u32) << 30) + | ((is_offset_32_bit_safe as u32) << 31); + + writer.write_u32::(flags)?; + + if compression_block_size == 0x3f { + writer.write_u32::(self.compression_block_size)?; + } + + if is_offset_32_bit_safe { + writer.write_u32::(self.offset as u32)?; + } else { + writer.write_u64::(self.offset)?; + } + + if is_uncompressed_size_32_bit_safe { + writer.write_u32::(self.uncompressed as u32)? + } else { + writer.write_u64::(self.uncompressed)? + } + + if self.compression.is_some() { + if is_size_32_bit_safe { + writer.write_u32::(self.compressed as u32)?; + } else { + writer.write_u64::(self.compressed)?; + } + + assert!(self.blocks.is_some()); + let blocks = self.blocks.as_ref().unwrap(); + if blocks.len() > 1 || self.is_encrypted() { + for b in blocks { + let block_size = b.end - b.start; + writer.write_u32::(block_size.try_into().unwrap())?; + } + } + } + + Ok(()) + } + pub fn read_file( &self, reader: &mut R, diff --git a/repak/src/pak.rs b/repak/src/pak.rs index 14cd165..ace496e 100644 --- a/repak/src/pak.rs +++ b/repak/src/pak.rs @@ -371,11 +371,7 @@ impl Pak { let mut encoded_entries = io::Cursor::new(vec![]); for entry in self.index.entries.values() { offsets.push(encoded_entries.get_ref().len() as u32); - entry.write( - &mut encoded_entries, - self.version, - super::entry::EntryLocation::Index, - )?; + entry.write_encoded(&mut encoded_entries)?; } (encoded_entries.into_inner(), offsets) };