zipng/zip/
configuration.rs

1use {
2    crate::{default, generic::never, ToPng, Zip},
3    std::{cmp::Ordering, fmt::Debug},
4};
5
6/// A reference to an entry in a [`Zip`] archive.
7#[non_exhaustive]
8pub struct ZipEntry<'name, 'body> {
9    pub name: &'name [u8],
10    pub body: &'body [u8],
11}
12
13/// Predicate function used for selecting entries in a [`Zip`] archive.
14pub type ZipEntryPredicate = fn(&ZipEntry) -> bool;
15
16/// Comparison function used for ordering entries in a [`Zip`] archive.
17pub type ZipEntryComparison = fn(&ZipEntry, &ZipEntry) -> Ordering;
18
19/// Sort file by name, first based on the number of slash `/` path separator
20/// characters, then lexicographically.
21pub static SORT_BY_NAME: ZipEntryComparison = |a, b| {
22    (
23        a.name.iter().filter(|&&c| c == b'/').collect::<Vec<_>>(),
24        a.name,
25    )
26        .cmp(&(
27            b.name.iter().filter(|&&c| c == b'/').collect::<Vec<_>>(),
28            b.name,
29        ))
30};
31
32/// Sorts files lexicographically based on their content, then applies
33/// [`SORT_BY_NAME`].
34pub static SORT_BY_BODY: ZipEntryComparison = |a, b| {
35    (a.body, a.name)
36        .cmp(&(b.body, b.name))
37        .then_with(|| SORT_BY_NAME(a, b))
38};
39
40/// Pins the `mimetype` magic header file used by EPUB and OpenDocument.
41pub static PIN_MIMETYPE: ZipEntryPredicate =
42    |file| file.name == b"mimetype" && file.body.is_ascii() && file.body.len() <= 0xFF;
43
44/// Configuration determining how the [`Zip`] archive is serialized.
45#[derive(Clone)]
46#[non_exhaustive]
47pub struct ZipConfiguration {
48    /// Whether all body data must be stored contiguously.
49    pub body_contiguous: bool,
50    /// Align and pad all body data into blocks of this many bytes.
51    pub body_alignment: usize,
52    /// Comparison function used to determine file body ordering.
53    pub sort_body_by: Option<ZipEntryComparison>,
54    /// Comparison function used to determine file metadata ordering.
55    pub sort_meta_by: Option<ZipEntryComparison>,
56    /// Predicate function used to determine files that should be pinned to the
57    /// top of the archive without alignment or padding.
58    pub pin_header_with: Option<ZipEntryPredicate>,
59}
60
61impl ZipConfiguration {
62    pub fn new(f: fn(&mut Self)) -> Self {
63        let mut zip_configuration = default();
64        f(&mut zip_configuration);
65
66        zip_configuration
67    }
68}
69
70impl Debug for ZipConfiguration {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        f.debug_struct("ZipConfiguration")
73            .field("body_contiguous", &self.body_contiguous)
74            .field("body_alignment", &self.body_alignment)
75            .field(
76                "sort_body_by",
77                self.sort_body_by.map(|_| &Some(())).unwrap_or(&None),
78            )
79            .field(
80                "sort_meta_by",
81                self.sort_meta_by.map(|_| &Some(())).unwrap_or(&None),
82            )
83            .finish()
84    }
85}
86
87impl Default for ZipConfiguration {
88    fn default() -> Self {
89        Self {
90            body_contiguous: true,
91            body_alignment: 1024,
92            sort_body_by: SORT_BY_BODY.into(),
93            sort_meta_by: SORT_BY_NAME.into(),
94            pin_header_with: PIN_MIMETYPE.into(),
95        }
96    }
97}
98
99impl Zip {
100    /// Configure this archive to avoid including anything extraneous.
101    pub fn minimal(&mut self) {
102        todo!()
103    }
104
105    /// Configures this archive to store file contents contiguously, aligned
106    /// and padded to to 1024-byte blocks.
107    pub fn blocks(&mut self) {
108        todo!()
109    }
110
111    /// Configures this archive to create a polyglot PNG/ZIP file which can also
112    /// be interpreted as a PNG image image file displaying the content of the
113    /// first PNG image file that the archive contains.
114    pub fn covered(&mut self) {
115        todo!()
116    }
117
118    /// Configures this archive to create a polyglot PNG/ZIP file which can also
119    /// be interpreted as a PNG image with all of the file contents displayed in
120    /// the image data.
121    pub fn uncovered(&mut self) {
122        todo!()
123    }
124}