# alpm-compress
A small library that provides streaming compression and decompression for multiple algorithms used in the ALPM ecosystem:
- bzip2 (`.bz2`)
- gzip (`.gz`)
- xz (`.xz`)
- zstd (`.zst`)
It offers a unified encoder/decoder API with configurable compression levels and, for zstd, optional multithreading.
In addition, it provides utilities to create and read tar archives:
- uncompressed (`.tar`)
- bzip2 (`.tar.bz2`)
- gzip (`.tar.gz`)
- xz (`.tar.xz`)
- zstd (`.tar.zst`)
## Documentation
- <https://alpm.archlinux.page/rustdoc/alpm_compress/> for development version of the crate
- <https://docs.rs/alpm-compress/latest/alpm_compress/> for released versions of the crate
## Examples
### Compressing
```rust
use std::{fs::File, io::Write};
use alpm_compress::compression::{
CompressionEncoder,
CompressionSettings,
ZstdThreads,
ZstdCompressionLevel
};
use tempfile::tempfile;
# fn main() -> testresult::TestResult {
// Create an encoder that writes zstd-compressed data to a file.
let file = tempfile()?;
let settings = CompressionSettings::Zstd {
compression_level: ZstdCompressionLevel::default(),
threads: ZstdThreads::default(),
};
let mut encoder = CompressionEncoder::new(file, &settings)?;
encoder.write_all(b"alpm-compress makes compression easy")?;
let _file = encoder.finish()?; // retrieve the inner File when done
# Ok(())
# }
```
Compression settings default to zstd compression, but you can select other algorithms and levels.
Since compression is optional via `None` variant, this library provides unified API to read and write both
compressed and uncompressed files, including tar archives.
```rust
use alpm_compress::compression::{
CompressionSettings,
Bzip2CompressionLevel,
GzipCompressionLevel,
XzCompressionLevel,
ZstdCompressionLevel,
ZstdThreads,
};
# fn main() {
// Bzip compression
let bzip2 = CompressionSettings::Bzip2 { compression_level: Bzip2CompressionLevel::default() };
// Gzip compression
let gzip = CompressionSettings::Gzip { compression_level: GzipCompressionLevel::default() };
// Xz compression
let xz = CompressionSettings::Xz { compression_level: XzCompressionLevel::default() };
// Zstd compression
let zstd = CompressionSettings::Zstd { compression_level: ZstdCompressionLevel::default(), threads: ZstdThreads::default() };
// No compression
let no_compression = CompressionSettings::None;
# }
```
### Decompressing
```rust
use std::{fs::File, io::Read};
use alpm_compress::decompression::{DecompressionSettings, CompressionDecoder};
use tempfile::tempfile;
# fn main() -> testresult::TestResult {
// Create a temporary file.
let mut file = tempfile()?;
// [..] Add zstd compressed content to the temporary file.
# // Create an encoder that writes zstd-compressed data to a file.
# use alpm_compress::compression::{CompressionEncoder, CompressionSettings, ZstdThreads, ZstdCompressionLevel};
# use std::io::{Write, Seek};
#
# let settings = CompressionSettings::Zstd {
# compression_level: ZstdCompressionLevel::default(),
# threads: ZstdThreads::default(),
# };
# let mut encoder = CompressionEncoder::new(file.try_clone()?, &settings)?;
# encoder.write_all(b"alpm-compress makes compression easy")?;
# encoder.flush()?;
# encoder.finish()?;
# file.rewind()?;
// Decompress a zstd-compressed file
let mut decoder = CompressionDecoder::new(file, DecompressionSettings::Zstd)?;
let mut buf = Vec::new();
decoder.read_to_end(&mut buf)?;
assert_eq!(buf, b"alpm-compress makes compression easy");
# Ok(())
# }
```
### Building a tarball
```rust
use alpm_compress::tarball::TarballBuilder;
use alpm_compress::compression::{CompressionSettings, ZstdCompressionLevel, ZstdThreads};
use tempfile::NamedTempFile;
use std::io::Write;
# fn main() -> testresult::TestResult {
let mut tarball = NamedTempFile::with_suffix(".tar.zst")?;
let settings = CompressionSettings::Zstd {
compression_level: ZstdCompressionLevel::default(),
threads: ZstdThreads::default(),
};
let mut builder = TarballBuilder::new(tarball.reopen()?, &settings)?;
// Create a temporary file to add to the tarball.
let inner_file = NamedTempFile::new()?;
{
let mut f = inner_file.reopen()?;
f.write_all(b"alpm4ever")?;
f.flush()?;
}
// Append the file to the tarball with a specific name.
builder
.inner_mut()
.append_path_with_name(inner_file.path(), "some_file.txt")?;
builder.finish()?;
# Ok(())
# }
```
### Reading a tarball
```rust
use alpm_compress::tarball::TarballReader;
use tempfile::NamedTempFile;
# use std::io::Write;
# use alpm_compress::tarball::TarballBuilder;
# use alpm_compress::compression::{CompressionSettings, ZstdCompressionLevel, ZstdThreads};
# fn main() -> testresult::TestResult {
# let inner_file = NamedTempFile::new()?;
# {
# let mut f = inner_file.reopen()?;
# f.write_all(b"alpm4ever")?;
# f.flush()?;
# }
let archive = NamedTempFile::with_suffix(".tar.zst")?;
// [..] Create a zstd-compressed tarball containing a file named "some_file.txt"
# let settings = CompressionSettings::Zstd {
# compression_level: ZstdCompressionLevel::default(),
# threads: ZstdThreads::default(),
# };
# {
# let file = archive.reopen()?;
# let mut builder = TarballBuilder::new(file, &settings)?;
# builder
# .inner_mut()
# .append_path_with_name(inner_file.path(), "some_file.txt")?;
# builder.finish()?;
# }
// Read the compressed archive
let mut reader = TarballReader::try_from(archive.path())?;
let entry = reader.read_entry("some_file.txt")?;
assert!(entry.is_some());
let content = entry.unwrap().content()?;
assert_eq!(content, b"alpm4ever");
# Ok(())
# }
```
## Contributing
Please refer to the [contribution guidelines] to learn how to contribute to this project.
## License
This project can be used under the terms of the [Apache-2.0] or [MIT].
Contributions to this project, unless noted otherwise, are automatically licensed under the terms of both of those licenses.
[contribution guidelines]: ../CONTRIBUTING.md
[Apache-2.0]: ../LICENSES/Apache-2.0.txt
[MIT]: ../LICENSES/MIT.txt