From bd77f62e99a5300dfa52aef3a7040414b28ebfd6 Mon Sep 17 00:00:00 2001 From: Igor Tolmachev Date: Mon, 10 Jun 2024 23:38:08 +0900 Subject: Reset branch --- src/archive.rs | 42 ------------- src/datatypes.rs | 20 ------- src/file.rs | 11 ---- src/io.rs | 25 -------- src/lib.rs | 11 ---- src/result.rs | 63 ------------------- src/utils.rs | 60 ------------------- src/zip/archive.rs | 0 src/zip/datatypes.rs | 166 --------------------------------------------------- src/zip/file.rs | 124 -------------------------------------- src/zip/io.rs | 155 ----------------------------------------------- src/zip/mod.rs | 6 -- 12 files changed, 683 deletions(-) delete mode 100644 src/archive.rs delete mode 100644 src/datatypes.rs delete mode 100644 src/file.rs delete mode 100644 src/io.rs delete mode 100644 src/result.rs delete mode 100644 src/utils.rs delete mode 100644 src/zip/archive.rs delete mode 100644 src/zip/datatypes.rs delete mode 100644 src/zip/file.rs delete mode 100644 src/zip/io.rs delete mode 100644 src/zip/mod.rs diff --git a/src/archive.rs b/src/archive.rs deleted file mode 100644 index ef74de9..0000000 --- a/src/archive.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::io::{ArchiveRead, ArchiveWrite}; -use crate::result::ArchiveResult; -use std::fs::File; -use std::path::Path; - -pub struct Archive { - pub io: IO, -} - -impl Archive { - pub fn file_reader(path: impl AsRef) -> ArchiveResult - where - IO: ArchiveRead, - { - Self::reader(File::open(path)?) - } - - pub fn reader(reader: IO::Reader) -> ArchiveResult { - Ok(Self { - io: IO::new(reader)?, - }) - } -} - -impl Archive {} - -impl Archive { - pub fn file_writer(path: impl AsRef) -> ArchiveResult - where - IO: ArchiveWrite, - { - Self::writer(File::create(path)?) - } - - pub fn writer(writer: IO::Writer) -> ArchiveResult { - Ok(Self { - io: IO::new(writer)?, - }) - } -} - -impl Archive {} diff --git a/src/datatypes.rs b/src/datatypes.rs deleted file mode 100644 index 59c7552..0000000 --- a/src/datatypes.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::result::ArchiveResult; -use crate::utils::ReadHelper; -use std::io::{Read, Write}; - -pub trait ArchiveDatatype: Sized { - const SIZE: usize = SIZE; - - fn parse(buf: [u8; SIZE]) -> Self; - - fn dump(&self) -> [u8; SIZE]; - - fn read(mut reader: impl Read) -> ArchiveResult { - Ok(Self::parse(reader.read2buf::()?)) - } - - fn write(&self, mut writer: impl Write) -> ArchiveResult<()> { - writer.write(&self.dump())?; - Ok(()) - } -} diff --git a/src/file.rs b/src/file.rs deleted file mode 100644 index 9fa2add..0000000 --- a/src/file.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::io::{Read, Write}; - -pub trait ArchiveFile { - type Info; - - fn new(info: Self::Info) -> Self; -} - -pub trait ArchiveFileRead: Read + ArchiveFile {} - -pub trait ArchiveFileWrite: Write + ArchiveFile {} diff --git a/src/io.rs b/src/io.rs deleted file mode 100644 index 43cf1a4..0000000 --- a/src/io.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::file::{ArchiveFileRead, ArchiveFileWrite}; -use crate::result::ArchiveResult; -use std::io::{Read, Write}; - -pub trait ArchiveRead: Sized { - type Reader: Read; - type FileInfo; - type FileReader: ArchiveFileRead; - - fn new(reader: Self::Reader) -> ArchiveResult; - - fn files(&self) -> ArchiveResult>; - - fn open_file(&self, name: &str) -> ArchiveResult; -} - -pub trait ArchiveWrite: Sized { - type Writer: Write; - type FileInfo; - type FileWriter: ArchiveFileWrite; - - fn new(write: Self::Writer) -> ArchiveResult; - - fn create_file(&self, name: &str) -> ArchiveResult; -} diff --git a/src/lib.rs b/src/lib.rs index 3907e21..e69de29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +0,0 @@ -pub mod zip; - -mod result; -mod utils; - -mod archive; -mod datatypes; -mod file; -mod io; - -pub use archive::Archive; diff --git a/src/result.rs b/src/result.rs deleted file mode 100644 index 9f35920..0000000 --- a/src/result.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::error::Error; -use std::fmt::{Debug, Display}; -use std::io; - -pub type ArchiveResult = Result; - -#[derive(Debug)] -pub enum ArchiveError { - IO(io::Error), - BadArchive { reason: &'static str }, - IncorrectSignature { expected: u32, received: u32 }, - IncorrectString { location: &'static str }, - IncorrectDate { year: u16, month: u16, day: u16 }, - IncorrectTime { hour: u16, min: u16, sec: u16 }, - UnsupportedCompressionMethod { method: u16 }, -} - -impl From for ArchiveError { - fn from(value: io::Error) -> Self { - Self::IO(value) - } -} - -impl Display for ArchiveError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::IO(err) => write!(f, "{err}"), - Self::BadArchive { reason } => { - write!(f, "Bad archive because {reason}") - } - Self::IncorrectSignature { expected, received } => { - write!( - f, - "Wrong signature (expected: {expected}, received: {received})" - ) - } - Self::IncorrectString { location } => { - write!(f, "Incorrect string in {location}") - } - Self::IncorrectDate { year, month, day } => { - write!( - f, - "Incorrect date (year: {year}, month: {month}, day: {day})" - ) - } - Self::IncorrectTime { hour, min, sec } => { - write!(f, "Incorrect time (hour: {hour}, min: {min}, sec: {sec})") - } - Self::UnsupportedCompressionMethod { method } => { - write!(f, "Unsupported compression method (method: {method})") - } - } - } -} - -impl Error for ArchiveError { - fn source(&self) -> Option<&(dyn Error + 'static)> { - match self { - Self::IO(source) => Some(source), - _ => None, - } - } -} diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 57ad1c9..0000000 --- a/src/utils.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::io::{Read, Result as IOResult}; - -macro_rules! archive_datatype { - { - $vis:vis struct $struct_name:ident { - $( - $($fix_field_name:ident: $fix_field_type:ty)? - $([const] $const_field_name:ident: $const_field_type:ty = $const_field_value:expr)? - , - )* - } - } - => { - #[derive(Debug)] - $vis struct $struct_name { $($(pub $fix_field_name: $fix_field_type,)?)* } - - #[allow(unused)] - impl $struct_name { - $($(pub const $const_field_name: $const_field_type = $const_field_value;)?)* - } - - - impl ArchiveDatatype<{$($((<$fix_field_type>::BITS as usize / 8)+)?)* 0}> for $struct_name { - fn parse(buf: [u8; Self::SIZE]) -> Self { - let mut byte = 0; - - $($( - byte += (<$fix_field_type>::BITS / 8) as usize; - let $fix_field_name = <$fix_field_type>::from_le_bytes(buf[byte - (<$fix_field_type>::BITS as usize / 8)..byte].try_into().unwrap()); - )?)* - - Self { $($($fix_field_name,)?)* } - } - - fn dump(&self) -> [u8; Self::SIZE] { - [$($(&self.$fix_field_name.to_le_bytes()[..],)?)*] - .concat() - .try_into() - .unwrap() - } - } - } -} -pub(crate) use archive_datatype; - -pub trait ReadHelper: Read { - fn read2buf(&mut self) -> IOResult<[u8; SIZE]> { - let mut buf = [0; SIZE]; - self.read(&mut buf)?; - Ok(buf) - } - - fn read2vec(&mut self, size: usize) -> IOResult> { - let mut buf = vec![0; size]; - self.read(&mut buf)?; - Ok(buf) - } -} - -impl ReadHelper for R {} diff --git a/src/zip/archive.rs b/src/zip/archive.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/zip/datatypes.rs b/src/zip/datatypes.rs deleted file mode 100644 index 5ce1045..0000000 --- a/src/zip/datatypes.rs +++ /dev/null @@ -1,166 +0,0 @@ -pub use crate::datatypes::ArchiveDatatype; -use crate::result::{ArchiveError, ArchiveResult}; -use crate::utils::{archive_datatype, ReadHelper}; -use std::io::{Read, Seek, SeekFrom}; - -archive_datatype! { - pub struct LocalFileHeader { - [const] SIGNATURE: u32 = 0x04034b50, - signature: u32, - version_needed: u16, - general_purpose_bit_flag: u16, - compression_method: u16, - last_mod_file_time: u16, - last_mod_file_date: u16, - crc32: u32, - compressed_size: u32, - uncompressed_size: u32, - file_name_length: u16, - extra_field_length: u16, - } -} - -archive_datatype! { - pub struct DataDescriptor { - [const] SIGNATURE: u32 = 0x08074b50, - crc32: u32, - compressed_size: u32, - uncompressed_size: u32, - } -} - -archive_datatype! { - pub struct ArchiveExtraDataRecord { - [const] SIGNATURE: u32 = 0x08064b50, - signature: u32, - extra_field_length: u32, - } -} - -archive_datatype! { - pub struct CentralDirectoryRecord { - [const] SIGNATURE: u32 = 0x02014b50, - signature: u32, - version_made_by: u16, - version_needed: u16, - general_purpose_bit_flag: u16, - compression_method: u16, - last_mod_file_time: u16, - last_mod_file_date: u16, - crc32: u32, - compressed_size: u32, - uncompressed_size: u32, - file_name_length: u16, - extra_field_length: u16, - file_comment_length: u16, - disk_number: u16, - internal_file_attributes: u16, - external_file_attributes: u32, - header_offset: u32, - } -} - -archive_datatype! { - pub struct DigitalSignature{ - [const] SIGNATURE: u32 = 0x05054b50, - signature: u32, - data_size: u16, - } -} - -archive_datatype! { - pub struct Zip64EndOfCentralDirectoryRecord { - [const] SIGNATURE: u32 = 0x06064b50, - signature: u32, - size_of_zip64_eocd: u64, - version_made_by: u16, - version_needed: u16, - disk: u32, - disk_where_starts_cd: u32, - entries_in_cd_on_disk: u64, - entries_in_cd: u64, - size_of_cd_records: u64, - offset_of_cd_entries: u64, - } -} - -impl Zip64EndOfCentralDirectoryRecord { - pub fn find( - mut reader: impl Read + Seek, - eocd_offset: u64, - ) -> ArchiveResult)>> { - let locator_offset = eocd_offset - Zip64EndOfCentralDirectoryLocator::SIZE as u64; - reader.seek(SeekFrom::Start(locator_offset))?; - - let locator = Zip64EndOfCentralDirectoryLocator::read(&mut reader)?; - if locator.signature != Zip64EndOfCentralDirectoryLocator::SIGNATURE { - return Ok(None); - } - - reader.seek(SeekFrom::Start(locator.offset_of_zip64_eocd))?; - let eocd64 = Self::read(&mut reader)?; - if eocd64.signature != Self::SIGNATURE { - return Err(ArchiveError::IncorrectSignature { - expected: Self::SIGNATURE, - received: eocd64.signature, - }); - } - - let ext_data = reader.read2vec(eocd64.size_of_zip64_eocd as usize + 12 - Self::SIZE)?; - Ok(Some((locator.offset_of_zip64_eocd, eocd64, ext_data))) - } -} - -archive_datatype! { - pub struct Zip64EndOfCentralDirectoryLocator { - [const] SIGNATURE: u32 = 0x07064b50, - signature: u32, - disk_where_starts_zip64_eocd: u32, - offset_of_zip64_eocd: u64, - total_disks_number: u32, - } -} - -archive_datatype! { - pub struct EndOfCentralDirectoryRecord { - [const] SIGNATURE: u32 = 0x06054b50, - signature: u32, - disk: u16, - disk_where_starts_cd: u16, - entries_in_cd_on_disk: u16, - entries_in_cd: u16, - size_of_cd_records: u32, - offset_of_cd_entries: u32, - comment_length: u16, - } -} - -impl EndOfCentralDirectoryRecord { - pub fn find(mut reader: impl Read + Seek) -> ArchiveResult<(u64, Self, String)> { - let file_size = reader.seek(SeekFrom::End(0))? as usize; - let limit: usize = (u16::MAX as usize + Self::SIZE).min(file_size); - let mut buf = vec![0; limit]; - - reader.seek(SeekFrom::End(-(limit as i64)))?; - reader.read(&mut buf)?; - - for byte in 0..limit - 4 { - if u32::from_le_bytes(buf[byte..byte + 4].try_into().unwrap()) == Self::SIGNATURE { - let eocd = Self::parse(buf[byte..byte + Self::SIZE].try_into().unwrap()); - - let comment = String::from_utf8( - buf[byte + Self::SIZE..byte + Self::SIZE + eocd.comment_length as usize].into(), - ) - .map_err(|_| ArchiveError::IncorrectString { - location: "archive_comment", - })?; - - return Ok(((file_size - limit + byte) as u64, eocd, comment)); - } - } - - Err(ArchiveError::BadArchive { - reason: "end of central directory record not found", - }) - } -} diff --git a/src/zip/file.rs b/src/zip/file.rs deleted file mode 100644 index 261390f..0000000 --- a/src/zip/file.rs +++ /dev/null @@ -1,124 +0,0 @@ -use crate::file::{ArchiveFile, ArchiveFileRead, ArchiveFileWrite}; -use crate::result::{ArchiveError, ArchiveResult}; -use chrono::NaiveDateTime; -use std::io::{Read, Write}; - -pub struct GeneralPurposeBitFlag {} - -pub enum CompressionMethod { - Store, - Deflate, - Bzip2, - LZMA, - Zstandard, -} - -impl TryFrom for CompressionMethod { - type Error = ArchiveError; - - fn try_from(value: u16) -> ArchiveResult { - Ok(match value { - 0 => Self::Store, - 8 => Self::Deflate, - 12 => Self::Bzip2, - 14 => Self::LZMA, - 93 | 20 => Self::Zstandard, - _ => return Err(ArchiveError::UnsupportedCompressionMethod { method: value }), - }) - } -} - -pub struct FileInfo { - number: u64, - version_made_by: u16, - version_needed: u16, - general_purpose_bit_flag: GeneralPurposeBitFlag, - compression_method: CompressionMethod, - file_modified_at: NaiveDateTime, - crc32: u32, - compressed_size: u64, - uncompressed_size: u64, - name: String, - comment: String, - header_offset: u64, -} - -impl FileInfo { - pub fn new( - number: u64, - version_made_by: u16, - version_needed: u16, - general_purpose_bit_flag: GeneralPurposeBitFlag, - compression_method: CompressionMethod, - file_modified_at: NaiveDateTime, - crc32: u32, - compressed_size: u64, - uncompressed_size: u64, - name: String, - comment: String, - header_offset: u64, - ) -> Self { - Self { - number, - version_made_by, - version_needed, - general_purpose_bit_flag, - compression_method, - file_modified_at, - crc32, - compressed_size, - uncompressed_size, - name, - comment, - header_offset, - } - } -} - -pub struct FileReader { - info: FileInfo, -} - -impl ArchiveFile for FileReader { - type Info = FileInfo; - - fn new(info: Self::Info) -> Self { - Self { info } - } -} - -impl Read for FileReader { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - todo!() - } -} - -impl ArchiveFileRead for FileReader {} - -impl FileReader {} - -pub struct FileWriter { - info: FileInfo, -} - -impl ArchiveFile for FileWriter { - type Info = FileInfo; - - fn new(info: Self::Info) -> Self { - Self { info } - } -} - -impl Write for FileWriter { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - todo!() - } - - fn flush(&mut self) -> std::io::Result<()> { - todo!() - } -} - -impl ArchiveFileWrite for FileWriter {} - -impl FileWriter {} diff --git a/src/zip/io.rs b/src/zip/io.rs deleted file mode 100644 index c41607f..0000000 --- a/src/zip/io.rs +++ /dev/null @@ -1,155 +0,0 @@ -use super::datatypes::*; -use super::file::{FileInfo, FileReader, FileWriter}; -use crate::io::{ArchiveRead, ArchiveWrite}; -use crate::result::{ArchiveError, ArchiveResult}; -use crate::utils::ReadHelper; -use chrono::{NaiveDate, NaiveDateTime, NaiveTime}; -use std::collections::HashMap; -use std::fs::File; -use std::io::Read; -use std::io::{Seek, SeekFrom, Write}; - -pub struct Reader { - reader: R, - files: HashMap, - comment: String, -} - -impl ArchiveRead for Reader { - type Reader = R; - type FileInfo = FileInfo; - type FileReader = FileReader; - - fn new(mut reader: Self::Reader) -> ArchiveResult { - let cd_size: u64; - let cd_offset: u64; - let cd_entries: u64; - - let (eocd_offset, eocd, comment) = EndOfCentralDirectoryRecord::find(&mut reader)?; - if let Some((eocd64_offset, eocd64, eocd64_extensible)) = - Zip64EndOfCentralDirectoryRecord::find(&mut reader, eocd_offset)? - { - cd_size = eocd64.size_of_cd_records; - cd_offset = eocd64.offset_of_cd_entries; - cd_entries = eocd64.entries_in_cd; - } else { - cd_size = eocd.size_of_cd_records as u64; - cd_offset = eocd.offset_of_cd_entries as u64; - cd_entries = eocd.entries_in_cd as u64; - } - - let mut buf = vec![0; cd_size as usize]; - reader.seek(SeekFrom::Start(cd_offset))?; - reader.read(&mut buf)?; - - let mut buf: &[u8] = &buf; - let mut files = HashMap::with_capacity(cd_entries as usize); - - for entry_number in 0..cd_entries { - let cd = CentralDirectoryRecord::read(&mut buf)?; - - let file_name = String::from_utf8(buf.read2vec(cd.file_name_length as usize)?).or( - Err(ArchiveError::IncorrectString { - location: "file_name", - }), - )?; - let mut extra_field: &[u8] = &buf.read2vec(cd.extra_field_length as usize)?; - let file_comment = String::from_utf8(buf.read2vec(cd.file_comment_length as usize)?) - .or(Err(ArchiveError::IncorrectString { - location: "file_comment", - }))?; - - let mut uncompressed_size: u64 = cd.uncompressed_size as u64; - let mut compressed_size: u64 = cd.compressed_size as u64; - let mut header_offset: u64 = cd.header_offset as u64; - - while extra_field.len() > 0 { - let header = u16::from_le_bytes(extra_field.read2buf()?); - let size = u16::from_le_bytes(extra_field.read2buf()?); - let mut data: &[u8] = &extra_field.read2vec(size as usize)?; - - match header { - 0x0001 => { - if uncompressed_size == 0xFFFFFFFF { - uncompressed_size = u64::from_le_bytes(data.read2buf()?); - } - if compressed_size == 0xFFFFFFFF { - compressed_size = u64::from_le_bytes(data.read2buf()?); - } - if header_offset == 0xFFFFFFFF { - header_offset = u64::from_le_bytes(data.read2buf()?); - } - } - _ => {} - }; - } - - let year = ((cd.last_mod_file_date >> 9) & 0x7F) + 1980; - let month = (cd.last_mod_file_date >> 5) & 0xF; - let day = cd.last_mod_file_date & 0x1F; - - let hour = (cd.last_mod_file_time >> 11) & 0x1F; - let min = (cd.last_mod_file_time >> 5) & 0x3F; - let sec = (cd.last_mod_file_time & 0x1F) * 2; - - files.insert( - file_name.clone(), - FileInfo::new( - entry_number, - cd.version_made_by, - cd.version_needed, - super::file::GeneralPurposeBitFlag {}, - cd.compression_method.try_into()?, - NaiveDateTime::new( - NaiveDate::from_ymd_opt(year as i32, month as u32, day as u32) - .ok_or(ArchiveError::IncorrectDate { year, month, day })?, - NaiveTime::from_hms_opt(hour as u32, min as u32, sec as u32) - .ok_or(ArchiveError::IncorrectTime { hour, min, sec })?, - ), - cd.crc32, - compressed_size, - uncompressed_size, - file_name, - file_comment, - header_offset, - ), - ); - } - - Ok(Self { - reader, - files, - comment, - }) - } - - fn files(&self) -> ArchiveResult> { - todo!() - } - - fn open_file(&self, name: &str) -> ArchiveResult { - todo!() - } -} - -impl Reader {} - -pub struct Writer { - writer: W, -} - -impl ArchiveWrite for Writer { - type Writer = W; - type FileInfo = FileInfo; - type FileWriter = FileWriter; - - fn new(writer: Self::Writer) -> ArchiveResult { - todo!() - } - - fn create_file(&self, name: &str) -> ArchiveResult { - todo!() - } -} - -impl Writer {} diff --git a/src/zip/mod.rs b/src/zip/mod.rs deleted file mode 100644 index b668b6b..0000000 --- a/src/zip/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod archive; -mod datatypes; -mod file; -mod io; - -pub use io::{Reader, Writer}; -- cgit v1.2.3