zipsign_api/
sign_unsign_zip.rs

1use std::io::{BufReader, BufWriter, Read, Seek, Write};
2
3use zip::result::ZipError;
4use zip::{ZipArchive, ZipWriter};
5
6#[derive(Debug, thiserror::Error)]
7pub(crate) enum CopyZipError {
8    #[error("could not read input ZIP")]
9    InputZip(#[source] ZipError),
10    #[error("could not read file #{1} inside input ZIP")]
11    InputZipIndex(#[source] ZipError, usize),
12    #[error("could not write to output")]
13    OutputWrite(#[source] std::io::Error),
14    #[error("could not write ZIP file #{1} to output")]
15    OutputZip(#[source] ZipError, usize),
16    #[error("could not finish writing output ZIP")]
17    OutputZipFinish(#[source] ZipError),
18}
19
20pub(crate) fn copy_zip<I, O>(input: &mut I, output: &mut O) -> Result<(), CopyZipError>
21where
22    I: ?Sized + Seek + Read,
23    O: ?Sized + Seek + Write,
24{
25    let mut input = ZipArchive::new(BufReader::new(input)).map_err(CopyZipError::InputZip)?;
26    let mut output = ZipWriter::new(BufWriter::new(output));
27
28    output.set_raw_comment(input.comment().into());
29    for idx in 0..input.len() {
30        let file = input
31            .by_index_raw(idx)
32            .map_err(|err| CopyZipError::InputZipIndex(err, idx))?;
33        output
34            .raw_copy_file(file)
35            .map_err(|err| CopyZipError::OutputZip(err, idx))?;
36    }
37    output
38        .finish()
39        .map_err(CopyZipError::OutputZipFinish)?
40        .flush()
41        .map_err(CopyZipError::OutputWrite)?;
42
43    Ok(())
44}