zip-extensions 0.14.1

An extension crate for zip.
Documentation
use crate::file_utils::file_write_all_bytes;
use crate::inflate::zip_archive_extensions::ZipArchiveExtensions;
use std::io;
use std::io::{Error, ErrorKind, Read};
use std::path::PathBuf;
use zip::ZipArchive;
use zip::read::ZipFile;
use zip::result::{ZipError, ZipResult};

impl<R: Read + io::Seek> ZipArchiveExtensions for ZipArchive<R> {
    fn extract(&mut self, target_directory: &PathBuf) -> ZipResult<()> {
        if !target_directory.is_dir() {
            return Err(ZipError::Io(Error::new(
                ErrorKind::InvalidInput,
                "The specified path does not indicate a valid directory path.",
            )));
        }

        for file_number in 0..self.len() {
            let mut next: ZipFile<R> = self.by_index(file_number)?;
            let sanitized_name = match next.enclosed_name() {
                Some(name) => name,
                None => continue,
            };
            if next.is_dir() {
                let extracted_folder_path = target_directory.join(sanitized_name);
                std::fs::create_dir_all(extracted_folder_path)?;
            } else if next.is_file() {
                let mut buffer: Vec<u8> = Vec::new();
                let _bytes_read = next.read_to_end(&mut buffer)?;
                let extracted_file_path = target_directory.join(sanitized_name);
                file_write_all_bytes(extracted_file_path, buffer.as_ref(), true)?;
            }
        }

        Ok(())
    }

    fn extract_file(
        &mut self,
        file_number: usize,
        destination_file_path: &PathBuf,
        overwrite: bool,
    ) -> ZipResult<()> {
        let mut buffer: Vec<u8> = Vec::new();
        self.extract_file_to_memory(file_number, &mut buffer)?;
        file_write_all_bytes(
            destination_file_path.to_path_buf(),
            buffer.as_ref(),
            overwrite,
        )?;
        Ok(())
    }

    fn extract_file_to_memory(
        &mut self,
        file_number: usize,
        buffer: &mut Vec<u8>,
    ) -> ZipResult<()> {
        let mut next: ZipFile<R> = self.by_index(file_number)?;
        if next.is_file() {
            let _bytes_read = next.read_to_end(buffer)?;
            return Ok(());
        }
        Err(ZipError::Io(Error::new(
            ErrorKind::InvalidInput,
            "The specified index does not indicate a file entry.",
        )))
    }

    fn entry_path(&mut self, file_number: usize) -> ZipResult<PathBuf> {
        let next: ZipFile<R> = self.by_index(file_number)?;
        Ok(next.mangled_name())
    }

    fn file_number(&mut self, entry_path: &PathBuf) -> Option<usize> {
        for file_number in 0..self.len() {
            if let Ok(next) = self.by_index(file_number) {
                let sanitized_name = next.mangled_name();
                if sanitized_name == *entry_path {
                    return Some(file_number);
                }
            }
        }
        None
    }
}