1pub use strum::IntoEnumIterator;
3use strum_macros::EnumIter;
4
5use crate::error::Result;
6
7#[cfg(feature = "tar")]
8use crate::archive::Tar;
9#[cfg(feature = "tar-bz")]
10use crate::archive::TarBz;
11#[cfg(feature = "tar-gz")]
12use crate::archive::TarGz;
13#[cfg(feature = "tar-xz")]
14use crate::archive::TarXz;
15#[cfg(feature = "tar-zstd")]
16use crate::archive::TarZstd;
17#[cfg(feature = "zip")]
18use crate::archive::Zip;
19#[cfg(feature = "7z")]
20use crate::archive::seven_zip::SevenZip;
21
22#[cfg(feature = "decode")]
23use crate::traits::Decode;
24#[cfg(feature = "encode")]
25use crate::traits::Encode;
26
27#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen)]
32#[derive(EnumIter, Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum Fmt {
34 #[cfg(feature = "tar")]
36 Tar,
37 #[cfg(feature = "tar-gz")]
39 TarGz,
40 #[cfg(feature = "tar-xz")]
42 TarXz,
43 #[cfg(feature = "tar-bz")]
45 TarBz,
46 #[cfg(feature = "tar-zstd")]
48 TarZstd,
49 #[cfg(feature = "zip")]
51 Zip,
52 #[cfg(feature = "7z")]
54 SevenZip,
55}
56
57impl Fmt {
58 #[cfg(feature = "decode")]
75 pub fn decode(&self, buffer: Vec<u8>) -> Result<Vec<File>> {
76 match self {
77 #[cfg(feature = "zip")]
78 Fmt::Zip => Zip::decode(buffer),
79 #[cfg(feature = "tar")]
80 Fmt::Tar => Tar::decode(buffer),
81 #[cfg(feature = "tar-gz")]
82 Fmt::TarGz => TarGz::decode(buffer),
83 #[cfg(feature = "tar-xz")]
84 Fmt::TarXz => TarXz::decode(buffer),
85 #[cfg(feature = "tar-bz")]
86 Fmt::TarBz => TarBz::decode(buffer),
87 #[cfg(feature = "tar-zstd")]
88 Fmt::TarZstd => TarZstd::decode(buffer),
89 #[cfg(feature = "7z")]
90 Fmt::SevenZip => SevenZip::decode(buffer),
91 }
92 }
93
94 #[cfg(feature = "encode")]
118 pub fn encode(&self, files: Vec<File>) -> Result<Vec<u8>> {
119 match self {
120 #[cfg(feature = "zip")]
121 Fmt::Zip => Zip::encode(files),
122 #[cfg(feature = "tar")]
123 Fmt::Tar => Tar::encode(files),
124 #[cfg(feature = "tar-gz")]
125 Fmt::TarGz => TarGz::encode(files),
126 #[cfg(feature = "tar-xz")]
127 Fmt::TarXz => TarXz::encode(files),
128 #[cfg(feature = "tar-bz")]
129 Fmt::TarBz => TarBz::encode(files),
130 #[cfg(feature = "tar-zstd")]
131 Fmt::TarZstd => TarZstd::encode(files),
132 #[cfg(feature = "7z")]
133 Fmt::SevenZip => SevenZip::encode(files),
134 }
135 }
136
137 pub fn guess(name: &str) -> Option<Self> {
154 for fmt in Fmt::iter() {
155 for ext in fmt.extensions() {
156 if name.ends_with(ext) {
157 return Some(fmt);
158 }
159 }
160 }
161 None
162 }
163
164 pub fn extensions(&self) -> &[&'static str] {
175 match self {
176 #[cfg(feature = "tar")]
177 Fmt::Tar => &[".tar"],
178 #[cfg(feature = "tar-gz")]
179 Fmt::TarGz => &[".tar.gz", ".tgz"],
180 #[cfg(feature = "tar-xz")]
181 Fmt::TarXz => &[".tar.xz", ".txz"],
182 #[cfg(feature = "tar-bz")]
183 Fmt::TarBz => &[".tar.bz2", ".tbz2", ".tbz"],
184 #[cfg(feature = "tar-zstd")]
185 Fmt::TarZstd => &[".tzstd", ".tzst", ".tar.zst"],
186 #[cfg(feature = "zip")]
187 Fmt::Zip => &[".zip"],
188 #[cfg(feature = "7z")]
189 Fmt::SevenZip => &[".7z"],
190 }
191 }
192}
193
194#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen)]
199#[derive(Debug, Clone, Default)]
200pub struct File {
201 #[cfg_attr(feature = "wasm", wasm_bindgen(skip))]
203 pub buffer: Vec<u8>,
204
205 #[cfg_attr(feature = "wasm", wasm_bindgen(skip))]
207 pub path: String,
208
209 pub mode: Option<u32>,
211
212 #[cfg_attr(feature = "wasm", wasm_bindgen(js_name = "isDir"))]
214 pub is_dir: bool,
215
216 #[cfg_attr(feature = "wasm", wasm_bindgen(js_name = "lastModified"))]
218 pub last_modified: Option<u64>,
219}
220
221#[cfg(feature = "wasm")]
222use wasm_bindgen::prelude::*;
223
224#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen)]
225impl File {
226 #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
235 pub fn new(
236 path: String,
237 buffer: Vec<u8>,
238 mode: Option<u32>,
239 is_dir: bool,
240 last_modified: Option<u64>,
241 ) -> Self {
242 File {
243 path,
244 buffer,
245 mode,
246 is_dir,
247 last_modified,
248 }
249 }
250}
251
252#[cfg(feature = "wasm")]
253#[wasm_bindgen]
254impl File {
255 #[wasm_bindgen(getter = buffer)]
259 pub fn get_buffer(self) -> Vec<u8> {
260 self.buffer
261 }
262
263 #[wasm_bindgen(setter = buffer)]
265 pub fn set_buffer(&mut self, buffer: Vec<u8>) {
266 self.buffer = buffer;
267 }
268
269 #[wasm_bindgen(getter = path)]
271 pub fn get_path(&self) -> String {
272 self.path.clone()
273 }
274
275 #[wasm_bindgen(setter = path)]
277 pub fn set_path(&mut self, path: String) {
278 self.path = path;
279 }
280
281 #[wasm_bindgen(getter = bufferSize)]
283 pub fn buffer_size(&self) -> usize {
284 self.buffer.len()
285 }
286
287 #[wasm_bindgen]
289 #[allow(clippy::should_implement_trait)]
290 pub fn clone(&self) -> Self {
291 Clone::clone(self)
292 }
293}
294
295#[cfg(test)]
296mod test {
297 use super::Fmt;
298
299 #[test]
300 fn test_guess() {
301 let test_cases = vec![
302 #[cfg(feature = "zip")]
303 ("a.zip", Fmt::Zip),
304 #[cfg(feature = "tar")]
305 ("a.tar", Fmt::Tar),
306 #[cfg(feature = "tar-gz")]
307 ("a.tar.gz", Fmt::TarGz),
308 #[cfg(feature = "tar-xz")]
309 ("a.tar.xz", Fmt::TarXz),
310 #[cfg(feature = "tar-bz")]
311 ("a.tar.bz2", Fmt::TarBz),
312 ];
313
314 for (name, fmt) in test_cases {
315 assert_eq!(
316 Fmt::guess(name),
317 Some(fmt),
318 "Failed to guess format for {}",
319 name
320 );
321 }
322 }
323}