sevenz_rust2/
lib.rs

1//! This project is a 7z compressor/decompressor written in pure Rust.
2//!
3//! This is a fork of the original, unmaintained sevenz-rust crate to continue the development
4//! and maintenance.
5//!
6//! ## Supported Codecs & filters
7//!
8//! | Codec          | Decompression | Compression |
9//! |----------------|---------------|-------------|
10//! | COPY           | ✓             | ✓           |
11//! | LZMA           | ✓             | ✓           |
12//! | LZMA2          | ✓             | ✓           |
13//! | BROTLI (*)     | ✓             | ✓           |
14//! | BZIP2          | ✓             | ✓           |
15//! | DEFLATE (*)    | ✓             | ✓           |
16//! | PPMD           | ✓             | ✓           |
17//! | LZ4 (*)        | ✓             | ✓           |
18//! | ZSTD (*)       | ✓             | ✓           |
19//!
20//! (*) Require optional cargo feature.
21//!
22//! | Filter        | Decompression | Compression |
23//! |---------------|---------------|-------------|
24//! | BCJ X86       | ✓             | ✓           |
25//! | BCJ ARM       | ✓             | ✓           |
26//! | BCJ ARM64     | ✓             | ✓           |
27//! | BCJ ARM_THUMB | ✓             | ✓           |
28//! | BCJ RISC_V    | ✓             | ✓           |
29//! | BCJ PPC       | ✓             | ✓           |
30//! | BCJ SPARC     | ✓             | ✓           |
31//! | BCJ IA64      | ✓             | ✓           |
32//! | BCJ2          | ✓             |             |
33//! | DELTA         | ✓             | ✓           |
34#![cfg_attr(docsrs, feature(doc_auto_cfg))]
35#![warn(missing_docs)]
36
37#[cfg(target_arch = "wasm32")]
38extern crate wasm_bindgen;
39
40#[cfg(feature = "compress")]
41mod encoder;
42/// Encoding options when compressing.
43#[cfg(feature = "compress")]
44pub mod encoder_options;
45mod encryption;
46mod error;
47mod reader;
48
49#[cfg(feature = "compress")]
50mod writer;
51
52pub(crate) mod archive;
53pub(crate) mod bitset;
54pub(crate) mod block;
55mod codec;
56pub(crate) mod decoder;
57
58mod time;
59#[cfg(feature = "util")]
60mod util;
61
62use std::{
63    io::{Read, Write},
64    ops::{Deref, DerefMut},
65};
66
67pub use archive::*;
68pub use block::*;
69pub use encryption::Password;
70pub use error::Error;
71pub use reader::{ArchiveReader, BlockDecoder};
72pub use time::NtTime;
73#[cfg(all(feature = "compress", feature = "util", not(target_arch = "wasm32")))]
74pub use util::compress::*;
75#[cfg(all(feature = "util", not(target_arch = "wasm32")))]
76pub use util::decompress::*;
77#[cfg(all(feature = "util", target_arch = "wasm32"))]
78pub use util::wasm::*;
79#[cfg(feature = "compress")]
80pub use writer::*;
81
82trait ByteReader {
83    fn read_u8(&mut self) -> std::io::Result<u8>;
84
85    #[cfg(feature = "brotli")]
86    fn read_u16(&mut self) -> std::io::Result<u16>;
87
88    fn read_u32(&mut self) -> std::io::Result<u32>;
89
90    fn read_u64(&mut self) -> std::io::Result<u64>;
91}
92
93trait ByteWriter {
94    #[cfg(feature = "compress")]
95    fn write_u8(&mut self, value: u8) -> std::io::Result<()>;
96
97    fn write_u16(&mut self, value: u16) -> std::io::Result<()>;
98
99    #[cfg(feature = "compress")]
100    fn write_u32(&mut self, value: u32) -> std::io::Result<()>;
101
102    #[cfg(feature = "compress")]
103    fn write_u64(&mut self, value: u64) -> std::io::Result<()>;
104}
105
106impl<T: Read> ByteReader for T {
107    #[inline(always)]
108    fn read_u8(&mut self) -> std::io::Result<u8> {
109        let mut buf = [0; 1];
110        self.read_exact(&mut buf)?;
111        Ok(buf[0])
112    }
113
114    #[cfg(feature = "brotli")]
115    #[inline(always)]
116    fn read_u16(&mut self) -> std::io::Result<u16> {
117        let mut buf = [0; 2];
118        self.read_exact(buf.as_mut())?;
119        Ok(u16::from_le_bytes(buf))
120    }
121
122    #[inline(always)]
123    fn read_u32(&mut self) -> std::io::Result<u32> {
124        let mut buf = [0; 4];
125        self.read_exact(buf.as_mut())?;
126        Ok(u32::from_le_bytes(buf))
127    }
128
129    #[inline(always)]
130    fn read_u64(&mut self) -> std::io::Result<u64> {
131        let mut buf = [0; 8];
132        self.read_exact(buf.as_mut())?;
133        Ok(u64::from_le_bytes(buf))
134    }
135}
136
137impl<T: Write> ByteWriter for T {
138    #[cfg(feature = "compress")]
139    #[inline(always)]
140    fn write_u8(&mut self, value: u8) -> std::io::Result<()> {
141        self.write_all(&[value])
142    }
143
144    #[inline(always)]
145    fn write_u16(&mut self, value: u16) -> std::io::Result<()> {
146        self.write_all(&value.to_le_bytes())
147    }
148
149    #[cfg(feature = "compress")]
150    #[inline(always)]
151    fn write_u32(&mut self, value: u32) -> std::io::Result<()> {
152        self.write_all(&value.to_le_bytes())
153    }
154
155    #[cfg(feature = "compress")]
156    #[inline(always)]
157    fn write_u64(&mut self, value: u64) -> std::io::Result<()> {
158        self.write_all(&value.to_le_bytes())
159    }
160}
161
162/// A trait for writers that finishes the stream on drop.
163trait AutoFinish {
164    /// Finish writing the stream without error handling.
165    fn finish_ignore_error(self);
166}
167
168/// A wrapper around a writer that finishes the stream on drop.
169#[allow(private_bounds)]
170pub struct AutoFinisher<T: AutoFinish>(Option<T>);
171
172impl<T: AutoFinish> Drop for AutoFinisher<T> {
173    fn drop(&mut self) {
174        if let Some(writer) = self.0.take() {
175            writer.finish_ignore_error();
176        }
177    }
178}
179
180impl<T: AutoFinish> Deref for AutoFinisher<T> {
181    type Target = T;
182
183    fn deref(&self) -> &Self::Target {
184        self.0.as_ref().unwrap()
185    }
186}
187
188impl<T: AutoFinish> DerefMut for AutoFinisher<T> {
189    fn deref_mut(&mut self) -> &mut Self::Target {
190        self.0.as_mut().unwrap()
191    }
192}