Skip to main content

easy_archive/
lib.rs

1/// Easy Archive - A cross-platform archive manipulation library
2///
3/// This library provides a unified interface for working with various archive formats
4/// including TAR, ZIP, and their compressed variants (gzip, xz, bzip2, zstd).
5///
6/// # Features
7///
8/// The library uses Cargo features to enable/disable format support:
9/// - `tar` - Plain TAR format
10/// - `tar-gz` - Gzip-compressed TAR
11/// - `tar-xz` - XZ-compressed TAR
12/// - `tar-bz` - Bzip2-compressed TAR
13/// - `tar-zstd` - Zstd-compressed TAR
14/// - `zip` - ZIP format
15/// - `default` - Enables all formats
16///
17/// # Example
18///
19/// ```no_run
20/// use easy_archive::{Fmt, File};
21///
22/// // Decode an archive
23/// let data = std::fs::read("archive.tar.gz")?;
24/// let files = Fmt::TarGz.decode(data)?;
25///
26/// // Encode files into an archive
27/// let files = vec![
28///     File {
29///         path: "hello.txt".to_string(),
30///         buffer: b"Hello, world!".to_vec(),
31///         ..Default::default()
32///     }
33/// ];
34/// let archive = Fmt::Zip.encode(files)?;
35/// std::fs::write("output.zip", archive)?;
36/// # Ok::<(), Box<dyn std::error::Error>>(())
37/// ```
38// Module declarations
39pub mod archive;
40pub mod error;
41pub mod traits;
42pub mod types;
43pub mod utils;
44
45#[cfg(feature = "cli")]
46pub mod cli;
47
48#[cfg(feature = "convert")]
49pub mod convert;
50
51// Re-export commonly used types and functions
52pub use error::{ArchiveError, Result};
53pub use types::{File, Fmt};
54pub use utils::{clean, human_size, mode_to_string};
55
56#[cfg(feature = "decode")]
57pub use traits::Decode;
58
59#[cfg(feature = "encode")]
60pub use traits::Encode;
61
62#[cfg(feature = "encode")]
63pub use utils::check_duplicate_files;
64
65#[cfg(all(feature = "encode", feature = "decode"))]
66pub use traits::Archive;
67
68#[cfg(feature = "convert")]
69pub use convert::{convert_archive, convert_archive_file};
70
71#[cfg(test)]
72mod test {
73    use crate::{File, types::Fmt};
74    use strum::IntoEnumIterator;
75
76    #[test]
77    fn test_decode() {
78        for name in std::fs::read_dir("../assets").unwrap() {
79            let path = name.unwrap().path();
80            let buffer = std::fs::read(&path).unwrap();
81            let fmt = Fmt::guess(&path.to_string_lossy()).unwrap();
82            let files = fmt.decode(buffer).unwrap();
83            let dist = files
84                .iter()
85                .find(|i| i.path == "mujs-build-0.0.11/dist-manifest.json")
86                .unwrap();
87            assert!(!dist.buffer.is_empty());
88        }
89    }
90
91    use std::path::PathBuf;
92
93    #[test]
94    fn encode_decode() {
95        for fmt in Fmt::iter() {
96            // Skip TarBz if not fully implemented
97            #[cfg(feature = "tar-bz")]
98            if fmt == Fmt::TarBz {
99                // TarBz encoding is now implemented
100                continue;
101            }
102
103            let mut files = vec![];
104            let base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
105            let asset_dir = base.join("../assets");
106
107            for entry in std::fs::read_dir(asset_dir).expect("read dir error") {
108                let file_path = entry.expect("get path error").path();
109                let path = file_path
110                    .file_name()
111                    .expect("get name error")
112                    .to_string_lossy()
113                    .to_string();
114                let buffer = std::fs::read(&file_path).expect("read file error");
115
116                files.push(File {
117                    buffer,
118                    path,
119                    mode: None,
120                    is_dir: false,
121                    last_modified: None,
122                })
123            }
124
125            let compressed = fmt.encode(files).expect("encode error");
126            println!("{:?} {}", fmt, compressed.len());
127            assert!(!compressed.is_empty());
128        }
129    }
130}