Skip to main content

async_zip/entry/
builder.rs

1// Copyright (c) 2022 Harry [Majored] [hello@majored.pw]
2// MIT License (https://github.com/Majored/rs-async-zip/blob/main/LICENSE)
3
4use crate::entry::ZipEntry;
5use crate::spec::{attribute::AttributeCompatibility, header::ExtraField, Compression};
6use crate::{date::ZipDateTime, string::ZipString};
7
8/// A builder for [`ZipEntry`].
9pub struct ZipEntryBuilder(pub(crate) ZipEntry);
10
11impl From<ZipEntry> for ZipEntryBuilder {
12    fn from(entry: ZipEntry) -> Self {
13        Self(entry)
14    }
15}
16
17impl ZipEntryBuilder {
18    /// Constructs a new builder which defines the raw underlying data of a ZIP entry.
19    ///
20    /// A filename and compression method are needed to construct the builder as minimal parameters.
21    pub fn new(filename: ZipString, compression: Compression) -> Self {
22        Self(ZipEntry::new(filename, compression))
23    }
24
25    /// Sets the entry's filename.
26    pub fn filename(mut self, filename: ZipString) -> Self {
27        self.0.filename = filename;
28        self
29    }
30
31    /// Sets the entry's compression method.
32    pub fn compression(mut self, compression: Compression) -> Self {
33        self.0.compression = compression;
34        self
35    }
36
37    /// Set a size hint for the file, to be written into the local file header.
38    /// Unlikely to be useful except for the case of streaming files to be Store'd.
39    /// This size hint does not affect the central directory, nor does it affect whole files.
40    pub fn size<N: Into<u64>, M: Into<u64>>(mut self, compressed_size: N, uncompressed_size: M) -> Self {
41        self.0.compressed_size = compressed_size.into();
42        self.0.uncompressed_size = uncompressed_size.into();
43        self
44    }
45
46    /// Set the deflate compression option.
47    ///
48    /// If the compression type isn't deflate, this option has no effect.
49    #[cfg(any(feature = "deflate", feature = "bzip2", feature = "zstd", feature = "lzma", feature = "xz"))]
50    pub fn deflate_option(mut self, option: crate::DeflateOption) -> Self {
51        self.0.compression_level = option.into_level();
52        self
53    }
54
55    /// Sets the entry's attribute host compatibility.
56    pub fn attribute_compatibility(mut self, compatibility: AttributeCompatibility) -> Self {
57        self.0.attribute_compatibility = compatibility;
58        self
59    }
60
61    /// Sets the entry's last modification date.
62    pub fn last_modification_date(mut self, date: ZipDateTime) -> Self {
63        self.0.last_modification_date = date;
64        self
65    }
66
67    /// Sets the entry's internal file attribute.
68    pub fn internal_file_attribute(mut self, attribute: u16) -> Self {
69        self.0.internal_file_attribute = attribute;
70        self
71    }
72
73    /// Sets the entry's external file attribute.
74    pub fn external_file_attribute(mut self, attribute: u32) -> Self {
75        self.0.external_file_attribute = attribute;
76        self
77    }
78
79    /// Sets the entry's extra field data.
80    pub fn extra_fields(mut self, field: Vec<ExtraField>) -> Self {
81        self.0.extra_fields = field;
82        self
83    }
84
85    /// Sets the entry's file comment.
86    pub fn comment(mut self, comment: ZipString) -> Self {
87        self.0.comment = comment;
88        self
89    }
90
91    /// Sets the entry's Unix permissions mode.
92    ///
93    /// If the attribute host compatibility isn't set to Unix, this will have no effect.
94    pub fn unix_permissions(mut self, mode: u16) -> Self {
95        if matches!(self.0.attribute_compatibility, AttributeCompatibility::Unix) {
96            self.0.external_file_attribute = (self.0.external_file_attribute & 0xFFFF) | (mode as u32) << 16;
97        }
98        self
99    }
100
101    /// Consumes this builder and returns a final [`ZipEntry`].
102    ///
103    /// This is equivalent to:
104    /// ```
105    /// # use async_zip::{ZipEntry, ZipEntryBuilder, Compression};
106    /// #
107    /// # let builder = ZipEntryBuilder::new(String::from("foo.bar").into(), Compression::Stored);
108    /// let entry: ZipEntry = builder.into();
109    /// ```
110    pub fn build(self) -> ZipEntry {
111        self.into()
112    }
113}