archive/
archive.rs

1use std::{fs::{self, File, OpenOptions}, path::PathBuf, cell::RefCell, io::{Write, self}};
2
3use stream_unpack::zip::{ZipUnpacker, ZipDecodedData, read_cd};
4
5fn main() {
6    let output_dir = "unpack";
7    let archive = fs::read("archive.zip").unwrap();
8    let _ = fs::remove_dir_all(output_dir);
9
10    let central_directory = read_cd::from_provider(
11        vec![archive.len()],
12        false,
13        |pos, length| {
14            println!("Requested {length} bytes at {pos}");
15            Ok(archive[(pos.offset)..(pos.offset + length)].to_owned())
16        }
17    ).unwrap().sort();
18
19    let current_file: RefCell<Option<File>> = RefCell::new(None);
20
21    let mut unpacker = ZipUnpacker::new(central_directory, vec![archive.len()]);
22    unpacker.set_callback(|data| {
23        match data {
24            ZipDecodedData::FileHeader(cdfh, _) => {
25                println!();
26
27                let mut path = PathBuf::from(output_dir);
28                path.push(&cdfh.filename);
29
30                if !cdfh.is_directory() {
31                    print!("New file: {}", cdfh.filename);
32                    io::stdout().flush()?;
33
34                    fs::create_dir_all(path.parent().unwrap())?;
35
36                    *current_file.borrow_mut() = Some(
37                        OpenOptions::new()
38                        .create(true)
39                        .write(true)
40                        .open(path)?
41                    );
42                } else {
43                    print!("New directory: {}", cdfh.filename);
44                    io::stdout().flush()?;
45
46                    fs::create_dir_all(path)?;
47                }
48            },
49
50            ZipDecodedData::FileData(data) => {
51                print!(".");
52                io::stdout().flush()?;
53
54                current_file.borrow().as_ref().unwrap().write_all(data)?;
55            }
56        }
57
58        Ok(())
59    });
60
61    unpacker.update(archive).unwrap();
62
63    println!("\nDone!");
64}