Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

Examples

Compressing

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.

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

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

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

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.