pub mod calibration;
pub mod ctw;
pub mod llm_policy;
#[cfg(feature = "backend-mamba")]
pub mod mambazip;
pub mod match_model;
pub mod particle;
pub mod ppmd;
pub mod rosaplus;
#[cfg(feature = "backend-rwkv")]
pub mod rwkvzip;
pub mod sparse_match;
pub mod text_context;
pub mod zpaq_rate;
use crate::coders::CoderType;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum BackendAvailability {
Enabled(&'static str),
Disabled {
canonical: &'static str,
feature: &'static str,
},
}
pub const AVAILABLE_RATE_BACKENDS: &[&str] = &[
"rosaplus",
"ctw",
"fac-ctw",
"match",
"sparse-match",
"ppmd",
"calibrated",
#[cfg(feature = "backend-mamba")]
"mamba",
#[cfg(feature = "backend-rwkv")]
"rwkv7",
#[cfg(feature = "backend-zpaq")]
"zpaq",
"mixture",
"particle",
];
pub const AVAILABLE_COMPRESSION_BACKENDS: &[&str] = &[
#[cfg(feature = "backend-zpaq")]
"zpaq",
"rate-ac",
"rate-rans",
#[cfg(feature = "backend-rwkv")]
"rwkv7",
];
pub fn resolve_rate_backend_name(input: &str) -> Option<BackendAvailability> {
let key = input.trim().to_ascii_lowercase();
match key.as_str() {
"rosaplus" | "rosa" => Some(BackendAvailability::Enabled("rosaplus")),
"ctw" => Some(BackendAvailability::Enabled("ctw")),
"fac-ctw" | "facctw" => Some(BackendAvailability::Enabled("fac-ctw")),
"match" => Some(BackendAvailability::Enabled("match")),
"sparse-match" | "sparse_match" | "sparsematch" => {
Some(BackendAvailability::Enabled("sparse-match"))
}
"ppmd" | "ppm" => Some(BackendAvailability::Enabled("ppmd")),
"calibrated" | "cal" => Some(BackendAvailability::Enabled("calibrated")),
"zpaq" => {
if cfg!(feature = "backend-zpaq") {
Some(BackendAvailability::Enabled("zpaq"))
} else {
Some(BackendAvailability::Disabled {
canonical: "zpaq",
feature: "backend-zpaq",
})
}
}
"mixture" | "mix" => Some(BackendAvailability::Enabled("mixture")),
"particle" | "particles" => Some(BackendAvailability::Enabled("particle")),
"mamba" | "mamba1" => {
if cfg!(feature = "backend-mamba") {
Some(BackendAvailability::Enabled("mamba"))
} else {
Some(BackendAvailability::Disabled {
canonical: "mamba",
feature: "backend-mamba",
})
}
}
"rwkv7" | "rwkv" => {
if cfg!(feature = "backend-rwkv") {
Some(BackendAvailability::Enabled("rwkv7"))
} else {
Some(BackendAvailability::Disabled {
canonical: "rwkv7",
feature: "backend-rwkv",
})
}
}
_ => None,
}
}
pub fn resolve_compression_backend_name(input: &str) -> Option<BackendAvailability> {
let key = input.trim().to_ascii_lowercase();
match key.as_str() {
"zpaq" => {
if cfg!(feature = "backend-zpaq") {
Some(BackendAvailability::Enabled("zpaq"))
} else {
Some(BackendAvailability::Disabled {
canonical: "zpaq",
feature: "backend-zpaq",
})
}
}
"rwkv7" | "rwkv" => {
if cfg!(feature = "backend-rwkv") {
Some(BackendAvailability::Enabled("rwkv7"))
} else {
Some(BackendAvailability::Disabled {
canonical: "rwkv7",
feature: "backend-rwkv",
})
}
}
"rate-ac" | "rate_ac" | "rateac" => Some(BackendAvailability::Enabled("rate-ac")),
"rate-rans" | "rate_rans" | "raterans" => Some(BackendAvailability::Enabled("rate-rans")),
_ => None,
}
}
pub fn parse_rate_coder(v: &str) -> Option<CoderType> {
match v {
"ac" | "AC" => Some(CoderType::AC),
"rans" | "RANS" | "rANS" => Some(CoderType::RANS),
_ => None,
}
}
#[cfg(feature = "backend-rwkv")]
pub fn parse_rwkv7_coder(v: &str) -> Option<CoderType> {
parse_rate_coder(v)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resolve_rate_backend_name_canonicalizes_aliases() {
assert_eq!(
resolve_rate_backend_name(" Rosa "),
Some(BackendAvailability::Enabled("rosaplus"))
);
assert_eq!(
resolve_rate_backend_name("facctw"),
Some(BackendAvailability::Enabled("fac-ctw"))
);
assert_eq!(
resolve_rate_backend_name("mix"),
Some(BackendAvailability::Enabled("mixture"))
);
assert_eq!(resolve_rate_backend_name("unknown"), None);
}
#[test]
fn resolve_rate_backend_name_reports_feature_disabled() {
if cfg!(feature = "backend-zpaq") {
assert_eq!(
resolve_rate_backend_name("zpaq"),
Some(BackendAvailability::Enabled("zpaq"))
);
} else {
assert_eq!(
resolve_rate_backend_name("zpaq"),
Some(BackendAvailability::Disabled {
canonical: "zpaq",
feature: "backend-zpaq",
})
);
}
if cfg!(feature = "backend-rwkv") {
assert_eq!(
resolve_rate_backend_name("rwkv7"),
Some(BackendAvailability::Enabled("rwkv7"))
);
} else {
assert_eq!(
resolve_rate_backend_name("rwkv"),
Some(BackendAvailability::Disabled {
canonical: "rwkv7",
feature: "backend-rwkv",
})
);
}
if cfg!(feature = "backend-mamba") {
assert_eq!(
resolve_rate_backend_name("mamba1"),
Some(BackendAvailability::Enabled("mamba"))
);
} else {
assert_eq!(
resolve_rate_backend_name("mamba"),
Some(BackendAvailability::Disabled {
canonical: "mamba",
feature: "backend-mamba",
})
);
}
}
#[test]
fn resolve_compression_backend_name_canonicalizes_aliases() {
assert_eq!(resolve_compression_backend_name("unknown"), None);
if cfg!(feature = "backend-zpaq") {
assert_eq!(
resolve_compression_backend_name("zpaq"),
Some(BackendAvailability::Enabled("zpaq"))
);
} else {
assert_eq!(
resolve_compression_backend_name("zpaq"),
Some(BackendAvailability::Disabled {
canonical: "zpaq",
feature: "backend-zpaq",
})
);
}
assert_eq!(
resolve_compression_backend_name("rate_ac"),
Some(BackendAvailability::Enabled("rate-ac"))
);
assert_eq!(
resolve_compression_backend_name("raterans"),
Some(BackendAvailability::Enabled("rate-rans"))
);
if cfg!(feature = "backend-rwkv") {
assert_eq!(
resolve_compression_backend_name("rwkv"),
Some(BackendAvailability::Enabled("rwkv7"))
);
}
}
#[cfg(feature = "backend-rwkv")]
#[test]
fn parse_rwkv7_coder_accepts_common_aliases() {
assert_eq!(parse_rwkv7_coder("ac"), Some(CoderType::AC));
assert_eq!(parse_rwkv7_coder("AC"), Some(CoderType::AC));
assert_eq!(parse_rwkv7_coder("rans"), Some(CoderType::RANS));
assert_eq!(parse_rwkv7_coder("RANS"), Some(CoderType::RANS));
assert_eq!(parse_rwkv7_coder("nope"), None);
}
}