Struct stream_unpack::zip::ZipUnpacker
source · pub struct ZipUnpacker<'a> { /* private fields */ }Expand description
A stream unpacker for ZIP archives
Implementations§
source§impl<'a> ZipUnpacker<'a>
impl<'a> ZipUnpacker<'a>
sourcepub fn new(
central_directory: SortedCentralDirectory,
disk_sizes: Vec<usize>,
on_decode: impl Fn(ZipDecodedData<'_>) -> Result<()> + 'a
) -> Self
pub fn new( central_directory: SortedCentralDirectory, disk_sizes: Vec<usize>, on_decode: impl Fn(ZipDecodedData<'_>) -> Result<()> + 'a ) -> Self
Creates a new ZipUnpacker
Callback on_decode will fire when the unpacker decodes new data
The easiest way to obtain a central directory object is to use read_cd::from_provider. “disk_sizes” must only contain one element if the archive is a cut one, and not a real split one.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
fn main() {
let output_dir = "unpack";
let archive = fs::read("archive.zip").unwrap();
let _ = fs::remove_dir_all(output_dir);
let central_directory = read_cd::from_provider(
vec![archive.len()],
false,
|pos, length| {
println!("Requested {length} bytes at {pos}");
Ok(archive[(pos.offset)..(pos.offset + length)].to_owned())
}
).unwrap().sort();
let current_file: RefCell<Option<File>> = RefCell::new(None);
let mut unpacker = ZipUnpacker::new(central_directory, vec![archive.len()], |data| {
match data {
ZipDecodedData::FileHeader(cdfh, _) => {
println!();
let mut path = PathBuf::from(output_dir);
path.push(&cdfh.filename);
if !cdfh.is_directory() {
print!("New file: {}", cdfh.filename);
io::stdout().flush()?;
fs::create_dir_all(path.parent().unwrap())?;
*current_file.borrow_mut() = Some(
OpenOptions::new()
.create(true)
.write(true)
.open(path)?
);
} else {
print!("New directory: {}", cdfh.filename);
io::stdout().flush()?;
fs::create_dir_all(path)?;
}
},
ZipDecodedData::FileData(data) => {
print!(".");
io::stdout().flush()?;
current_file.borrow().as_ref().unwrap().write_all(data)?;
}
}
Ok(())
});
unpacker.update(archive).unwrap();
println!("\nDone!");
}More examples
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
fn main() {
let output_dir = "unpack";
let archives = [
"multipart/archive_m.z01",
"multipart/archive_m.z02",
"multipart/archive_m.z03",
"multipart/archive_m.z04",
"multipart/archive_m.z05",
"multipart/archive_m.z06",
"multipart/archive_m.z07",
"multipart/archive_m.zip"
].map(fs::read).map(Result::unwrap);
let sizes = archives.iter().map(Vec::len).collect::<Vec<_>>();
let _ = fs::remove_dir_all(output_dir);
let central_directory = read_cd::from_provider(
&sizes,
false,
|pos, length| {
println!("Requested {length} bytes at {pos}");
Ok(archives[pos.disk][(pos.offset)..(pos.offset + length)].to_owned())
}
).unwrap().sort();
let current_file: RefCell<Option<File>> = RefCell::new(None);
let mut unpacker = ZipUnpacker::new(central_directory, sizes, |data| {
match data {
ZipDecodedData::FileHeader(cdfh, _) => {
println!();
let mut path = PathBuf::from(output_dir);
path.push(&cdfh.filename);
if !cdfh.is_directory() {
print!("New file: {}", cdfh.filename);
io::stdout().flush()?;
fs::create_dir_all(path.parent().unwrap())?;
*current_file.borrow_mut() = Some(
OpenOptions::new()
.create(true)
.write(true)
.open(path)?
);
} else {
print!("New directory: {}", cdfh.filename);
io::stdout().flush()?;
fs::create_dir_all(path)?;
}
},
ZipDecodedData::FileData(data) => {
print!(".");
io::stdout().flush()?;
current_file.borrow().as_ref().unwrap().write_all(data)?;
}
}
Ok(())
});
for archive in archives {
unpacker.update(archive).unwrap();
}
println!("\nDone!");
}sourcepub fn resume(
central_directory: SortedCentralDirectory,
disk_sizes: Vec<usize>,
position: ZipPosition,
on_decode: impl Fn(ZipDecodedData<'_>) -> Result<()> + 'a
) -> Result<Self, DecoderError>
pub fn resume( central_directory: SortedCentralDirectory, disk_sizes: Vec<usize>, position: ZipPosition, on_decode: impl Fn(ZipDecodedData<'_>) -> Result<()> + 'a ) -> Result<Self, DecoderError>
Creates a new ZipUnpacker, starting from the specified position. If the archive is not actually split, you must set disk number to 0 and use the absolute offset, even if there are multiple files
Callback on_decode will fire when the unpacker decodes new data
The easiest way to obtain a central directory object is to use read_cd::from_provider. “disk_sizes” must only contain one element if the archive is a cut one, and not a real split one.
sourcepub fn update(
&mut self,
data: impl AsRef<[u8]>
) -> Result<(usize, bool), DecoderError>
pub fn update( &mut self, data: impl AsRef<[u8]> ) -> Result<(usize, bool), DecoderError>
Update this ZipUnpacker with new bytes. The callback may or may not be fired, depending on the content. The callback may be fired multiple times.
The first return value is how much the caller should advance the input buffer (0 means that there wasn’t enough data in the buffer and the caller should provide more), and the second value determines whether all files were processed (which means that the caller should stop providing data)
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
fn main() {
let output_dir = "unpack";
let archive = fs::read("archive.zip").unwrap();
let _ = fs::remove_dir_all(output_dir);
let central_directory = read_cd::from_provider(
vec![archive.len()],
false,
|pos, length| {
println!("Requested {length} bytes at {pos}");
Ok(archive[(pos.offset)..(pos.offset + length)].to_owned())
}
).unwrap().sort();
let current_file: RefCell<Option<File>> = RefCell::new(None);
let mut unpacker = ZipUnpacker::new(central_directory, vec![archive.len()], |data| {
match data {
ZipDecodedData::FileHeader(cdfh, _) => {
println!();
let mut path = PathBuf::from(output_dir);
path.push(&cdfh.filename);
if !cdfh.is_directory() {
print!("New file: {}", cdfh.filename);
io::stdout().flush()?;
fs::create_dir_all(path.parent().unwrap())?;
*current_file.borrow_mut() = Some(
OpenOptions::new()
.create(true)
.write(true)
.open(path)?
);
} else {
print!("New directory: {}", cdfh.filename);
io::stdout().flush()?;
fs::create_dir_all(path)?;
}
},
ZipDecodedData::FileData(data) => {
print!(".");
io::stdout().flush()?;
current_file.borrow().as_ref().unwrap().write_all(data)?;
}
}
Ok(())
});
unpacker.update(archive).unwrap();
println!("\nDone!");
}More examples
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
fn main() {
let output_dir = "unpack";
let archives = [
"multipart/archive_m.z01",
"multipart/archive_m.z02",
"multipart/archive_m.z03",
"multipart/archive_m.z04",
"multipart/archive_m.z05",
"multipart/archive_m.z06",
"multipart/archive_m.z07",
"multipart/archive_m.zip"
].map(fs::read).map(Result::unwrap);
let sizes = archives.iter().map(Vec::len).collect::<Vec<_>>();
let _ = fs::remove_dir_all(output_dir);
let central_directory = read_cd::from_provider(
&sizes,
false,
|pos, length| {
println!("Requested {length} bytes at {pos}");
Ok(archives[pos.disk][(pos.offset)..(pos.offset + length)].to_owned())
}
).unwrap().sort();
let current_file: RefCell<Option<File>> = RefCell::new(None);
let mut unpacker = ZipUnpacker::new(central_directory, sizes, |data| {
match data {
ZipDecodedData::FileHeader(cdfh, _) => {
println!();
let mut path = PathBuf::from(output_dir);
path.push(&cdfh.filename);
if !cdfh.is_directory() {
print!("New file: {}", cdfh.filename);
io::stdout().flush()?;
fs::create_dir_all(path.parent().unwrap())?;
*current_file.borrow_mut() = Some(
OpenOptions::new()
.create(true)
.write(true)
.open(path)?
);
} else {
print!("New directory: {}", cdfh.filename);
io::stdout().flush()?;
fs::create_dir_all(path)?;
}
},
ZipDecodedData::FileData(data) => {
print!(".");
io::stdout().flush()?;
current_file.borrow().as_ref().unwrap().write_all(data)?;
}
}
Ok(())
});
for archive in archives {
unpacker.update(archive).unwrap();
}
println!("\nDone!");
}