pub struct VersionMadeBy {
pub compatibility_information: CompatibleFileAttributeInformation,
pub version: ZipVersion,
}
#[derive(Debug, Clone, PartialEq)]
pub enum CompatibleFileAttributeInformation {
MsDosAndOs2,
Amiga,
OpenVms,
Unix,
VmCms,
AtariSt,
Os2,
Macintosh,
ZSystem,
CpM,
WindowsNtfs,
Mvs,
Vse,
AcornRisc,
VFat,
AlternateMvs,
BeOs,
Tandem,
Os400,
OsX,
}
impl TryFrom<u8> for CompatibleFileAttributeInformation {
type Error = u8;
fn try_from(value: u8) -> Result<Self, Self::Error> {
use CompatibleFileAttributeInformation::*;
match value {
0 => Ok(MsDosAndOs2),
1 => Ok(Amiga),
2 => Ok(OpenVms),
3 => Ok(Unix),
4 => Ok(VmCms),
5 => Ok(AtariSt),
6 => Ok(Os2),
7 => Ok(Macintosh),
8 => Ok(ZSystem),
9 => Ok(CpM),
10 => Ok(WindowsNtfs),
11 => Ok(Mvs),
12 => Ok(Vse),
13 => Ok(AcornRisc),
14 => Ok(VFat),
15 => Ok(AlternateMvs),
16 => Ok(BeOs),
17 => Ok(Tandem),
18 => Ok(Os400),
19 => Ok(OsX),
other => Err(other),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ZipVersion {
pub major_version: u8,
pub minor_version: u8,
}
impl From<u8> for ZipVersion {
fn from(value: u8) -> Self {
let major_version = value / 10;
let minor_version = value.rem_euclid(10);
Self {
major_version,
minor_version,
}
}
}
impl From<u16> for ZipVersion {
fn from(value: u16) -> Self {
let version = value.to_le_bytes();
Self {
major_version: version[0],
minor_version: version[1],
}
}
}
impl ZipVersion {
pub fn new(major_version: u8, minor_version: u8) -> Self {
Self {
major_version,
minor_version,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum MinimumFeatureVersion {
Default,
VolumeLabel,
Folder,
CompressedUsingDeflate,
EncryptedUsingPkWare,
CompressedUsingDeflate64,
CompressedUsingPkwareDclImplode,
PatchDataSet,
UsesZip64FormatExtentions,
CompressedUsingBzip2,
EncryptedUsingDes,
EncryptedUsing3Des,
EncryptedUsingOriginalRc2,
EncryptedUsingRc4,
EncryptedUsingAes,
EncryptedUsingCorrectedRc2,
EncryptedUsingCorrectedRc2_64,
EncryptedUsingNonOaepKeyWrapping,
CentralDirectoryEncryption,
CompressedUsingLzma,
CompressedUsingPpmd,
EncryptedUsingBlowfish,
EncryptedUsingTwofish,
}
impl From<MinimumFeatureVersion> for ZipVersion {
fn from(value: MinimumFeatureVersion) -> Self {
use MinimumFeatureVersion::*;
match value {
Default => ZipVersion::new(1, 0),
VolumeLabel => ZipVersion::new(1, 1),
Folder => ZipVersion::new(2, 0),
CompressedUsingDeflate => ZipVersion::new(2, 0),
EncryptedUsingPkWare => ZipVersion::new(2, 0),
CompressedUsingDeflate64 => ZipVersion::new(2, 1),
CompressedUsingPkwareDclImplode => ZipVersion::new(2, 5),
PatchDataSet => ZipVersion::new(2, 7),
UsesZip64FormatExtentions => ZipVersion::new(4, 5),
CompressedUsingBzip2 => ZipVersion::new(4, 7),
EncryptedUsingDes => ZipVersion::new(5, 0),
EncryptedUsing3Des => ZipVersion::new(5, 0),
EncryptedUsingOriginalRc2 => ZipVersion::new(5, 0),
EncryptedUsingRc4 => ZipVersion::new(5, 0),
EncryptedUsingAes => ZipVersion::new(5, 1),
EncryptedUsingCorrectedRc2 => ZipVersion::new(5, 1),
EncryptedUsingCorrectedRc2_64 => ZipVersion::new(5, 2),
EncryptedUsingNonOaepKeyWrapping => ZipVersion::new(6, 1),
CentralDirectoryEncryption => ZipVersion::new(6, 2),
CompressedUsingLzma => ZipVersion::new(6, 3),
CompressedUsingPpmd => ZipVersion::new(6, 3),
EncryptedUsingBlowfish => ZipVersion::new(6, 3),
EncryptedUsingTwofish => ZipVersion::new(6, 3),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum CompressionMethod {
Stored,
Shrunk,
ReducedWithFactor1,
ReducedWithFactor2,
ReducedWithFactor3,
ReducedWithFactor4,
Imploded,
Deflated,
EnhancedDeflatingUsingDeflate64,
PkWareDataCompressionLIbraryImploding,
Bzip2,
Lzma,
IbmZOsCmpsc,
IbmTerse,
IbmLz77z,
Zstdandart,
Mp3,
Xz,
Jpeg,
WavPack,
PpmdV1R1,
Aex,
}
impl CompressionMethod {
pub const fn is_deprecated(&self) -> bool {
use CompressionMethod::*;
matches!(
self,
Shrunk | ReducedWithFactor1 | ReducedWithFactor2 | ReducedWithFactor3 | ReducedWithFactor4 | Imploded
)
}
}
impl TryFrom<u16> for CompressionMethod {
type Error = u16;
fn try_from(value: u16) -> Result<Self, Self::Error> {
use CompressionMethod::*;
match value {
0 => Ok(Stored),
1 => Ok(Shrunk),
2 => Ok(ReducedWithFactor1),
3 => Ok(ReducedWithFactor2),
4 => Ok(ReducedWithFactor3),
5 => Ok(ReducedWithFactor4),
6 => Ok(Imploded),
8 => Ok(Deflated),
9 => Ok(EnhancedDeflatingUsingDeflate64),
10 => Ok(PkWareDataCompressionLIbraryImploding),
12 => Ok(Bzip2),
14 => Ok(Lzma),
16 => Ok(IbmZOsCmpsc),
18 => Ok(IbmTerse),
19 => Ok(IbmLz77z),
93 => Ok(Zstdandart),
94 => Ok(Mp3),
95 => Ok(Xz),
96 => Ok(Jpeg),
97 => Ok(WavPack),
98 => Ok(PpmdV1R1),
99 => Ok(Aex),
other => Err(other),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn order_zip_version() {
let v1_0 = ZipVersion::new(1, 0);
let v1_1 = ZipVersion::new(1, 1);
let v2_0 = ZipVersion::new(2, 0);
let v2_1 = ZipVersion::new(2, 1);
assert_eq!(v1_0, v1_0);
assert_ne!(v1_0, v1_1);
assert_ne!(v1_1, v2_1);
assert!(v1_1 > v1_0);
assert!(v2_0 > v1_0);
assert!(v2_0 > v1_1);
assert!(v2_1 > v2_0);
assert!(v2_0 <= v2_0);
assert!(v2_0 < v2_1);
assert!(v1_1 < v2_1);
assert!(v1_0 < v2_1);
assert_eq!(v1_0.max(v1_1), v1_1);
}
#[test]
fn parse_zip_version() {
assert_eq!(ZipVersion::from(30u8), ZipVersion::new(3, 0));
assert_eq!(ZipVersion::from(19u8), ZipVersion::new(1, 9));
assert_eq!(ZipVersion::from(123u8), ZipVersion::new(12, 3));
assert_eq!(ZipVersion::from(1u16), ZipVersion::new(1, 0));
assert_eq!(ZipVersion::from(258u16), ZipVersion::new(2, 1));
assert_eq!(ZipVersion::from(259u16), ZipVersion::new(3, 1));
}
#[test]
fn parse_compatible_file_attribute_infromation() {
use CompatibleFileAttributeInformation::*;
assert_eq!(CompatibleFileAttributeInformation::try_from(0).unwrap(), MsDosAndOs2);
assert_eq!(CompatibleFileAttributeInformation::try_from(19).unwrap(), OsX);
assert_eq!(CompatibleFileAttributeInformation::try_from(123), Err(123));
assert!(CompatibleFileAttributeInformation::try_from(1).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(2).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(3).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(4).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(5).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(6).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(7).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(8).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(9).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(10).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(11).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(12).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(13).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(14).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(15).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(16).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(17).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(18).is_ok());
assert!(CompatibleFileAttributeInformation::try_from(20).is_err());
assert!(CompatibleFileAttributeInformation::try_from(21).is_err());
assert!(CompatibleFileAttributeInformation::try_from(22).is_err());
assert!(CompatibleFileAttributeInformation::try_from(23).is_err());
assert!(CompatibleFileAttributeInformation::try_from(55).is_err());
assert!(CompatibleFileAttributeInformation::try_from(200).is_err());
assert!(CompatibleFileAttributeInformation::try_from(255).is_err());
}
#[test]
fn parse_minimum_feature_version() {
use MinimumFeatureVersion::*;
assert_eq!(ZipVersion::from(Default), ZipVersion::new(1, 0));
assert_eq!(ZipVersion::from(CompressedUsingDeflate64), ZipVersion::new(2, 1));
assert_eq!(ZipVersion::from(UsesZip64FormatExtentions), ZipVersion::new(4, 5));
assert_eq!(ZipVersion::from(EncryptedUsingDes), ZipVersion::new(5, 0));
assert_eq!(ZipVersion::from(CentralDirectoryEncryption), ZipVersion::new(6, 2));
assert_eq!(ZipVersion::from(CompressedUsingLzma), ZipVersion::new(6, 3));
}
#[test]
fn parse_compression_method() {
use CompressionMethod::*;
assert_eq!(CompressionMethod::try_from(0).unwrap(), Stored);
assert_eq!(CompressionMethod::try_from(9).unwrap(), EnhancedDeflatingUsingDeflate64);
assert_eq!(CompressionMethod::try_from(15), Err(15));
assert_eq!(CompressionMethod::try_from(93).unwrap(), Zstdandart);
assert_eq!(CompressionMethod::try_from(200), Err(200));
assert!(CompressionMethod::try_from(1).is_ok());
assert!(CompressionMethod::try_from(2).is_ok());
assert!(CompressionMethod::try_from(3).is_ok());
assert!(CompressionMethod::try_from(4).is_ok());
assert!(CompressionMethod::try_from(5).is_ok());
assert!(CompressionMethod::try_from(6).is_ok());
assert!(CompressionMethod::try_from(7).is_err());
assert!(CompressionMethod::try_from(8).is_ok());
assert!(CompressionMethod::try_from(9).is_ok());
assert!(CompressionMethod::try_from(10).is_ok());
assert!(CompressionMethod::try_from(11).is_err());
assert!(CompressionMethod::try_from(12).is_ok());
assert!(CompressionMethod::try_from(13).is_err());
assert!(CompressionMethod::try_from(14).is_ok());
assert!(CompressionMethod::try_from(16).is_ok());
assert!(CompressionMethod::try_from(17).is_err());
assert!(CompressionMethod::try_from(18).is_ok());
assert!(CompressionMethod::try_from(19).is_ok());
assert!(CompressionMethod::try_from(20).is_err());
assert!(CompressionMethod::try_from(21).is_err());
assert!(CompressionMethod::try_from(22).is_err());
assert!(CompressionMethod::try_from(92).is_err());
assert!(CompressionMethod::try_from(93).is_ok());
assert!(CompressionMethod::try_from(94).is_ok());
assert!(CompressionMethod::try_from(95).is_ok());
assert!(CompressionMethod::try_from(96).is_ok());
assert!(CompressionMethod::try_from(97).is_ok());
assert!(CompressionMethod::try_from(98).is_ok());
assert!(CompressionMethod::try_from(99).is_ok());
assert!(CompressionMethod::try_from(100).is_err());
assert!(CompressionMethod::try_from(200).is_err());
assert!(CompressionMethod::try_from(255).is_err());
assert!(!Stored.is_deprecated());
assert!(ReducedWithFactor3.is_deprecated());
}
}