use crate::driver::ArchiveFileInfo; use crate::zip::{ZipError, ZipResult}; use chrono::{DateTime, Local}; #[derive(Debug, Clone)] pub enum CompressionMethod { Store, Deflate, BZIP2, LZMA, ZStd, XZ, } impl CompressionMethod { pub(crate) fn from_struct_id(id: u16) -> ZipResult { match id { 0 => Ok(Self::Store), 8 => Ok(Self::Deflate), 12 => Ok(Self::BZIP2), 14 => Ok(Self::LZMA), 93 => Ok(Self::ZStd), 95 => Ok(Self::XZ), 1..=7 | 9..=11 | 13 | 15..=20 | 94 | 96..=99 => { Err(ZipError::UnsupportedCompressionMethod.into()) } 21..=92 | 100.. => Err(ZipError::InvalidCompressionMethod.into()), } } } #[derive(Debug, Clone)] pub struct BitFlag { flag: u16, } pub mod bit { #[derive(Debug, PartialEq, Eq)] pub enum DeflateMode { Normal, Maximum, Fast, SuperFast, } } macro_rules! get_set_bit_flag { {$($get:ident $set:ident $bit:expr)+} => { $( pub fn $get(&self) -> bool { self.get_bit($bit) } pub fn $set(&mut self, enable: bool) { self.set_bit($bit, enable); } )* }; } impl BitFlag { pub fn new(flag: u16) -> Self { Self { flag } } #[inline] fn get_bit(&self, bit: u32) -> bool { (self.flag & 2u16.pow(bit)) > 0 } #[inline] fn set_bit(&mut self, bit: u32, enable: bool) { if enable { self.flag |= 2u16.pow(bit); } else { self.flag &= !2u16.pow(bit); } } pub fn deflate_mode(&self) -> bit::DeflateMode { match self.flag & 6 { 0 => bit::DeflateMode::Normal, 2 => bit::DeflateMode::Maximum, 4 => bit::DeflateMode::Fast, 6 => bit::DeflateMode::SuperFast, _ => panic!("impossible"), } } pub fn set_deflate_mode(&mut self, mode: bit::DeflateMode) { match mode { bit::DeflateMode::Normal => { self.set_bit(1, false); self.set_bit(2, false); } bit::DeflateMode::Maximum => { self.set_bit(1, true); self.set_bit(2, false); } bit::DeflateMode::Fast => { self.set_bit(1, false); self.set_bit(2, true); } bit::DeflateMode::SuperFast => { self.set_bit(1, true); self.set_bit(2, true); } } } get_set_bit_flag! { is_encrypted set_encrypted 0 is_imploding_8k set_imploding_8k 1 is_imploding_3sf_trees set_imploding_3sf_trees 2 is_lzma_has_eos_marker set_lzma_has_eos_marker 1 is_has_data_descriptor set_has_data_descriptor 3 is_patched_data set_patched_data 5 is_strong_encryption set_strong_encryption 6 is_utf8 set_utf8 11 is_cd_encryption set_cd_encryption 13 } } #[derive(Debug, Clone)] pub struct ZipFileInfo { pub compression_method: CompressionMethod, pub bit_flag: BitFlag, pub datetime: DateTime, pub crc: u32, pub compressed_size: u64, pub size: u64, pub header_pointer: u64, pub name: String, pub comment: String, } impl ZipFileInfo { pub fn new( compression_method: CompressionMethod, bit_flag: BitFlag, datetime: DateTime, crc: u32, compressed_size: u64, size: u64, header_pointer: u64, name: String, comment: String, ) -> Self { Self { compression_method, bit_flag, datetime, crc, compressed_size, size, header_pointer, name, comment, } } } impl ArchiveFileInfo for ZipFileInfo {}