Skip to main content

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 copy ZIP comment to output")]
13    OutputComment(#[source] ZipError),
14    #[error("could not write to output")]
15    OutputWrite(#[source] std::io::Error),
16    #[error("could not write ZIP file #{1} to output")]
17    OutputZip(#[source] ZipError, usize),
18    #[error("could not finish writing output ZIP")]
19    OutputZipFinish(#[source] ZipError),
20}
21
22pub(crate) fn copy_zip<I, O>(input: &mut I, output: &mut O) -> Result<(), CopyZipError>
23where
24    I: ?Sized + Seek + Read,
25    O: ?Sized + Seek + Write,
26{
27    let mut input = ZipArchive::new(BufReader::new(input)).map_err(CopyZipError::InputZip)?;
28    let mut output = ZipWriter::new(BufWriter::new(output));
29
30    output
31        .set_raw_comment(input.comment().into())
32        .map_err(CopyZipError::OutputComment)?;
33    for idx in 0..input.len() {
34        let file = input
35            .by_index_raw(idx)
36            .map_err(|err| CopyZipError::InputZipIndex(err, idx))?;
37        output
38            .raw_copy_file(file)
39            .map_err(|err| CopyZipError::OutputZip(err, idx))?;
40    }
41    output
42        .finish()
43        .map_err(CopyZipError::OutputZipFinish)?
44        .flush()
45        .map_err(CopyZipError::OutputWrite)?;
46
47    Ok(())
48}