Skip to main content

zip/extra_fields/
mod.rs

1//! Types for extra fields
2
3use core::fmt::Display;
4
5mod aex_encryption;
6mod custom_extra_field;
7mod data_stream_alignment;
8mod extended_timestamp;
9mod extra_field;
10mod ntfs;
11mod zip64_extended_information;
12mod zipinfo_utf8;
13
14// re-export extra fields
15#[cfg(feature = "aes-crypto")]
16pub use aex_encryption::AexEncryption;
17pub use custom_extra_field::CustomExtraField;
18pub use data_stream_alignment::DataStreamAlignment;
19pub use extended_timestamp::ExtendedTimestamp;
20pub use extra_field::{ExtraField, ExtraFields};
21pub use ntfs::Ntfs;
22pub use zip64_extended_information::{Zip64ExtendedInformation, Zip64Sizes};
23pub use zipinfo_utf8::UnicodeExtraField;
24
25// re-export
26pub use crate::format::extra_fields::EXTRA_FIELD_MAPPING;
27use crate::format::extra_fields::ExtraFieldId;
28
29/// Internal extra-field identifiers (`u16` tags) recognized by this crate.
30///
31/// This enum is crate-private and used for matching/dispatch on raw ZIP extra
32/// field IDs. It is distinct from [`ExtraField`], which represents parsed,
33/// public extra-field data structures.
34#[repr(u16)]
35#[derive(Debug, Copy, Clone, PartialEq, Eq)]
36#[non_exhaustive]
37pub(crate) enum UsedExtraField {
38    /// ZIP64 extended information extra field
39    Zip64ExtendedInfo = ExtraFieldId::Zip64ExtendedInfo.as_u16(),
40    /// NTFS
41    Ntfs = ExtraFieldId::Ntfs.as_u16(),
42    /// extended timestamp
43    /// from <https://libzip.org/specifications/extrafld.txt>
44    ExtendedTimestamp = ExtraFieldId::ExtendedTimestamp.as_u16(),
45    /// Info-ZIP Unicode Comment Extra Field
46    UnicodeComment = ExtraFieldId::UnicodeComment.as_u16(),
47    /// Info-ZIP Unicode Path Extra Field
48    UnicodePath = ExtraFieldId::UnicodePath.as_u16(),
49    /// AE-x encryption structure
50    AeXEncryption = ExtraFieldId::AeXEncryption.as_u16(),
51    /// Data Stream Alignment (Apache Commons-Compress)
52    DataStreamAlignment = ExtraFieldId::DataStreamAlignment.as_u16(),
53}
54
55impl UsedExtraField {
56    pub const fn to_le_bytes(self) -> [u8; 2] {
57        let field_u16 = self.as_u16();
58        field_u16.to_le_bytes()
59    }
60
61    pub const fn as_u16(self) -> u16 {
62        self as u16
63    }
64}
65
66impl From<UsedExtraField> for u16 {
67    fn from(value: UsedExtraField) -> Self {
68        value.as_u16()
69    }
70}
71
72impl Display for UsedExtraField {
73    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
74        write!(f, "0x{:04X}", *self as u16)
75    }
76}
77
78macro_rules! extra_field_match {
79    ($x:expr, $( $variant:path ),+ $(,)?) => {
80        match $x {
81            $(
82                v if v == $variant as u16 => Ok($variant),
83            )+
84            _ => Err(()),
85        }
86    };
87}
88
89impl TryFrom<u16> for UsedExtraField {
90    type Error = ();
91
92    fn try_from(value: u16) -> Result<Self, Self::Error> {
93        extra_field_match!(
94            value,
95            UsedExtraField::Zip64ExtendedInfo,
96            UsedExtraField::Ntfs,
97            UsedExtraField::ExtendedTimestamp,
98            UsedExtraField::UnicodeComment,
99            UsedExtraField::UnicodePath,
100            UsedExtraField::DataStreamAlignment,
101            UsedExtraField::AeXEncryption,
102        )
103    }
104}