### pub fn start(self) -> Result<(ZipEntryWriter<'archive, W>, ZipDataWriterConfig), Error> Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipFileBuilder.html?search= Marks the start of file data writing. Returns a tuple containing the entry writer and the data writer configuration. ```APIDOC ## pub fn start(self) -> Result<(ZipEntryWriter<'archive, W>, ZipDataWriterConfig), Error> ### Description Mark the start of file data. Returns a tuple where the entry handles the ZIP format and writes compressed data, and the config constructs data writers that handle uncompressed data and CRC32 calculation. ``` -------------------------------- ### start(self) -> Result<(ZipEntryWriter<'archive, W>, ZipDataWriterConfig), Error> Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipFileBuilder.html Marks the start of file data and returns the entry writer and data writer configuration. ```APIDOC ## start(self) -> Result<(ZipEntryWriter<'archive, W>, ZipDataWriterConfig), Error> ### Description Mark the start of file data. Returns a tuple containing an `entry` that handles the ZIP format and writes compressed data, and a `config` that constructs data writers for uncompressed data and CRC32 calculation. ``` -------------------------------- ### start Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipFileBuilder.html?search=u32+-%3E+bool Marks the start of file data and returns the necessary writers for handling ZIP format and data compression. ```APIDOC ## pub fn start(self) -> Result<(ZipEntryWriter<'archive, W>, ZipDataWriterConfig), Error> ### Description Marks the start of file data. Returns a tuple containing an `entry` that handles the ZIP format and writes compressed data, and a `config` that constructs data writers for uncompressed data and CRC32 calculation. ``` -------------------------------- ### Adding a Directory Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html Example of adding a directory entry to the archive with specific Unix permissions. ```rust archive.new_dir("my-dir/") .unix_permissions(0o755) .create()?; ``` -------------------------------- ### Start file data writing Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipFileBuilder.html?search= Demonstrates initializing a file entry and writing data using either stored or compressed formats. ```rust let (mut entry, config) = archive.new_file("file.txt").start().unwrap(); let mut writer = config.wrap(&mut entry); writer.write_all(b"Hello").unwrap(); let (_, output) = writer.finish().unwrap(); entry.finish(output).unwrap(); ``` ```rust let (mut entry, config) = archive.new_file("file.txt").start().unwrap(); let encoder = flate2::write::DeflateEncoder::new(&mut entry, flate2::Compression::default()); let mut writer = config.wrap(encoder); writer.write_all(b"Hello").unwrap(); let (encoder, output) = writer.finish().unwrap(); encoder.finish().unwrap(); entry.finish(output).unwrap(); ``` -------------------------------- ### Appending ZIP to existing data Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriterBuilder.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates using with_offset to create a ZIP archive that starts after existing prefix data in a stream. ```rust use std::io::{Cursor, Write, Seek, SeekFrom}; // Create a file with some prefix data let mut output = Cursor::new(Vec::new()); output.write_all(b"This is a custom header or prefix data\n").unwrap(); let zip_start_offset = output.position(); // Create ZIP archive starting after the prefix data let mut archive = rawzip::ZipArchiveWriter::builder() .with_offset(zip_start_offset) // Tell the archive where it starts .build(&mut output); // Add files normally let (mut file, config) = archive.new_file("data.txt").start().unwrap(); let mut writer = config.wrap(&mut file); writer.write_all(b"File content").unwrap(); let (_, desc) = writer.finish().unwrap(); file.finish(desc).unwrap(); archive.finish().unwrap(); // The resulting file contains both prefix data and the ZIP archive let final_data = output.into_inner(); assert!(final_data.starts_with(b"This is a custom header")); ``` -------------------------------- ### fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> Result<()> Source: https://docs.rs/rawzip/latest/rawzip/trait.ReaderAt.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Reads exactly enough bytes to fill the provided buffer starting at the specified offset. ```APIDOC ## fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> Result<()> ### Description Reads exactly enough bytes to fill the provided buffer starting at the specified offset. This is a sibling to read_exact, but operates at an offset. ### Parameters - **buf** (&mut [u8]) - The buffer to fill with data. - **offset** (u64) - The offset from the start of the data where the read should begin. ``` -------------------------------- ### fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> Result<()> Source: https://docs.rs/rawzip/latest/rawzip/trait.ReaderAt.html Reads exactly the number of bytes required to fill the provided buffer starting at the specified offset. ```APIDOC ## fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> Result<()> ### Description Reads exactly the number of bytes needed to fill the buffer at a specific offset. This is a provided method that acts as a sibling to read_exact. ### Parameters - **buf** (&mut [u8]) - The buffer to fill with data. - **offset** (u64) - The position from the start of the data to begin reading. ### Returns - **Result<()>** - Returns Ok(()) if the buffer was filled, or an error if the read failed or reached EOF prematurely. ``` -------------------------------- ### fn read_at(&self, buf: &mut [u8], offset: u64) -> Result Source: https://docs.rs/rawzip/latest/rawzip/trait.ReaderAt.html Reads bytes from the reader starting at the specified offset into the provided buffer. ```APIDOC ## fn read_at(&self, buf: &mut [u8], offset: u64) -> Result ### Description Reads bytes from the reader at a specific offset. This method is required for implementing the ReaderAt trait. ### Parameters - **buf** (&mut [u8]) - The buffer to read data into. - **offset** (u64) - The position from the start of the data to begin reading. ### Returns - **Result** - The number of bytes read, or an error if the operation fails. ``` -------------------------------- ### Adding a File with Configuration Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html Demonstrates adding a file with specific compression methods and Unix permissions. ```rust let (mut entry, config) = archive.new_file("my-file") .compression_method(rawzip::CompressionMethod::DEFLATE) .unix_permissions(0o644) .start()?; let mut writer = config.wrap(&mut entry); writer.write_all(b"Hello, world!")?; let (_, output) = writer.finish()?; entry.finish(output)?; ``` -------------------------------- ### Create EntryPath instances Source: https://docs.rs/rawzip/latest/rawzip/path/struct.EntryPath.html Use conformant for standard UTF-8 paths that require normalization, or verbatim for raw byte paths that should not be interpreted. ```rust use rawzip::path::EntryPath; // A UTF-8 path, normalized on write. let path = EntryPath::conformant("docs/readme.txt"); // Exact bytes, no normalization, no UTF-8 flag. let path = EntryPath::verbatim(b"odd\x05name"); ``` -------------------------------- ### Encryptor::get_mut Source: https://docs.rs/rawzip/latest/rawzip/zipcrypto/struct.Encryptor.html?search=std%3A%3Avec Gets a mutable reference to the underlying writer. ```APIDOC ## pub fn get_mut(&mut self) -> &mut W ### Description Gets a mutable reference to the underlying writer. Writing directly to it bypasses encryption, so use with care. ``` -------------------------------- ### Encryptor::get_ref Source: https://docs.rs/rawzip/latest/rawzip/zipcrypto/struct.Encryptor.html?search=std%3A%3Avec Gets a shared reference to the underlying writer. ```APIDOC ## pub fn get_ref(&self) -> &W ### Description Gets a shared reference to the underlying writer. ``` -------------------------------- ### Encrypting a ZIP Entry Source: https://docs.rs/rawzip/latest/rawzip/zipcrypto/struct.Encryptor.html?search=std%3A%3Avec Demonstrates how to initialize an Encryptor, wrap it with a deflater, and perform a full round-trip encryption and decryption cycle. ```rust let password = b"rawzipiscool"; let mut output = std::io::Cursor::new(Vec::new()); let mut archive = ZipArchiveWriter::new(&mut output); let (mut entry, config) = archive .new_file("test.txt") .compression_method(CompressionMethod::DEFLATE) .encrypted(true) .start()?; // In production these 11 bytes must come from a cryptographic RNG. let header_random = [0u8; 11]; // rawzip always writes a data descriptor, so the check byte is the high // byte of the DOS mod time. let check_byte = (entry.last_modified_dos().packed_time() >> 8) as u8; let encryptor = Encryptor::new(&mut entry, password, header_random, check_byte)?; let deflater = flate2::write::DeflateEncoder::new(encryptor, flate2::Compression::default()); let mut writer = config.wrap(deflater); writer.write_all(b"aaaaaaaaaaaaaaaa\n")?; let (deflater, descriptor) = writer.finish()?; deflater.finish()?; // drops the encryptor, releasing the borrow on `entry` entry.finish(descriptor)?; archive.finish()?; // Round-trips back through the reader. let zip = output.into_inner(); let archive = ZipArchive::from_slice(&zip)?; let entry = archive.entries().next().unwrap()?; let zip_entry = archive.get_entry(entry.wayfinder())?; let decryptor = Decryptor::new(zip_entry.data(), password)?; let inflater = flate2::read::DeflateDecoder::new(decryptor); let mut decoded = Vec::new(); zip_entry.verifying_reader(inflater).read_to_end(&mut decoded)?; assert_eq!(decoded, b"aaaaaaaaaaaaaaaa\n"); ``` -------------------------------- ### ZipLocator::locate_in_reader Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipLocator.html Locates the EOCD record in a reader starting from a specific offset. ```APIDOC ## pub fn locate_in_reader(&self, reader: R, buffer: &mut [u8], end_offset: u64) -> Result, (R, Error)> ### Description Locates the EOCD record in a reader, treating the specified end offset as the starting point for a backwards search. This is useful for concatenated archives or when the archive is not at the end of the reader. ``` -------------------------------- ### ZipEntry::compressed_data_range Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipEntry.html Returns the start and end byte offsets for the compressed data. ```APIDOC ## pub fn compressed_data_range(&self) -> (u64, u64) ### Description Returns a tuple of start and end byte offsets for the compressed data within the underlying reader. ``` -------------------------------- ### Basic Zip Archive Creation Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html Demonstrates the standard workflow for creating a new ZIP archive and adding a file to it. ```rust use std::io::Write; let mut output = std::io::Cursor::new(Vec::new()); let mut archive = rawzip::ZipArchiveWriter::new(&mut output); let (mut entry, config) = archive.new_file("file.txt").start().unwrap(); let mut writer = config.wrap(&mut entry); writer.write_all(b"Hello, world!").unwrap(); let (_, output) = writer.finish().unwrap(); entry.finish(output).unwrap(); archive.finish().unwrap(); ``` -------------------------------- ### Decrypting a ZipCrypto entry Source: https://docs.rs/rawzip/latest/rawzip/zipcrypto/struct.Decryptor.html Demonstrates how to initialize a Decryptor with a password and wrap it in a DeflateDecoder to read the decrypted, decompressed data. ```rust let data = std::fs::read("assets/zipcrypto.zip")?; let archive = ZipArchive::from_slice(&data)?; let entry = archive.entries().next().unwrap()?; let zip_entry = archive.get_entry(entry.wayfinder())?; let decryptor = Decryptor::new(zip_entry.data(), b"rawzipiscool")?; // Optionally, for a cheap up-front password check, use `check_byte`. Omitted from // the example for brevity. let inflater = flate2::read::DeflateDecoder::new(decryptor); // The verifying reader checks the decrypted data against the entry's CRC32. let mut output = Vec::new(); zip_entry.verifying_reader(inflater).read_to_end(&mut output)?; assert_eq!(output, b"aaaaaaaaaaaaaaaa\n"); ``` -------------------------------- ### Decryptor::new Source: https://docs.rs/rawzip/latest/rawzip/zipcrypto/struct.Decryptor.html?search= Creates a new Decryptor instance by wrapping a reader positioned at the start of an encrypted entry. ```APIDOC ## pub fn new(reader: R, password: &[u8]) -> Result ### Description Wraps a reader positioned at the start of an entry’s encrypted data, reading and decrypting the encryption header. ### Parameters - **reader** (R: Read) - The reader positioned at the start of the encrypted data. - **password** (&[u8]) - The password used for decryption. ### Returns - **Result** - A new Decryptor instance or an error if initialization fails. ``` -------------------------------- ### Create ZipArchive from a file Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchive.html Initializes a ZipArchive instance using a file and a provided buffer. ```rust let mut buffer = vec![0u8; RECOMMENDED_BUFFER_SIZE]; let archive = ZipArchive::from_file(file, &mut buffer)?; ``` -------------------------------- ### Decryptor::new Source: https://docs.rs/rawzip/latest/rawzip/zipcrypto/struct.Decryptor.html?search=u32+-%3E+bool Creates a new Decryptor instance by wrapping a reader positioned at the start of an encrypted entry. ```APIDOC ## pub fn new(reader: R, password: &[u8]) -> Result ### Description Wraps a reader positioned at the start of an entry’s encrypted data, reading and decrypting the encryption header. It is recommended to check `check_byte` afterwards for a password sanity test. ### Parameters - **reader** (R) - The reader positioned at the start of the encrypted data. - **password** (&[u8]) - The password used for decryption. ``` -------------------------------- ### Decryptor::new Source: https://docs.rs/rawzip/latest/rawzip/zipcrypto/struct.Decryptor.html Creates a new Decryptor instance by wrapping a reader positioned at the start of an encrypted entry. ```APIDOC ## pub fn new(reader: R, password: &[u8]) -> Result ### Description Wraps a reader positioned at the start of an entry’s encrypted data, reading and decrypting the encryption header. ### Parameters - **reader** (R: Read) - The reader containing the encrypted data. - **password** (&[u8]) - The password used for decryption. ### Returns - **Result** - A new Decryptor instance or an error if the header could not be read. ``` -------------------------------- ### Customizing ZipArchiveWriter with Builder Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html Shows how to use the builder pattern to configure the writer, such as setting initial capacity. ```rust use std::io::Write; let mut output = std::io::Cursor::new(Vec::::new()); let mut _archive = rawzip::ZipArchiveWriter::builder() .with_capacity(1000) // Optimize for 1000 anticipated files .build(&mut output); // ... add files as usual ``` -------------------------------- ### ZipArchiveWriterBuilder::with_offset Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriterBuilder.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Sets the starting offset for writing, which is useful when there is prelude data prior to the zip archive. ```APIDOC ### pub fn with_offset(self, offset: u64) -> Self Sets the starting offset for writing. Useful when there is prelude data prior to the zip archive. For zip64 archives, setting the correct offset is required. ``` -------------------------------- ### EntryPath::conformant Source: https://docs.rs/rawzip/latest/rawzip/path/struct.EntryPath.html Creates a normalized UTF-8 path, setting the UTF-8 flag in the ZIP header when necessary. ```APIDOC ### pub fn conformant>>(path: S) -> Self Creates a normalized UTF-8 path. This method ensures the path is treated as UTF-8 and sets the `EntryFlags::is_utf8` flag in the ZIP header when needed. ``` -------------------------------- ### ZipArchiveWriterBuilder::with_offset Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriterBuilder.html?search=u32+-%3E+bool Sets the starting offset for writing, useful when there is prelude data prior to the zip archive. ```APIDOC ## pub fn with_offset(self, offset: u64) -> Self ### Description Sets the starting offset for writing. Useful when there is prelude data prior to the zip archive. For zip64 archives, setting the correct offset is required. ``` -------------------------------- ### Decryptor::new Source: https://docs.rs/rawzip/latest/rawzip/zipcrypto/struct.Decryptor.html?search=std%3A%3Avec Creates a new Decryptor instance by wrapping a reader positioned at the start of an entry's encrypted data. ```APIDOC ## pub fn new(reader: R, password: &[u8]) -> Result ### Description Wraps a reader positioned at the start of an entry’s encrypted data, reading and decrypting the encryption header. ### Parameters - **reader** (R) - The reader containing the encrypted data. - **password** (&[u8]) - The password used for decryption. ### Returns - **Result** - A new Decryptor instance or an error if initialization fails. ``` -------------------------------- ### EntryPath::conformant Source: https://docs.rs/rawzip/latest/rawzip/path/struct.EntryPath.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates a normalized UTF-8 path, setting the UTF-8 flag when needed. ```APIDOC ## EntryPath::conformant ### Description Creates a normalized UTF-8 path, setting the `EntryFlags::is_utf8` flag when needed. ### Signature `pub fn conformant>>(path: S) -> Self` ``` -------------------------------- ### Accessing Raw and Normalized File Paths Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipFileHeaderRecord.html Demonstrates how to retrieve a raw file path and how to normalize it to a safe path using the alloc feature. ```rust // Get raw path (potentially unsafe) let raw_path = entry.file_path(); println!("Raw path bytes: {:?}", raw_path.as_ref()); ``` ```rust let safe_path = entry.file_path().try_normalize()?; println!("Safe path: {}", safe_path.as_ref()); ``` -------------------------------- ### Process a ZIP archive from a slice Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipSliceArchive.html Demonstrates how to initialize a ZipArchive from a byte slice and iterate through its entries. ```rust use rawzip::{ZipArchive, ZipSliceArchive, Error}; fn process_zip_slice(data: &[u8]) -> Result<(), Error> { let archive = ZipArchive::from_slice(data)?; println!("Found {} entries.", archive.entries_hint()); for entry_result in archive.entries() { let entry = entry_result?; println!("File: {:?}", entry.file_path().as_ref()); } Ok(()) } ``` -------------------------------- ### EntryPath::verbatim Source: https://docs.rs/rawzip/latest/rawzip/path/struct.EntryPath.html Creates an exact, uninterpreted path without the UTF-8 flag. ```APIDOC ### pub fn verbatim>>(path: B) -> Self Creates an exact, uninterpreted path. This method writes the provided bytes directly to the ZIP file name field without normalization or the UTF-8 flag. ``` -------------------------------- ### Processing concatenated archives Source: https://docs.rs/rawzip/latest/rawzip/guide/reading/index.html Shows how to locate and extract entries from multiple ZIP archives concatenated together by finding the start offset of the last archive. ```rust use rawzip::ZipLocator; // Two archives, back to back. let mut blob = one_file_zip("first.txt", b"from archive one"); blob.extend_from_slice(&one_file_zip("second.txt", b"from archive two")); // A plain locate finds the *last* archive. let last = ZipLocator::new().locate_in_slice(&blob).map_err(|(_, e)| e)?; let entry = last.entries().next_entry()?.expect("one entry"); assert_eq!(entry.file_path().try_normalize()?.as_ref(), "second.txt"); // Where does the last archive begin? let zip_start = last .entries() .into_iter() .filter_map(Result::ok) .map(|e| e.local_header_offset()) .min() .unwrap_or(0); // Re-scan everything before it to recover the previous archive. let prev = ZipLocator::new().locate_in_slice(&blob[..zip_start as usize]).map_err(|(_, e)| e)?; let entry = prev.entries().next_entry()?.expect("one entry"); assert_eq!(entry.file_path().try_normalize()?.as_ref(), "first.txt"); ``` -------------------------------- ### EntryPath::verbatim Source: https://docs.rs/rawzip/latest/rawzip/path/struct.EntryPath.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates an exact, uninterpreted path without the UTF-8 flag. ```APIDOC ## EntryPath::verbatim ### Description Creates an exact, uninterpreted path without the UTF-8 flag. ### Signature `pub fn verbatim>>(path: B) -> Self` ``` -------------------------------- ### ZipArchiveEntryWayfinder Size Hint Methods Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveEntryWayfinder.html?search=std%3A%3Avec Convenience methods to retrieve size hints without dealing with lifetime issues. ```rust pub fn uncompressed_size_hint(&self) -> u64 ``` ```rust pub fn compressed_size_hint(&self) -> u64 ``` -------------------------------- ### Reading Prelude Data with RangeReader Source: https://docs.rs/rawzip/latest/rawzip/struct.RangeReader.html?search=u32+-%3E+bool Demonstrates using RangeReader to read a specific byte range from a ZIP file's prelude. ```rust use std::io::Read; use rawzip::{ZipArchive, RangeReader, RECOMMENDED_BUFFER_SIZE}; use std::fs::File; let file = File::open("assets/test-prefix.zip")?; let mut buffer = vec![0u8; RECOMMENDED_BUFFER_SIZE]; let archive = ZipArchive::from_file(file, &mut buffer)?; // Typically you only need the first entry to find where the zip data starts // but this is the longer form that examines every entry in case they are // out of order let mut zip_start_offset = archive.directory_offset(); let mut entries = archive.entries(&mut buffer); while let Some(entry) = entries.next_entry()? { zip_start_offset = zip_start_offset.min(entry.local_header_offset()); } // For example purposes, just slurp up all the prelude data let mut prelude_reader = RangeReader::new(archive.get_ref(), 0..zip_start_offset); prelude_reader.read_exact(&mut buffer[..zip_start_offset as usize])?; assert_eq!( &buffer[..zip_start_offset as usize], b"prefix that could be an executable jar file" ); ``` -------------------------------- ### ZipArchiveWriterBuilder::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriterBuilder.html?search=u32+-%3E+bool Creates a new instance of ZipArchiveWriterBuilder. ```APIDOC ## pub fn new() -> Self ### Description Creates a new ZipArchiveWriterBuilder instance. ``` -------------------------------- ### ZipArchiveWriterBuilder::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriterBuilder.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates a new instance of ZipArchiveWriterBuilder. ```APIDOC ### pub fn new() -> Self Creates a new `ZipArchiveWriterBuilder`. ``` -------------------------------- ### VersionMadeBy Implementation Methods Source: https://docs.rs/rawzip/latest/rawzip/struct.VersionMadeBy.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Methods for interacting with the raw 16-bit value and extracting specific ZIP metadata. ```rust pub const fn from_raw(value: u16) -> Self ``` ```rust pub const fn creator_system(self) -> CreatorSystem ``` ```rust pub const fn zip_version(self) -> u8 ``` ```rust pub const fn as_u16(self) -> u16 ``` -------------------------------- ### Create ZipFilePath from bytes or string Source: https://docs.rs/rawzip/latest/rawzip/path/struct.ZipFilePath.html?search= Methods to instantiate a ZipFilePath from raw bytes or a UTF-8 string. ```rust pub fn from_bytes(data: &[u8]) -> ZipFilePath> ``` ```rust pub fn from_str(name: &str) -> ZipFilePath> ``` -------------------------------- ### Perform a Zip Archive Round-trip Source: https://docs.rs/rawzip/latest/rawzip/index.html Demonstrates writing a DEFLATE-compressed file to a Zip archive and reading it back, including path normalization and integrity verification. ```rust use std::io::Read; let data = b"Hello, world!"; // Create a new zip archive around a `Write` implementation. let mut output = Vec::new(); let mut archive = rawzip::ZipArchiveWriter::new(&mut output); // Declare the entry, then point your compressor at it. `config.wrap` tracks the // uncompressed size and CRC that the Zip data descriptor needs. let (mut entry, config) = archive.new_file("file.txt") .compression_method(rawzip::CompressionMethod::DEFLATE) .start()?; let encoder = flate2::write::DeflateEncoder::new(&mut entry, flate2::Compression::default()); let mut writer = config.wrap(encoder); std::io::copy(&mut &data[..], &mut writer)?; // Unwind the layers, then write the central directory. let (encoder, descriptor) = writer.finish()?; encoder.finish()?; entry.finish(descriptor)?; archive.finish()?; // --- It's reading time! --- We're reading from a slice for brevity let archive = rawzip::ZipArchive::from_slice(&output)?; let mut entries = archive.entries(); let entry = entries.next_entry()?.unwrap(); // Demonstrate normalizing file paths to avoid Zip Slip vulnerabilities. assert_eq!(entry.file_path().try_normalize()?.as_ref(), "file.txt"); assert_eq!(entry.compression_method(), rawzip::CompressionMethod::DEFLATE); // A wayfinder locates the entry's data within the archive. let local_entry = archive.get_entry(entry.wayfinder())?; let decompressor = flate2::bufread::DeflateDecoder::new(local_entry.data()); // A verifying reader checks the decompressed size and CRC as you read. let mut actual = Vec::new(); local_entry.verifying_reader(decompressor).read_to_end(&mut actual)?; assert_eq!(&data[..], actual); ``` -------------------------------- ### Iterate over ZIP archive entries Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchive.html Demonstrates how to iterate through entries in the central directory using a mutable buffer. ```rust fn example(file: File) -> Result<(), Error> { let mut buffer = vec![0u8; RECOMMENDED_BUFFER_SIZE]; let archive = ZipArchive::from_file(file, &mut buffer)?; let entries_hint = archive.entries_hint(); let mut actual_entries = 0; let mut entries_iterator = archive.entries(&mut buffer); while let Some(_) = entries_iterator.next_entry()? { actual_entries += 1; } println!("Found {} entries (hint: {})", actual_entries, entries_hint); Ok(()) } ``` -------------------------------- ### pub fn uncompressed_size_hint(&self) -> u64 Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveEntryWayfinder.html?search=u32+-%3E+bool Returns the uncompressed size hint for the Zip entry. This is a convenience method to avoid lifetime issues. ```APIDOC ## pub fn uncompressed_size_hint(&self) -> u64 ### Description Returns the uncompressed size hint for the Zip entry. This is a convenience method to avoid having to deal with lifetime issues on a ZipFileHeaderRecord. ### Returns - **u64** - The uncompressed size hint. ``` -------------------------------- ### ZipArchive::from_file Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchive.html?search= Creates a new ZipArchive instance from a file source using a provided buffer. ```APIDOC ## ZipArchive::from_file ### Description Creates a new ZipArchive instance from a file. This method requires the 'std' feature to be enabled. ### Signature `pub fn from_file(reader: R, buffer: &mut [u8]) -> Result, Error>` ### Parameters - **reader** (R) - The file or source implementing Read and Seek traits. - **buffer** (&mut [u8]) - A mutable slice used as a buffer for reading operations. ### Example ```rust let mut buffer = vec![0u8; RECOMMENDED_BUFFER_SIZE]; let archive = ZipArchive::from_file(file, &mut buffer)?; ``` ``` -------------------------------- ### Define EntryPath Structure Source: https://docs.rs/rawzip/latest/rawzip/path/struct.EntryPath.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E The internal structure definition for EntryPath. ```rust pub struct EntryPath<'a>(/* private fields */); ``` -------------------------------- ### Check path properties Source: https://docs.rs/rawzip/latest/rawzip/path/struct.ZipFilePath.html?search= Methods to inspect the state of the path. ```rust pub fn is_dir(&self) -> bool ``` ```rust pub fn len(&self) -> usize ``` ```rust pub fn is_empty(&self) -> bool ``` -------------------------------- ### ZipArchive::from_file Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchive.html Creates a new ZipArchive instance from a file. Requires the 'std' feature. ```APIDOC ## ZipArchive::from_file ### Description Creates a new ZipArchive instance from a file. This method requires the 'std' feature enabled. ### Signature pub fn from_file(reader: R, buffer: &mut [u8]) -> Result, ZipError> ``` -------------------------------- ### ZipStr::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipStr.html?search= Creates a new ZipStr instance from a byte slice. ```APIDOC ## pub fn new(data: &'a [u8]) -> Self ### Description Creates a new `ZipStr` from a byte slice. ### Parameters - **data** (&'a [u8]) - The byte slice containing the text data. ``` -------------------------------- ### ZipStr::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipStr.html?search=u32+-%3E+bool Creates a new ZipStr instance from a byte slice. ```APIDOC ## pub fn new(data: &'a [u8]) -> Self ### Description Creates a new `ZipStr` from a byte slice. ### Parameters - **data** (&'a [u8]) - Required - The byte slice containing the text data. ``` -------------------------------- ### Handle raw paths Source: https://docs.rs/rawzip/latest/rawzip/path/struct.ZipFilePath.html?search= Methods for interacting with unvalidated raw paths. ```rust pub fn as_bytes(&self) -> &'a [u8] ⓘ ``` ```rust pub fn try_normalize(self) -> Result>, Error> ``` -------------------------------- ### ZipFilePath::from_str Source: https://docs.rs/rawzip/latest/rawzip/path/struct.ZipFilePath.html Creates a normalized path from a UTF-8 string. ```APIDOC ## pub fn from_str(name: &str) -> ZipFilePath> ### Description Creates a normalized path from a UTF-8 string. The path is automatically normalized according to internal rules. ### Parameters - **name** (&str) - Required - The UTF-8 string to convert into a normalized path. ``` -------------------------------- ### ZipFilePath::from_str Source: https://docs.rs/rawzip/latest/rawzip/path/struct.ZipFilePath.html?search=std%3A%3Avec Creates a normalized path from a UTF-8 string. ```APIDOC ## pub fn from_str(name: &str) -> ZipFilePath> ### Description Creates a normalized path from a UTF-8 string. The path is automatically normalized according to library rules. ### Parameters - **name** (&str) - Required - The UTF-8 string path. ``` -------------------------------- ### Write stored file data with ZipFileBuilder Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipFileBuilder.html Demonstrates writing uncompressed data to a ZIP archive entry. ```rust let (mut entry, config) = archive.new_file("file.txt").start().unwrap(); let mut writer = config.wrap(&mut entry); writer.write_all(b"Hello").unwrap(); let (_, output) = writer.finish().unwrap(); entry.finish(output).unwrap(); ``` -------------------------------- ### Copying Modification Times in Rust Source: https://docs.rs/rawzip/latest/rawzip/time/index.html Demonstrates reading a ZIP archive and writing a new one while preserving modification times. It handles both UTC and local time variants by converting local timestamps to UTC. ```rust use rawzip::{ZipArchive, ZipArchiveWriter, ZipDataWriter}; use rawzip::time::{ZipDateTimeKind, UtcDateTime}; use std::io::Write; // Read a test ZIP file with timestamps let input_data = include_bytes!("../assets/time-go.zip"); let input_archive = ZipArchive::from_slice(input_data).unwrap(); // Create output archive let mut output_data = Vec::new(); let mut output_archive = ZipArchiveWriter::new(&mut output_data); // Copy each entry with its modification time let mut entries = input_archive.entries(); while let Ok(Some(entry)) = entries.next_entry() { let name = entry.file_path().try_normalize().unwrap().as_ref().to_string(); let modification_time = entry.last_modified(); let utc_time = match modification_time { ZipDateTimeKind::Utc(utc_time) => utc_time, ZipDateTimeKind::Local(local_time) => { // Convert local time to UTC by reinterpreting the components // This treats the local time as if it were UTC UtcDateTime::from_components( local_time.year(), local_time.month(), local_time.day(), local_time.hour(), local_time.minute(), local_time.second(), local_time.nanosecond() ).unwrap() } }; if !entry.is_dir() { // Copy file with preserved modification time let (mut entry, config) = output_archive.new_file(&name) .last_modified(utc_time) .start() .unwrap(); let mut writer = config.wrap(&mut entry); writer.write_all(b"example data").unwrap(); let (_, descriptor) = writer.finish().unwrap(); entry.finish(descriptor).unwrap(); } else { // Copy directory with preserved modification time output_archive.new_dir(&name) .last_modified(utc_time) .create() .unwrap(); } } output_archive.finish().unwrap(); // Verify the output archive preserves timestamps let output_archive = ZipArchive::from_slice(&output_data).unwrap(); assert!(output_archive.entries_hint() > 0, "Output should contain entries"); // Verify at least one entry has a UTC timestamp let mut output_entries = output_archive.entries(); let mut has_utc_timestamp = false; while let Ok(Some(entry)) = output_entries.next_entry() { if matches!(entry.last_modified(), ZipDateTimeKind::Utc(_)) { has_utc_timestamp = true; break; } } assert!(has_utc_timestamp, "Output should contain UTC timestamps"); ``` -------------------------------- ### Write deflate compressed file data with ZipFileBuilder Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipFileBuilder.html Demonstrates writing compressed data to a ZIP archive entry using the flate2 crate. ```rust let (mut entry, config) = archive.new_file("file.txt").start().unwrap(); let encoder = flate2::write::DeflateEncoder::new(&mut entry, flate2::Compression::default()); let mut writer = config.wrap(encoder); writer.write_all(b"Hello").unwrap(); let (encoder, output) = writer.finish().unwrap(); encoder.finish().unwrap(); entry.finish(output).unwrap(); ``` -------------------------------- ### Adding extra fields to ZipFileBuilder Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipFileBuilder.html?search= Demonstrates how to add custom extra fields to local file headers, the central directory, or both. ```rust let mut output = Cursor::new(Vec::new()); let mut archive = ZipArchiveWriter::new(&mut output); let my_custom_field = ExtraFieldId::new(0x6666); // File with extra fields only in the local file header let (mut local_file, config) = archive.new_file("video.mp4") .extra_field(my_custom_field, b"field1", Header::LOCAL)? .start()?; let mut writer = config.wrap(&mut local_file); writer.write_all(b"video data")?; let (_, desc) = writer.finish()?; local_file.finish(desc)?; // File with extra fields only in the central directory let (mut central_file, config) = archive.new_file("document.pdf") .extra_field(my_custom_field, b"field2", Header::CENTRAL)? .start()?; let mut writer = config.wrap(&mut central_file); writer.write_all(b"PDF content")?; let (_, desc) = writer.finish()?; central_file.finish(desc)?; // File with extra fields in both headers for maximum compatibility assert_eq!(Header::default(), Header::LOCAL | Header::CENTRAL); let (mut both_file, config) = archive.new_file("important.dat") .extra_field(my_custom_field, b"field3", Header::default())? .start()?; let mut writer = config.wrap(&mut both_file); writer.write_all(b"important data")?; let (_, desc) = writer.finish()?; both_file.finish(desc)?; archive.finish()?; // Verify the behavior when reading back the central directory let zip_data = output.into_inner(); let archive = ZipArchive::from_slice(&zip_data)?; for entry_result in archive.entries() { let entry = entry_result?; // Find our custom field in the central directory let custom_field_data = entry.extra_fields() .find(|(id, _)| *id == my_custom_field) .map(|(_, data)| data); match entry.file_path().as_ref() { b"video.mp4" => { // local only field should not be in central directory assert_eq!(custom_field_data, None); } b"document.pdf" => { // central only field should be in central directory assert_eq!(custom_field_data, Some(b"field2".as_slice())); } b"important.dat" => { // both location field should be in central directory assert_eq!(custom_field_data, Some(b"field3".as_slice())); } _ => {} } } ``` -------------------------------- ### ZipDirBuilder::create Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipDirBuilder.html?search=u32+-%3E+bool Creates the directory entry. ```APIDOC ### pub fn create(self) -> Result Creates the directory entry in the ZIP archive. ``` -------------------------------- ### Read local file header from ZipEntry Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipEntry.html Demonstrates how to retrieve the local file header for a ZipEntry using a provided buffer, allowing access to file paths and extra fields that may differ from the central directory. ```rust // Test with filename mismatch test fixture let file = File::open("assets/filename_mismatch_test.zip")?; let mut buf = vec![0u8; RECOMMENDED_BUFFER_SIZE]; let archive = ZipArchive::from_file(file, &mut buf)?; let mut entries = archive.entries(&mut buf); let entry_header = entries.next_entry()?.unwrap(); // Central directory shows one filename assert_eq!(entry_header.file_path().as_ref(), b"malware.exe"); let wayfinder = entry_header.wayfinder(); let entry = archive.get_entry(wayfinder)?; // Read the local header let mut local_buffer = vec![0u8; 1024]; let local_header = entry.local_header(&mut local_buffer)?; // Local header shows different filename assert_eq!(local_header.file_path().as_ref(), b"safe_file.txt"); // Access extra fields from local header let mut found_fields = 0; for (field_id, _data) in local_header.extra_fields() { found_fields += 1; // Could check for specific extra field types here println!("Found extra field: {:04x}", field_id.as_u16()); } ``` -------------------------------- ### Normalize ZIP archive paths Source: https://docs.rs/rawzip/latest/rawzip/path/index.html?search=std%3A%3Avec Demonstrates converting raw bytes or strings into normalized, safe paths using ZipFilePath. ```rust use rawzip::path::ZipFilePath; // From raw bytes let raw_path = ZipFilePath::from_bytes(b"../../../etc/passwd"); let safe_path = raw_path.try_normalize()?; // Returns error if invalid UTF-8 assert_eq!(safe_path.as_str(), "etc/passwd"); // From string let normalized_path = ZipFilePath::from_str("dir\\file.txt"); assert_eq!(normalized_path.as_str(), "dir/file.txt"); assert_eq!(String::from(normalized_path), "dir/file.txt"); // Backslashes to forward slashes let path = ZipFilePath::from_str("dir\\subdir\\file.txt"); assert_eq!(path.as_str(), "dir/subdir/file.txt"); // Remove redundant slashes let path = ZipFilePath::from_str("dir//subdir///file.txt"); assert_eq!(path.as_str(), "dir/subdir/file.txt"); // Resolve relative components let path = ZipFilePath::from_str("dir/../file.txt"); assert_eq!(path.as_str(), "file.txt"); // Remove leading slashes (absolute -> relative) let path = ZipFilePath::from_str("/etc/passwd"); assert_eq!(path.as_str(), "etc/passwd"); // Prevent directory traversal let path = ZipFilePath::from_str("../../../etc/passwd"); assert_eq!(path.as_str(), "etc/passwd"); // Get string from normalized path let path = ZipFilePath::from_str("dir/file.txt"); let my_str = String::from(path.into_owned()); assert_eq!(my_str, String::from("dir/file.txt")); ``` -------------------------------- ### Access EntryFlags methods Source: https://docs.rs/rawzip/latest/rawzip/struct.EntryFlags.html?search=u32+-%3E+bool Methods for inspecting specific bits within the ZIP entry flags. ```rust pub const fn bits(self) -> u16 ``` ```rust pub const fn is_encrypted(self) -> bool ``` ```rust pub const fn has_data_descriptor(self) -> bool ``` ```rust pub const fn has_strong_encryption(self) -> bool ``` ```rust pub const fn is_utf8(self) -> bool ``` ```rust pub const fn is_masked(self) -> bool ``` -------------------------------- ### RangeReader Methods Source: https://docs.rs/rawzip/latest/rawzip/struct.RangeReader.html?search=std%3A%3Avec Core methods for initializing and interacting with a RangeReader instance. ```APIDOC ## pub fn new(archive: R, range: Range) -> Self ### Description Creates a new `RangeReader` that will read data from the specified range. ## pub fn position(&self) -> u64 ### Description Returns the current read position within the range. ## pub fn remaining(&self) -> u64 ### Description Returns the remaining bytes that are expected to be read from the current position. ## pub fn end_offset(&self) -> u64 ### Description Returns the end offset of the range. ## pub fn get_ref(&self) -> &R ### Description Returns a reference to the underlying reader. ## pub fn into_inner(self) -> R ### Description Consumes the self and returns the underlying reader. ``` -------------------------------- ### ZipFilePath::from_str Source: https://docs.rs/rawzip/latest/rawzip/path/struct.ZipFilePath.html?search=u32+-%3E+bool Creates a normalized path from a UTF-8 string, applying automatic normalization rules. ```APIDOC ## pub fn from_str(name: &str) -> ZipFilePath> ### Description Creates a normalized path from a UTF-8 string. The path is automatically normalized according to library rules. ### Parameters - **name** (&str) - Required - The string representation of the path. ``` -------------------------------- ### ZipArchiveWriter::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html Creates a new ZipArchiveWriter instance that writes to the provided writer. ```APIDOC ## pub fn new(writer: W) -> Self ### Description Creates a new ZipArchiveWriter that writes to the specified writer. ### Parameters - **writer** (W) - The underlying writer to which the ZIP archive will be written. ``` -------------------------------- ### ZipArchiveWriter::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html?search= Creates a new ZipArchiveWriter instance that writes to the provided writer. ```APIDOC ## pub fn new(writer: W) -> Self ### Description Creates a new ZipArchiveWriter that writes to the specified writer. ### Signature `pub fn new(writer: W) -> Self` ``` -------------------------------- ### ZipArchiveWriter::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates a new ZipArchiveWriter instance that writes to the provided writer. ```APIDOC ### pub fn new(writer: W) -> Self Creates a new `ZipArchiveWriter` that writes to the provided `writer`. ``` -------------------------------- ### ZipArchiveWriter::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html?search=u32+-%3E+bool Creates a new ZipArchiveWriter instance that writes to the provided writer. ```APIDOC ## pub fn new(writer: W) -> Self ### Description Creates a new ZipArchiveWriter that writes to the specified writer. ### Parameters - **writer** (W) - The underlying writer to which the ZIP archive data will be written. ``` -------------------------------- ### ZipArchiveWriter::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html?search=std%3A%3Avec Creates a new ZipArchiveWriter instance that writes to the provided writer. ```APIDOC ### pub fn new(writer: W) -> Self Creates a new `ZipArchiveWriter` that writes to `writer`. ``` -------------------------------- ### ZipLocator::new Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipLocator.html Creates a new ZipLocator instance with a default maximum search space of 1 MiB. ```APIDOC ## pub fn new() ### Description Creates a new `ZipLocator` with a default maximum search space of 1 MiB. ``` -------------------------------- ### RECOMMENDED_BUFFER_SIZE Source: https://docs.rs/rawzip/latest/rawzip/constant.RECOMMENDED_BUFFER_SIZE.html?search=std%3A%3Avec The RECOMMENDED_BUFFER_SIZE constant provides a suggested buffer size for reading from a zip file, based on the zip specification recommendation of 65,535 bytes. ```APIDOC ## RECOMMENDED_BUFFER_SIZE ### Description The recommended buffer size to use when reading from a zip file. A buffer of this size should hold an entire central directory record as the spec recommends (4.4.10). ### Definition `pub const RECOMMENDED_BUFFER_SIZE: usize = 65_536;` ### Usage Note While this size is recommended, a pathological central directory record can still exceed this size, potentially causing `ErrorKind::BufferTooSmall`. In such cases, `MAX_CENTRAL_DIRECTORY_RECORD_SIZE` may be used to avoid the error. ``` -------------------------------- ### Calculate CRC32 incrementally Source: https://docs.rs/rawzip/latest/rawzip/struct.Crc32.html Demonstrates initializing a Crc32 accumulator, updating it with multiple byte slices, and retrieving the final checksum. ```rust let mut crc = Crc32::new(); crc.update(b"Hello, "); crc.update(b"world!"); assert_eq!(crc.checksum(), rawzip::crc32(b"Hello, world!")); ``` -------------------------------- ### EntryMode::permissions Source: https://docs.rs/rawzip/latest/rawzip/struct.EntryMode.html?search=u32+-%3E+bool Retrieves the Unix permission bits for the zip entry. ```APIDOC ### pub const fn permissions(&self) -> u32 Returns the Unix permission bits (e.g., 0o755). ``` -------------------------------- ### Handle normalized paths Source: https://docs.rs/rawzip/latest/rawzip/path/struct.ZipFilePath.html?search= Methods for interacting with validated normalized paths. ```rust pub fn as_str(&self) -> &str ``` ```rust pub fn into_owned(self) -> ZipFilePath ``` -------------------------------- ### Encryptor::new Source: https://docs.rs/rawzip/latest/rawzip/zipcrypto/struct.Encryptor.html Creates a new Encryptor instance, wrapping a writer and emitting the required 12-byte encryption header. ```APIDOC ## pub fn new(writer: W, password: &[u8], header_random: [u8; 11], check_byte: u8) -> Result ### Description Wraps a writer positioned at the start of an entry’s body, emitting the encrypted 12-byte encryption header. The `header_random` bytes should be drawn from a cryptographic RNG to prevent information leakage. ### Parameters - **writer** (W) - The underlying writer to wrap. - **password** (&[u8]) - The password used for encryption. - **header_random** ([u8; 11]) - 11 random bytes for the encryption header. - **check_byte** (u8) - The password verifier byte (typically the high byte of the CRC32 or DOS mod time). ``` -------------------------------- ### Tracking Stream Offsets Source: https://docs.rs/rawzip/latest/rawzip/struct.ZipArchiveWriter.html Illustrates how to use stream_offset to monitor the position within the archive during file creation. ```rust use std::io::Write; let mut output = std::io::Cursor::new(Vec::new()); let mut archive = rawzip::ZipArchiveWriter::new(&mut output); // 1. Get local header offset let local_header_offset = archive.stream_offset(); let (mut file, config) = archive.new_file("test.txt").start().unwrap(); // 2. Get start of data offset let data_start_offset = file.stream_offset(); // Write some data let mut writer = config.wrap(&mut file); writer.write_all(b"Hello World").unwrap(); let (_, desc) = writer.finish().unwrap(); // 3. Get end of compressed data offset let end_data_offset = file.stream_offset(); let written_entry = file.finish(desc).unwrap(); // 4. Get end of data descriptor offset (next file's local header offset) let end_descriptor_offset = archive.stream_offset(); archive.finish().unwrap(); assert_eq!(local_header_offset, 0); assert!(data_start_offset > local_header_offset); assert_eq!(end_data_offset, data_start_offset + b"Hello World".len() as u64); assert_eq!(end_descriptor_offset, end_data_offset + 16); // 16 bytes for data descriptor assert_eq!(written_entry.compressed_size(), end_data_offset - data_start_offset); ```