Skip to content

Commit 3fd6bfb

Browse files
committed
✨ Add Reserved/Private variants to Compression, Encryption, CipherMode, DataKind enums
1 parent 7f12664 commit 3fd6bfb

6 files changed

Lines changed: 175 additions & 29 deletions

File tree

cli/src/command/diff.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,9 @@ fn compare_entry<T: AsRef<[u8]>>(
335335
DataKind::HardLink => {
336336
println!("{}", DiffKind::TypeMismatch.display(path_str));
337337
}
338+
_ => {
339+
println!("{}", DiffKind::TypeMismatch.display(path_str));
340+
}
338341
}
339342
Ok(())
340343
}

cli/src/command/list.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ impl TableRow {
451451
),
452452
DataKind::Directory => EntryType::Directory(entry.name().to_string()),
453453
DataKind::File => EntryType::File(entry.name().to_string()),
454+
_ => EntryType::File(entry.name().to_string()),
454455
},
455456
// Only collect xattrs if needed
456457
xattrs: if collect.xattrs {

lib/src/entry/header.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,10 @@ impl EntryHeader {
122122
let mut data = Vec::with_capacity(6 + name.len());
123123
data.push(self.major);
124124
data.push(self.minor);
125-
data.push(self.data_kind as u8);
126-
data.push(self.compression as u8);
127-
data.push(self.encryption as u8);
128-
data.push(self.cipher_mode as u8);
125+
data.push(self.data_kind.to_byte());
126+
data.push(self.compression.to_byte());
127+
data.push(self.encryption.to_byte());
128+
data.push(self.cipher_mode.to_byte());
129129
data.extend_from_slice(name);
130130
data
131131
}
@@ -272,9 +272,9 @@ impl SolidHeader {
272272
[
273273
self.major,
274274
self.minor,
275-
self.compression as u8,
276-
self.encryption as u8,
277-
self.cipher_mode as u8,
275+
self.compression.to_byte(),
276+
self.encryption.to_byte(),
277+
self.cipher_mode.to_byte(),
278278
]
279279
}
280280

lib/src/entry/options.rs

Lines changed: 146 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,45 @@ mod private {
132132

133133
/// Compression method.
134134
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
135-
#[repr(u8)]
136135
pub enum Compression {
137136
/// Do not apply any compression.
138-
No = 0,
137+
No,
139138
/// Zlib format.
140-
Deflate = 1,
139+
Deflate,
141140
/// ZStandard format.
142-
ZStandard = 2,
141+
ZStandard,
143142
/// Xz format.
144-
XZ = 4,
143+
XZ,
144+
/// Value reserved for future PNA specification (raw value < 128).
145+
Reserved(u8),
146+
/// Application-specific private value (raw value >= 128).
147+
Private(u8),
148+
}
149+
150+
impl Compression {
151+
/// Serialize this compression method to its u8 representation.
152+
#[inline]
153+
pub const fn to_byte(self) -> u8 {
154+
match self {
155+
Self::No => 0,
156+
Self::Deflate => 1,
157+
Self::ZStandard => 2,
158+
Self::XZ => 4,
159+
Self::Reserved(v) | Self::Private(v) => v,
160+
}
161+
}
162+
163+
/// Returns `true` if this is a reserved value.
164+
#[inline]
165+
pub const fn is_reserved(self) -> bool {
166+
matches!(self, Self::Reserved(_))
167+
}
168+
169+
/// Returns `true` if this is a private value.
170+
#[inline]
171+
pub const fn is_private(self) -> bool {
172+
matches!(self, Self::Private(_))
173+
}
145174
}
146175

147176
impl TryFrom<u8> for Compression {
@@ -154,7 +183,8 @@ impl TryFrom<u8> for Compression {
154183
1 => Ok(Self::Deflate),
155184
2 => Ok(Self::ZStandard),
156185
4 => Ok(Self::XZ),
157-
value => Err(UnknownValueError(value)),
186+
v if v < 128 => Ok(Self::Reserved(v)),
187+
v => Ok(Self::Private(v)),
158188
}
159189
}
160190
}
@@ -291,14 +321,42 @@ impl<T: AsRef<[u8]>> From<T> for Password {
291321

292322
/// Encryption algorithm.
293323
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
294-
#[repr(u8)]
295324
pub enum Encryption {
296325
/// Do not apply any encryption.
297-
No = 0,
326+
No,
298327
/// Aes algorithm.
299-
Aes = 1,
328+
Aes,
300329
/// Camellia algorithm.
301-
Camellia = 2,
330+
Camellia,
331+
/// Value reserved for future PNA specification (raw value < 128).
332+
Reserved(u8),
333+
/// Application-specific private value (raw value >= 128).
334+
Private(u8),
335+
}
336+
337+
impl Encryption {
338+
/// Serialize this encryption method to its u8 representation.
339+
#[inline]
340+
pub const fn to_byte(self) -> u8 {
341+
match self {
342+
Self::No => 0,
343+
Self::Aes => 1,
344+
Self::Camellia => 2,
345+
Self::Reserved(v) | Self::Private(v) => v,
346+
}
347+
}
348+
349+
/// Returns `true` if this is a reserved value.
350+
#[inline]
351+
pub const fn is_reserved(self) -> bool {
352+
matches!(self, Self::Reserved(_))
353+
}
354+
355+
/// Returns `true` if this is a private value.
356+
#[inline]
357+
pub const fn is_private(self) -> bool {
358+
matches!(self, Self::Private(_))
359+
}
302360
}
303361

304362
impl TryFrom<u8> for Encryption {
@@ -310,19 +368,47 @@ impl TryFrom<u8> for Encryption {
310368
0 => Ok(Self::No),
311369
1 => Ok(Self::Aes),
312370
2 => Ok(Self::Camellia),
313-
value => Err(UnknownValueError(value)),
371+
v if v < 128 => Ok(Self::Reserved(v)),
372+
v => Ok(Self::Private(v)),
314373
}
315374
}
316375
}
317376

318377
/// Cipher mode of encryption algorithm.
319378
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
320-
#[repr(u8)]
321379
pub enum CipherMode {
322380
/// Cipher Block Chaining mode.
323-
CBC = 0,
381+
CBC,
324382
/// Counter mode.
325-
CTR = 1,
383+
CTR,
384+
/// Value reserved for future PNA specification (raw value < 128).
385+
Reserved(u8),
386+
/// Application-specific private value (raw value >= 128).
387+
Private(u8),
388+
}
389+
390+
impl CipherMode {
391+
/// Serialize this cipher mode to its u8 representation.
392+
#[inline]
393+
pub const fn to_byte(self) -> u8 {
394+
match self {
395+
Self::CBC => 0,
396+
Self::CTR => 1,
397+
Self::Reserved(v) | Self::Private(v) => v,
398+
}
399+
}
400+
401+
/// Returns `true` if this is a reserved value.
402+
#[inline]
403+
pub const fn is_reserved(self) -> bool {
404+
matches!(self, Self::Reserved(_))
405+
}
406+
407+
/// Returns `true` if this is a private value.
408+
#[inline]
409+
pub const fn is_private(self) -> bool {
410+
matches!(self, Self::Private(_))
411+
}
326412
}
327413

328414
impl TryFrom<u8> for CipherMode {
@@ -333,7 +419,8 @@ impl TryFrom<u8> for CipherMode {
333419
match value {
334420
0 => Ok(Self::CBC),
335421
1 => Ok(Self::CTR),
336-
value => Err(UnknownValueError(value)),
422+
v if v < 128 => Ok(Self::Reserved(v)),
423+
v => Ok(Self::Private(v)),
337424
}
338425
}
339426
}
@@ -472,17 +559,46 @@ impl HashAlgorithm {
472559
/// Each variant determines how the entry's data should be interpreted
473560
/// and how the entry should be extracted to the filesystem.
474561
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
475-
#[repr(u8)]
476562
pub enum DataKind {
477563
/// Regular file. Entry data contains the file contents.
478-
File = 0,
564+
File,
479565
/// Directory. Entry has no data content.
480-
Directory = 1,
566+
Directory,
481567
/// Symbolic link. Entry data contains the UTF-8 encoded link target path.
482-
SymbolicLink = 2,
568+
SymbolicLink,
483569
/// Hard link. Entry data contains the UTF-8 encoded path of the target entry
484570
/// within the same archive.
485-
HardLink = 3,
571+
HardLink,
572+
/// Value reserved for future PNA specification (raw value < 128).
573+
Reserved(u8),
574+
/// Application-specific private value (raw value >= 128).
575+
Private(u8),
576+
}
577+
578+
impl DataKind {
579+
/// Serialize this data kind to its u8 representation.
580+
#[inline]
581+
pub const fn to_byte(self) -> u8 {
582+
match self {
583+
Self::File => 0,
584+
Self::Directory => 1,
585+
Self::SymbolicLink => 2,
586+
Self::HardLink => 3,
587+
Self::Reserved(v) | Self::Private(v) => v,
588+
}
589+
}
590+
591+
/// Returns `true` if this is a reserved value.
592+
#[inline]
593+
pub const fn is_reserved(self) -> bool {
594+
matches!(self, Self::Reserved(_))
595+
}
596+
597+
/// Returns `true` if this is a private value.
598+
#[inline]
599+
pub const fn is_private(self) -> bool {
600+
matches!(self, Self::Private(_))
601+
}
486602
}
487603

488604
impl TryFrom<u8> for DataKind {
@@ -495,7 +611,8 @@ impl TryFrom<u8> for DataKind {
495611
1 => Ok(Self::Directory),
496612
2 => Ok(Self::SymbolicLink),
497613
3 => Ok(Self::HardLink),
498-
value => Err(UnknownValueError(value)),
614+
v if v < 128 => Ok(Self::Reserved(v)),
615+
v => Ok(Self::Private(v)),
499616
}
500617
}
501618
}
@@ -778,7 +895,10 @@ impl WriteOptionsBuilder {
778895
match self.encryption {
779896
Encryption::Aes => CipherAlgorithm::Aes,
780897
Encryption::Camellia => CipherAlgorithm::Camellia,
781-
Encryption::No => unreachable!(),
898+
_ => panic!(
899+
"unsupported encryption method for writing: {:?}",
900+
self.encryption
901+
),
782902
},
783903
self.cipher_mode,
784904
))
@@ -791,6 +911,10 @@ impl WriteOptionsBuilder {
791911
Compression::Deflate => Compress::Deflate(self.compression_level.into()),
792912
Compression::ZStandard => Compress::ZStandard(self.compression_level.into()),
793913
Compression::XZ => Compress::XZ(self.compression_level.into()),
914+
_ => panic!(
915+
"unsupported compression method for writing: {:?}",
916+
self.compression
917+
),
794918
},
795919
cipher,
796920
}

