pub use strum::IntoEnumIterator;
use strum_macros::EnumIter;
use crate::error::Result;
#[cfg(feature = "tar")]
use crate::archive::Tar;
#[cfg(feature = "tar-bz")]
use crate::archive::TarBz;
#[cfg(feature = "tar-gz")]
use crate::archive::TarGz;
#[cfg(feature = "tar-xz")]
use crate::archive::TarXz;
#[cfg(feature = "tar-zstd")]
use crate::archive::TarZstd;
#[cfg(feature = "gz")]
use crate::archive::Gz;
#[cfg(feature = "zip")]
use crate::archive::Zip;
#[cfg(feature = "7z")]
use crate::archive::seven_zip::SevenZip;
#[cfg(feature = "decode")]
use crate::traits::Decode;
#[cfg(feature = "encode")]
use crate::traits::Encode;
#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen)]
#[derive(EnumIter, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Fmt {
#[cfg(feature = "tar")]
Tar,
#[cfg(feature = "tar-gz")]
TarGz,
#[cfg(feature = "tar-xz")]
TarXz,
#[cfg(feature = "tar-bz")]
TarBz,
#[cfg(feature = "tar-zstd")]
TarZstd,
#[cfg(feature = "gz")]
Gz,
#[cfg(feature = "zip")]
Zip,
#[cfg(feature = "7z")]
SevenZip,
}
impl Fmt {
#[cfg(feature = "decode")]
pub fn decode(&self, buffer: Vec<u8>) -> Result<Vec<File>> {
match self {
#[cfg(feature = "zip")]
Fmt::Zip => Zip::decode(buffer),
#[cfg(feature = "tar")]
Fmt::Tar => Tar::decode(buffer),
#[cfg(feature = "tar-gz")]
Fmt::TarGz => TarGz::decode(buffer),
#[cfg(feature = "tar-xz")]
Fmt::TarXz => TarXz::decode(buffer),
#[cfg(feature = "tar-bz")]
Fmt::TarBz => TarBz::decode(buffer),
#[cfg(feature = "tar-zstd")]
Fmt::TarZstd => TarZstd::decode(buffer),
#[cfg(feature = "gz")]
Fmt::Gz => Gz::decode(buffer),
#[cfg(feature = "7z")]
Fmt::SevenZip => SevenZip::decode(buffer),
}
}
#[cfg(feature = "encode")]
pub fn encode(&self, files: Vec<File>) -> Result<Vec<u8>> {
match self {
#[cfg(feature = "zip")]
Fmt::Zip => Zip::encode(files),
#[cfg(feature = "tar")]
Fmt::Tar => Tar::encode(files),
#[cfg(feature = "tar-gz")]
Fmt::TarGz => TarGz::encode(files),
#[cfg(feature = "tar-xz")]
Fmt::TarXz => TarXz::encode(files),
#[cfg(feature = "tar-bz")]
Fmt::TarBz => TarBz::encode(files),
#[cfg(feature = "tar-zstd")]
Fmt::TarZstd => TarZstd::encode(files),
#[cfg(feature = "gz")]
Fmt::Gz => Gz::encode(files),
#[cfg(feature = "7z")]
Fmt::SevenZip => SevenZip::encode(files),
}
}
pub fn guess(name: &str) -> Option<Self> {
for fmt in Fmt::iter() {
for ext in fmt.extensions() {
if name.ends_with(ext) {
return Some(fmt);
}
}
}
None
}
pub fn extensions(&self) -> &[&'static str] {
match self {
#[cfg(feature = "tar")]
Fmt::Tar => &[".tar"],
#[cfg(feature = "tar-gz")]
Fmt::TarGz => &[".tar.gz", ".tgz"],
#[cfg(feature = "tar-xz")]
Fmt::TarXz => &[".tar.xz", ".txz"],
#[cfg(feature = "tar-bz")]
Fmt::TarBz => &[".tar.bz2", ".tbz2", ".tbz"],
#[cfg(feature = "tar-zstd")]
Fmt::TarZstd => &[".tzstd", ".tzst", ".tar.zst"],
#[cfg(feature = "gz")]
Fmt::Gz => &[".gz"],
#[cfg(feature = "zip")]
Fmt::Zip => &[".zip"],
#[cfg(feature = "7z")]
Fmt::SevenZip => &[".7z"],
}
}
pub fn is_single_file(&self) -> bool {
match self {
#[cfg(feature = "gz")]
Fmt::Gz => true,
_ => false,
}
}
}
#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen)]
#[derive(Debug, Clone, Default)]
pub struct File {
#[cfg_attr(feature = "wasm", wasm_bindgen(skip))]
pub buffer: Vec<u8>,
#[cfg_attr(feature = "wasm", wasm_bindgen(skip))]
pub path: String,
pub mode: Option<u32>,
#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = "isDir"))]
pub is_dir: bool,
#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = "lastModified"))]
pub last_modified: Option<u64>,
}
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen)]
impl File {
#[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
pub fn new(
path: String,
buffer: Vec<u8>,
mode: Option<u32>,
is_dir: bool,
last_modified: Option<u64>,
) -> Self {
File {
path,
buffer,
mode,
is_dir,
last_modified,
}
}
}
#[cfg(feature = "wasm")]
#[wasm_bindgen]
impl File {
#[wasm_bindgen(getter = buffer)]
pub fn get_buffer(self) -> Vec<u8> {
self.buffer
}
#[wasm_bindgen(setter = buffer)]
pub fn set_buffer(&mut self, buffer: Vec<u8>) {
self.buffer = buffer;
}
#[wasm_bindgen(getter = path)]
pub fn get_path(&self) -> String {
self.path.clone()
}
#[wasm_bindgen(setter = path)]
pub fn set_path(&mut self, path: String) {
self.path = path;
}
#[wasm_bindgen(getter = bufferSize)]
pub fn buffer_size(&self) -> usize {
self.buffer.len()
}
#[wasm_bindgen]
#[allow(clippy::should_implement_trait)]
pub fn clone(&self) -> Self {
Clone::clone(self)
}
}
#[cfg(test)]
mod test {
use super::Fmt;
#[test]
fn test_guess() {
let test_cases = vec![
#[cfg(feature = "zip")]
("a.zip", Fmt::Zip),
#[cfg(feature = "tar")]
("a.tar", Fmt::Tar),
#[cfg(feature = "tar-gz")]
("a.tar.gz", Fmt::TarGz),
#[cfg(feature = "tar-xz")]
("a.tar.xz", Fmt::TarXz),
#[cfg(feature = "tar-bz")]
("a.tar.bz2", Fmt::TarBz),
#[cfg(all(feature = "tar-gz", feature = "gz"))]
("a.tar.gz", Fmt::TarGz),
#[cfg(feature = "gz")]
("a.gz", Fmt::Gz),
#[cfg(feature = "gz")]
("tool.exe.gz", Fmt::Gz),
];
for (name, fmt) in test_cases {
assert_eq!(
Fmt::guess(name),
Some(fmt),
"Failed to guess format for {}",
name
);
}
}
}