1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use crate::format::*;
use nom::{combinator::map, number::streaming::le_u16};
use std::fmt;

/// A zip version (either created by, or required when reading an archive).
///
/// Versions determine which features are supported by a tool, and
/// which features are required when reading a file.
///
/// For more information, see the [.ZIP Application Note](https://support.pkware.com/display/PKZIP/APPNOTE), section 4.4.2.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct Version(pub u16);

impl fmt::Debug for Version {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{:?} v{}.{}",
            self.host_system(),
            self.major(),
            self.minor()
        )
    }
}

impl Version {
    /// Parse a version from a byte slice
    pub fn parse<'a>(i: &'a [u8]) -> parse::Result<'a, Self> {
        map(le_u16, |v| Self(v))(i)
    }

    /// Identifies the host system on which the zip attributes are compatible.
    pub fn host_system(&self) -> HostSystem {
        match self.host() {
            0 => HostSystem::MsDos,
            1 => HostSystem::Amiga,
            2 => HostSystem::OpenVms,
            3 => HostSystem::Unix,
            4 => HostSystem::VmCms,
            5 => HostSystem::AtariSt,
            6 => HostSystem::Os2Hpfs,
            7 => HostSystem::Macintosh,
            8 => HostSystem::ZSystem,
            9 => HostSystem::CpM,
            10 => HostSystem::WindowsNtfs,
            11 => HostSystem::Mvs,
            12 => HostSystem::Vse,
            13 => HostSystem::AcornRisc,
            14 => HostSystem::Vfat,
            15 => HostSystem::AlternateMvs,
            16 => HostSystem::BeOs,
            17 => HostSystem::Tandem,
            18 => HostSystem::Os400,
            19 => HostSystem::Osx,
            n => HostSystem::Unknown(n),
        }
    }

    /// Integer host system
    pub fn host(&self) -> u8 {
        (self.0 >> 8) as u8
    }

    /// Integer version, e.g. 45 for Zip version 4.5
    pub fn version(&self) -> u8 {
        (self.0 & 0xff) as u8
    }

    /// ZIP specification major version
    ///
    /// See APPNOTE, section 4.4.2.1
    pub fn major(&self) -> u32 {
        self.version() as u32 / 10
    }

    /// ZIP specification minor version
    ///
    /// See APPNOTE, section 4.4.2.1
    pub fn minor(&self) -> u32 {
        self.version() as u32 % 10
    }
}

/// System on which an archive was created, as encoded into a version u16.
///
/// See APPNOTE, section 4.4.2.2
#[derive(Debug)]
pub enum HostSystem {
    /// MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)
    MsDos,
    /// Amiga
    Amiga,
    /// OpenVMS
    OpenVms,
    /// UNIX
    Unix,
    /// VM/CMS
    VmCms,
    /// Atari ST
    AtariSt,
    /// OS/2 H.P.F.S
    Os2Hpfs,
    /// Macintosh (see `Osx`)
    Macintosh,
    /// Z-System
    ZSystem,
    /// CP/M
    CpM,
    /// Windows NTFS
    WindowsNtfs,
    /// MVS (OS/390 - Z/OS)
    Mvs,
    /// VSE
    Vse,
    /// Acorn Risc
    AcornRisc,
    /// VFAT
    Vfat,
    /// alternate MVS
    AlternateMvs,
    /// BeOS
    BeOs,
    /// Tandem
    Tandem,
    /// OS/400
    Os400,
    /// OS X (Darwin)
    Osx,
    /// Unknown host system
    ///
    /// Values 20 through 255 are currently unused, as of
    /// APPNOTE.TXT 6.3.6 (April 26, 2019)
    Unknown(u8),
}