lib/src/entry/read.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ pub(crate) fn decrypt_reader<R: Read>(
5858
}
5959
}
6060
}
61+
_ => {
62+
return Err(io::Error::new(
63+
io::ErrorKind::Unsupported,
64+
format!("unsupported encryption method: {encryption:?}"),
65+
))
66+
}
6167
})
6268
}
6369

@@ -76,6 +82,12 @@ pub(crate) fn decompress_reader<R: Read>(
7682
}
7783
Compression::ZStandard => DecompressReader::ZStd(zstd::Decoder::with_buffer(reader)?),
7884
Compression::XZ => DecompressReader::Xz(liblzma::bufread::XzDecoder::new(reader)),
85+
_ => {
86+
return Err(io::Error::new(
87+
io::ErrorKind::Unsupported,
88+
format!("unsupported compression method: {compression:?}"),
89+
))
90+
}
7991
})
8092
}
8193

lib/src/entry/write.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,12 @@ fn encryption_writer<W: Write>(
161161
..
162162
},
163163
}) => CipherWriter::CtrCamellia(Ctr128BEWriter::new(writer, key.as_bytes(), iv)?),
164+
Some(WriteCipher { context, .. }) => {
165+
return Err(io::Error::new(
166+
io::ErrorKind::Unsupported,
167+
format!("unsupported cipher mode for writing: {:?}", context.mode),
168+
))
169+
}
164170
})
165171
}
166172

0 commit comments

Comments
 (0)