1use std::fmt::Debug;
2use std::convert::TryFrom;
3use enumflags2::BitFlags;
4use crate::error::*;
5
6pub type Id = [u8; 2];
7pub type SubfieldId = [u8; 2];
8pub type Name = String;
9pub type Comment = String;
10pub type Crc16 = u16;
11pub type Crc32 = u32;
12
13#[derive(BitFlags, Debug, Copy, Clone, PartialEq)]
14#[repr(u8)]
15pub enum Flags {
16 Text = 1,
17 HeaderCrc = 2,
18 Extra = 4,
19 Name = 8,
20 Comment = 16,
21 Reserved0 = 32,
22 Reserved1 = 64,
23 Reserved2 = 128,
24}
25
26#[derive(BitFlags, Debug, Copy, Clone, PartialEq)]
27#[repr(u8)]
28pub enum CompressionFlags {
29 BestCompression = 2,
30 FastestCompression = 4,
31}
32
33#[derive(Debug, Copy, Clone, PartialEq)]
34#[repr(u8)]
35pub enum CompressionMethod {
36 Reserved0 = 0,
37 Reserved1 = 1,
38 Reserved2 = 2,
39 Reserved3 = 3,
40 Reserved4 = 4,
41 Reserved5 = 5,
42 Reserved6 = 6,
43 Reserved7 = 7,
44 Deflate = 8,
45}
46
47impl TryFrom<u8> for CompressionMethod {
48 type Error = Error;
49 fn try_from(byte: u8) -> std::result::Result<Self, Self::Error> {
50 use CompressionMethod::*;
51 match byte {
52 0 => Ok(Reserved0),
53 1 => Ok(Reserved1),
54 2 => Ok(Reserved2),
55 3 => Ok(Reserved3),
56 4 => Ok(Reserved4),
57 5 => Ok(Reserved5),
58 6 => Ok(Reserved6),
59 7 => Ok(Reserved7),
60 8 => Ok(Deflate),
61 _ => Err(Error(ErrorKind::InvalidCompressionMethod, None)),
62 }
63 }
64}
65
66impl Default for CompressionMethod {
67 fn default() -> Self { CompressionMethod::Deflate }
68}
69
70#[derive(Debug, Copy, Clone, PartialEq)]
71#[repr(u8)]
72pub enum OperatingSystem {
73 Fat = 0,
74 Amiga = 1,
75 Vms = 2,
76 Unix = 3,
77 VmCms = 4,
78 Atari = 5,
79 Hpfs = 6,
80 Macintosh = 7,
81 ZSystem = 8,
82 Cpm = 9,
83 Tops = 10,
84 Ntfs = 11,
85 Qdos = 12,
86 Acorn = 13,
87 Unknown = 255,
88}
89
90impl Default for OperatingSystem {
91 fn default() -> Self { OperatingSystem::Unknown }
92}
93
94impl TryFrom<u8> for OperatingSystem {
95 type Error = Error;
96 fn try_from(byte: u8) -> std::result::Result<Self, Self::Error> {
97 use OperatingSystem::*;
98 match byte {
99 0 => Ok(Fat),
100 1 => Ok(Amiga),
101 2 => Ok(Vms),
102 3 => Ok(Unix),
103 4 => Ok(VmCms),
104 5 => Ok(Atari),
105 6 => Ok(Hpfs),
106 7 => Ok(Macintosh),
107 8 => Ok(ZSystem),
108 9 => Ok(Cpm),
109 10 => Ok(Tops),
110 11 => Ok(Ntfs),
111 12 => Ok(Qdos),
112 13 => Ok(Acorn),
113 155 => Ok(Unknown),
114 _ => Err(Error(ErrorKind::InvalidCompressionMethod, None)),
115 }
116 }
117}
118
119#[derive(Debug, Copy, Clone, PartialEq)]
120pub enum SubFieldType {
121 ApolloFileTypeInformation,
122}
123
124impl From<SubFieldType> for [u8; 2] {
125 fn from(t: SubFieldType) -> Self {
126 use SubFieldType::*;
127 match t {
128 ApolloFileTypeInformation => [0x41, 0x70], }
130 }
131}
132
133impl Header {
134 pub const GZIP_ID: [u8; 2] = [0x1f, 0x8b];
135}
136
137#[derive(Default, Debug, Clone)]
138pub struct Extra {
139 pub length: u16,
140 pub subfield_id: SubfieldId,
141 pub data_length: u16,
142 pub data: Vec<u8>,
143}
144
145#[derive(Default, Debug, Clone)]
146pub struct Header {
147 pub id: Id,
148 pub compression_method: CompressionMethod,
149 pub flags: BitFlags<Flags>,
150 pub modification_time: u32,
151 pub compression_flags: BitFlags<CompressionFlags>,
152 pub operating_system: OperatingSystem,
153 pub extra: Option<Extra>,
154 pub name: Option<Name>,
155 pub comment: Option<Comment>,
156 pub crc: Option<Crc16>,
157}
158
159#[derive(Default, Clone)]
160pub struct Member {
161 pub header: Header,
162 pub data: Vec<u8>,
163 pub crc: Crc32,
164 pub input_size: u32,
165}
166
167impl Debug for Member {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
169 f.debug_struct("GZIP Member")
170 .field("Header", &self.header)
171 .field("Read Data Size", &self.data.len())
172 .field("Input Size", &self.input_size)
173 .field("CRC32", &self.crc)
174 .finish()
175 }
176}