rc_zip/parse/
version.rs

1use ownable::{IntoOwned, ToOwned};
2use std::fmt;
3use winnow::{binary::le_u8, seq, PResult, Parser, Partial};
4
5/// A zip version (either created by, or required when reading an archive).
6///
7/// Versions determine which features are supported by a tool, and
8/// which features are required when reading a file.
9///
10/// For more information, see the [.ZIP Application Note](https://support.pkware.com/display/PKZIP/APPNOTE), section 4.4.2.
11#[derive(Clone, Copy, ToOwned, IntoOwned, PartialEq, Eq, Hash)]
12pub struct Version {
13    /// The host system on which
14    pub host_system: HostSystem,
15
16    /// Integer version, e.g. 45 for Zip version 4.5
17    /// See APPNOTE, section 4.4.2.1
18    pub version: u8,
19}
20
21impl fmt::Debug for Version {
22    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23        write!(f, "{:?} v{}", self.host_system, self.version)
24    }
25}
26
27impl Version {
28    /// Parse a version from a byte slice
29    pub fn parser(i: &mut Partial<&'_ [u8]>) -> PResult<Self> {
30        seq! {Self {
31            version: le_u8,
32            host_system: le_u8.map(HostSystem::from),
33        }}
34        .parse_next(i)
35    }
36}
37
38/// System on which an archive was created, as encoded into a version u16.
39///
40/// See APPNOTE, section 4.4.2.2
41#[derive(Debug, Clone, Copy, ToOwned, IntoOwned, PartialEq, Eq, Hash)]
42#[repr(u8)]
43pub enum HostSystem {
44    /// MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)
45    MsDos = Self::MS_DOS,
46
47    /// Amiga
48    Amiga = Self::AMIGA,
49
50    /// OpenVMS
51    OpenVms = Self::OPEN_VMS,
52
53    /// UNIX
54    Unix = Self::UNIX,
55
56    /// VM/CMS
57    VmCms = Self::VM_CMS,
58
59    /// Atari ST
60    AtariSt = Self::ATARI_ST,
61
62    /// OS/2 H.P.F.S
63    Os2Hpfs = Self::OS2_HPFS,
64
65    /// Macintosh (see `Osx`)
66    Macintosh = Self::MACINTOSH,
67
68    /// Z-System
69    ZSystem = Self::Z_SYSTEM,
70
71    /// CP/M
72    CpM = Self::CP_M,
73
74    /// Windows NTFS
75    WindowsNtfs = Self::WINDOWS_NTFS,
76
77    /// MVS (OS/390 - Z/OS)
78    Mvs = Self::MVS,
79
80    /// VSE
81    Vse = Self::VSE,
82
83    /// Acorn Risc
84    AcornRisc = Self::ACORN_RISC,
85
86    /// VFAT
87    Vfat = Self::VFAT,
88
89    /// alternate MVS
90    AlternateMvs = Self::ALTERNATE_MVS,
91
92    /// BeOS
93    BeOs = Self::BE_OS,
94
95    /// Tandem
96    Tandem = Self::TANDEM,
97
98    /// OS/400
99    Os400 = Self::OS400,
100
101    /// OS X (Darwin)
102    Osx = Self::OSX,
103
104    /// Unknown host system
105    ///
106    /// Values 20 through 255 are currently unused, as of
107    /// APPNOTE.TXT 6.3.10
108    Unknown(u8),
109}
110
111impl HostSystem {
112    const MS_DOS: u8 = 0;
113    const AMIGA: u8 = 1;
114    const OPEN_VMS: u8 = 2;
115    const UNIX: u8 = 3;
116    const VM_CMS: u8 = 4;
117    const ATARI_ST: u8 = 5;
118    const OS2_HPFS: u8 = 6;
119    const MACINTOSH: u8 = 7;
120    const Z_SYSTEM: u8 = 8;
121    const CP_M: u8 = 9;
122    const WINDOWS_NTFS: u8 = 10;
123    const MVS: u8 = 11;
124    const VSE: u8 = 12;
125    const ACORN_RISC: u8 = 13;
126    const VFAT: u8 = 14;
127    const ALTERNATE_MVS: u8 = 15;
128    const BE_OS: u8 = 16;
129    const TANDEM: u8 = 17;
130    const OS400: u8 = 18;
131    const OSX: u8 = 19;
132}
133
134impl From<u8> for HostSystem {
135    fn from(u: u8) -> Self {
136        match u {
137            Self::MS_DOS => Self::MsDos,
138            Self::AMIGA => Self::Amiga,
139            Self::OPEN_VMS => Self::OpenVms,
140            Self::UNIX => Self::Unix,
141            Self::VM_CMS => Self::VmCms,
142            Self::ATARI_ST => Self::AtariSt,
143            Self::OS2_HPFS => Self::Os2Hpfs,
144            Self::MACINTOSH => Self::Macintosh,
145            Self::Z_SYSTEM => Self::ZSystem,
146            Self::CP_M => Self::CpM,
147            Self::WINDOWS_NTFS => Self::WindowsNtfs,
148            Self::MVS => Self::Mvs,
149            Self::VSE => Self::Vse,
150            Self::ACORN_RISC => Self::AcornRisc,
151            Self::VFAT => Self::Vfat,
152            Self::ALTERNATE_MVS => Self::AlternateMvs,
153            Self::BE_OS => Self::BeOs,
154            Self::TANDEM => Self::Tandem,
155            Self::OS400 => Self::Os400,
156            Self::OSX => Self::Osx,
157            u => Self::Unknown(u),
158        }
159    }
160}
161
162impl From<HostSystem> for u8 {
163    fn from(host_system: HostSystem) -> Self {
164        match host_system {
165            HostSystem::MsDos => HostSystem::MS_DOS,
166            HostSystem::Amiga => HostSystem::AMIGA,
167            HostSystem::OpenVms => HostSystem::OPEN_VMS,
168            HostSystem::Unix => HostSystem::UNIX,
169            HostSystem::VmCms => HostSystem::VM_CMS,
170            HostSystem::AtariSt => HostSystem::ATARI_ST,
171            HostSystem::Os2Hpfs => HostSystem::OS2_HPFS,
172            HostSystem::Macintosh => HostSystem::MACINTOSH,
173            HostSystem::ZSystem => HostSystem::Z_SYSTEM,
174            HostSystem::CpM => HostSystem::CP_M,
175            HostSystem::WindowsNtfs => HostSystem::WINDOWS_NTFS,
176            HostSystem::Mvs => HostSystem::MVS,
177            HostSystem::Vse => HostSystem::VSE,
178            HostSystem::AcornRisc => HostSystem::ACORN_RISC,
179            HostSystem::Vfat => HostSystem::VFAT,
180            HostSystem::AlternateMvs => HostSystem::ALTERNATE_MVS,
181            HostSystem::BeOs => HostSystem::BE_OS,
182            HostSystem::Tandem => HostSystem::TANDEM,
183            HostSystem::Os400 => HostSystem::OS400,
184            HostSystem::Osx => HostSystem::OSX,
185            HostSystem::Unknown(u) => u,
186        }
187    }
188}