an efficient binary archive format
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix writer close

zach 4afbaa6b 37292c88

+29 -13
+3 -3
include/bindle.h
··· 13 13 #include <stdbool.h> 14 14 15 15 typedef enum BindleCompress { 16 - BindleCompressNone, 17 - BindleCompressZstd, 18 - BindleCompressAuto, 16 + BindleCompressNone = 0, 17 + BindleCompressZstd = 1, 18 + BindleCompressAuto = 2, 19 19 } BindleCompress; 20 20 21 21 typedef struct Bindle Bindle;
+26 -10
src/lib.rs
··· 36 36 #[repr(C)] 37 37 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] 38 38 pub enum Compress { 39 - None, 40 - Zstd, 39 + None = 0, 40 + Zstd = 1, 41 41 #[default] 42 - Auto, 42 + Auto = 2, 43 43 } 44 44 45 45 #[repr(C, packed)] ··· 156 156 157 157 impl<'a> Writer<'a> { 158 158 pub fn write_chunk(&mut self, data: &[u8]) -> io::Result<()> { 159 + if self.name.is_empty() { 160 + return Err(std::io::Error::new(std::io::ErrorKind::Other, "closed")); 161 + } 162 + 159 163 self.uncompressed_size += data.len() as u64; 160 164 161 165 if let Some(encoder) = &mut self.encoder { ··· 168 172 } 169 173 170 174 fn close_drop(&mut self) -> io::Result<()> { 171 - let compression_type = if let Some(encoder) = self.encoder.take() { 172 - encoder.finish()?; 173 - 1 175 + if self.name.is_empty() { 176 + return Ok(()); 177 + } 178 + 179 + let (compression_type, current_pos) = if let Some(encoder) = self.encoder.take() { 180 + let mut f = encoder.finish()?; 181 + let pos = f.stream_position()?; 182 + // Sync the main file handle to match the encoder's position 183 + self.bindle.file.seek(SeekFrom::Start(pos))?; 184 + (1, pos) 174 185 } else { 175 - 0 186 + let pos = self.bindle.file.stream_position()?; 187 + (0, pos) 176 188 }; 177 189 178 - let current_pos = self.bindle.file.stream_position()?; 179 190 let compressed_size = current_pos - self.start_offset; 180 191 181 192 // Handle 8-byte alignment padding ··· 196 207 }; 197 208 198 209 self.bindle.index.insert(self.name.clone(), entry); 210 + self.name.clear(); // Mark as closed 199 211 Ok(()) 200 212 } 201 213 ··· 447 459 pub fn read<'a>(&'a self, name: &str) -> Option<Cow<'a, [u8]>> { 448 460 let entry = self.index.get(name)?; 449 461 let mmap = self.mmap.as_ref()?; 450 - let data = 451 - mmap.get(entry.offset() as usize..(entry.offset() + entry.compressed_size()) as usize)?; 452 462 453 463 if entry.compression_type == Compress::Zstd as u8 { 464 + let data = mmap.get( 465 + entry.offset() as usize..(entry.offset() + entry.compressed_size()) as usize, 466 + )?; 454 467 let mut out = Vec::with_capacity(entry.uncompressed_size() as usize); 455 468 zstd::Decoder::new(data).ok()?.read_to_end(&mut out).ok()?; 456 469 Some(Cow::Owned(out)) 457 470 } else { 471 + let data = mmap.get( 472 + entry.offset() as usize..(entry.offset() + entry.uncompressed_size()) as usize, 473 + )?; 458 474 Some(Cow::Borrowed(data)) 459 475 } 460 476 }