use-compression 0.1.0

Compression level, intent, and codec label primitives for RustUse
Documentation
#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]

//! Compression level and intent primitives for `RustUse`.

#[cfg(feature = "brotli")]
pub use use_brotli as brotli;
#[cfg(feature = "bzip2")]
pub use use_bzip2 as bzip2;
#[cfg(feature = "gzip")]
pub use use_gzip as gzip;
#[cfg(feature = "lz4")]
pub use use_lz4 as lz4;
#[cfg(feature = "xz")]
pub use use_xz as xz;
#[cfg(feature = "zstd")]
pub use use_zstd as zstd;

/// Generic compression level labels.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum CompressionLevel {
    /// Prefer fastest compression.
    Fastest,
    /// Balance speed and compressed size.
    #[default]
    Balanced,
    /// Prefer best compressed size.
    Best,
    /// Caller-specified numeric compression level.
    Numeric(u32),
}

impl CompressionLevel {
    /// Returns a stable lowercase label.
    #[must_use]
    pub const fn as_str(self) -> &'static str {
        match self {
            Self::Fastest => "fastest",
            Self::Balanced => "balanced",
            Self::Best => "best",
            Self::Numeric(_) => "numeric",
        }
    }

    /// Returns the numeric level when this is [`CompressionLevel::Numeric`].
    #[must_use]
    pub const fn numeric(self) -> Option<u32> {
        match self {
            Self::Numeric(level) => Some(level),
            Self::Fastest | Self::Balanced | Self::Best => None,
        }
    }
}

/// Intent behind a compression choice.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum CompressionIntent {
    /// Prefer compression speed.
    Speed,
    /// Prefer compressed size.
    Size,
    /// Balance speed and size.
    #[default]
    Balanced,
    /// Prefer compatibility with broad tooling.
    Compatibility,
}

impl CompressionIntent {
    /// Returns a stable lowercase label.
    #[must_use]
    pub const fn as_str(self) -> &'static str {
        match self {
            Self::Speed => "speed",
            Self::Size => "size",
            Self::Balanced => "balanced",
            Self::Compatibility => "compatibility",
        }
    }
}

/// Generic compression settings metadata.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct CompressionSettings {
    /// Compression level label.
    pub level: CompressionLevel,
    /// Compression intent label.
    pub intent: CompressionIntent,
}

impl CompressionSettings {
    /// Creates compression settings metadata.
    #[must_use]
    pub const fn new(level: CompressionLevel, intent: CompressionIntent) -> Self {
        Self { level, intent }
    }
}

#[cfg(test)]
mod tests {
    use super::{CompressionIntent, CompressionLevel, CompressionSettings};

    #[test]
    fn describes_level_and_intent() {
        let settings =
            CompressionSettings::new(CompressionLevel::Numeric(9), CompressionIntent::Size);

        assert_eq!(settings.level.as_str(), "numeric");
        assert_eq!(settings.level.numeric(), Some(9));
        assert_eq!(settings.intent.as_str(), "size");
    }

    #[cfg(all(
        feature = "bzip2",
        feature = "brotli",
        feature = "gzip",
        feature = "lz4"
    ))]
    #[test]
    fn exposes_codec_namespaces() {
        assert!(super::bzip2::is_bzip2_filename("bundle.tar.bz2"));
        assert!(super::brotli::is_brotli_filename("bundle.tar.br"));
        assert_eq!(super::gzip::GZIP_EXTENSION, "gz");
        assert!(super::lz4::is_lz4_filename("bundle.tar.lz4"));
    }
}