async_sevenz/lib.rs
1//! This project is an async 7z compressor/decompressor written in pure Rust.
2//!
3//! This is a fork of [sevenz-rust2](https://github.com/hasenbanck/sevenz-rust2), then translated the api to async with [async-compression](https://crates.io/crates/async-compression) by AI.
4//!
5//! ## Supported Codecs & filters
6//!
7//! | Codec | Decompression | Compression |
8//! |----------------|---------------|-------------|
9//! | COPY | ✓ | ✓ |
10//! | LZMA | ✓ | ✓ |
11//! | LZMA2 | ✓ | ✓ |
12//! | BROTLI (*) | ✓ | ✓ |
13//! | BZIP2 | ✓ | ✓ |
14//! | DEFLATE (*) | ✓ | ✓ |
15//! | PPMD | ✓ | ✓ |
16//! | LZ4 (*) | ✓ | ✓ |
17//! | ZSTD (*) | ✓ | ✓ |
18//!
19//! (*) Require optional cargo feature.
20//!
21//! | Filter | Decompression | Compression |
22//! |---------------|---------------|-------------|
23//! | BCJ X86 | ✓ | ✓ |
24//! | BCJ ARM | ✓ | ✓ |
25//! | BCJ ARM64 | ✓ | ✓ |
26//! | BCJ ARM_THUMB | ✓ | ✓ |
27//! | BCJ RISC_V | ✓ | ✓ |
28//! | BCJ PPC | ✓ | ✓ |
29//! | BCJ SPARC | ✓ | ✓ |
30//! | BCJ IA64 | ✓ | ✓ |
31//! | BCJ2 | ✓ | |
32//! | DELTA | ✓ | ✓ |
33//!
34//! # Usage
35//!
36//! ```rust
37//! use std::path::PathBuf;
38//!
39//! use tempfile::tempdir;
40//!
41//! use async_sevenz::decompress_file;
42//!
43//! #[tokio::main]
44//! async fn main() {
45//! let mut src = PathBuf::new();
46//! src.push("examples/data/sample.7z");
47//! let dest = tempdir().unwrap();
48//! decompress_file(src, dest.path()).await.expect("complete");
49//! }
50//! ```
51//!
52//! ## Decompress an encrypted 7z file
53//!
54//! ```rust
55//! # #[cfg(feature = "aes256")]
56//! # {
57//! use std::path::PathBuf;
58//!
59//! use tempfile::tempdir;
60//!
61//! use async_sevenz::decompress_file_with_password;
62//!
63//! #[tokio::main]
64//! async fn main() {
65//! let mut src = PathBuf::new();
66//! src.push("tests/resources/encrypted.7z");
67//! let dest = tempdir().unwrap();
68//! decompress_file_with_password(src, dest.path(), "sevenz-rust".into()).await
69//! .expect("complete");
70//! }
71//! # }
72//! ```
73//!
74//! # Compression
75//!
76//! ```rust
77//! # #[cfg(feature = "compress")]
78//! # {
79//! use std::path::PathBuf;
80//!
81//! use tempfile::tempdir;
82//!
83//! use async_sevenz::compress_to_path;
84//!
85//! #[tokio::main]
86//! async fn main() {
87//! let src = PathBuf::from("examples/data/sample");
88//! let dest_dir = tempdir().unwrap();
89//! let dest = dest_dir.path().join("sample.7z");
90//! compress_to_path(src, &dest).await.expect("compress ok");
91//! }
92//! # }
93//! ```
94//!
95//! ## Compress with AES encryption
96//!
97//! ```rust
98//! # #[cfg(all(feature = "compress", feature = "aes256"))]
99//! # {
100//! use std::path::PathBuf;
101//!
102//! use tempfile::tempdir;
103//!
104//! use async_sevenz::compress_to_path_encrypted;
105//!
106//! #[tokio::main]
107//! async fn main() {
108//! let src = PathBuf::from("examples/data/sample");
109//! let dest_dir = tempdir().unwrap();
110//! let dest = dest_dir.path().join("sample_encrypted.7z");
111//! compress_to_path_encrypted(src, &dest, "sevenz-rust".into()).await
112//! .expect("compress ok");
113//! }
114//! # }
115//! ```
116//!
117//! ## Solid compression
118//!
119//! ```rust
120//! # #[cfg(feature = "compress")]
121//! # {
122//! use async_sevenz::ArchiveWriter;
123//!
124//! #[tokio::main]
125//! async fn main() {
126//! let mut writer = ArchiveWriter::create_in_memory()
127//! .await
128//! .expect("create writer ok");
129//! writer
130//! .push_source_path("examples/data/sample", |_| async { true })
131//! .await
132//! .expect("pack ok");
133//! writer.finish().await.expect("compress ok");
134//! }
135//! # }
136//! ```
137//!
138//! ## Configure the compression methods
139//!
140//! ```rust
141//! # #[cfg(feature = "compress")]
142//! # {
143//! use async_sevenz::{ArchiveWriter, encoder_options};
144//!
145//! #[tokio::main]
146//! async fn main() {
147//! let mut writer = ArchiveWriter::create_in_memory()
148//! .await
149//! .expect("create writer ok");
150//! writer.set_content_methods(vec![
151//! encoder_options::AesEncoderOptions::new("sevenz-rust".into()).into(),
152//! encoder_options::Lzma2Options::from_level(9).into(),
153//! ]);
154//! writer
155//! .push_source_path("examples/data/sample", |_| async { true })
156//! .await
157//! .expect("pack ok");
158//! writer.finish().await.expect("compress ok");
159//! }
160//! # }
161//! ```
162#![cfg_attr(docsrs, feature(doc_cfg))]
163#![warn(missing_docs)]
164
165#[cfg(target_arch = "wasm32")]
166extern crate wasm_bindgen;
167
168#[cfg(feature = "compress")]
169mod encoder;
170/// Encoding options when compressing.
171#[cfg(feature = "compress")]
172pub mod encoder_options;
173mod encryption;
174mod error;
175mod reader;
176
177#[cfg(feature = "compress")]
178mod writer;
179
180pub(crate) mod archive;
181pub(crate) mod bitset;
182pub(crate) mod block;
183mod codec;
184pub(crate) mod decoder;
185
186mod time;
187mod util;
188
189use std::ops::{Deref, DerefMut};
190
191pub use archive::*;
192pub use block::*;
193pub use encryption::Password;
194pub use error::Error;
195pub use reader::{ArchiveReader, BlockDecoder};
196pub use time::NtTime;
197#[cfg(all(feature = "compress", not(target_arch = "wasm32")))]
198pub use util::compress::*;
199#[cfg(not(target_arch = "wasm32"))]
200pub use util::decompress::*;
201#[cfg(target_arch = "wasm32")]
202pub use util::wasm::*;
203#[cfg(feature = "compress")]
204pub use writer::*;
205
206/// A trait for writers that finishes the stream on drop.
207pub trait AutoFinish {
208 /// Finish writing the stream without error handling.
209 fn finish_ignore_error(self);
210}
211
212/// A wrapper around a writer that finishes the stream on drop.
213pub struct AutoFinisher<T: AutoFinish>(Option<T>);
214
215impl<T: AutoFinish> Drop for AutoFinisher<T> {
216 fn drop(&mut self) {
217 if let Some(writer) = self.0.take() {
218 writer.finish_ignore_error();
219 }
220 }
221}
222
223impl<T: AutoFinish> Deref for AutoFinisher<T> {
224 type Target = T;
225
226 fn deref(&self) -> &Self::Target {
227 self.0.as_ref().unwrap()
228 }
229}
230
231impl<T: AutoFinish> DerefMut for AutoFinisher<T> {
232 fn deref_mut(&mut self) -> &mut Self::Target {
233 self.0.as_mut().unwrap()
234 }
235}