Skip to main content

lowfat_core/
level.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::str::FromStr;
4
5/// Intensity level for filtering.
6/// lite = gentle trim, full = default, ultra = max compression.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Default)]
8#[serde(rename_all = "lowercase")]
9pub enum Level {
10    Lite,
11    #[default]
12    Full,
13    Ultra,
14}
15
16impl Level {
17    /// Scale a base head-limit by level.
18    /// lite = 2x, full = base, ultra = max(base/2, 5)
19    pub fn head_limit(&self, base: usize) -> usize {
20        match self {
21            Level::Lite => base * 2,
22            Level::Full => base,
23            Level::Ultra => (base / 2).max(5),
24        }
25    }
26}
27
28impl fmt::Display for Level {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        match self {
31            Level::Lite => write!(f, "lite"),
32            Level::Full => write!(f, "full"),
33            Level::Ultra => write!(f, "ultra"),
34        }
35    }
36}
37
38impl FromStr for Level {
39    type Err = String;
40
41    fn from_str(s: &str) -> Result<Self, Self::Err> {
42        match s.to_lowercase().as_str() {
43            "lite" => Ok(Level::Lite),
44            "full" => Ok(Level::Full),
45            "ultra" => Ok(Level::Ultra),
46            _ => Err(format!("unknown level: {s} (expected: lite, full, ultra)")),
47        }
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn head_limit_lite() {
57        assert_eq!(Level::Lite.head_limit(40), 80);
58    }
59
60    #[test]
61    fn head_limit_full() {
62        assert_eq!(Level::Full.head_limit(40), 40);
63    }
64
65    #[test]
66    fn head_limit_ultra() {
67        assert_eq!(Level::Ultra.head_limit(40), 20);
68    }
69
70    #[test]
71    fn head_limit_ultra_minimum() {
72        // base=8 -> 8/2=4, but min is 5
73        assert_eq!(Level::Ultra.head_limit(8), 5);
74    }
75
76    #[test]
77    fn from_str() {
78        assert_eq!("lite".parse::<Level>().unwrap(), Level::Lite);
79        assert_eq!("FULL".parse::<Level>().unwrap(), Level::Full);
80        assert_eq!("Ultra".parse::<Level>().unwrap(), Level::Ultra);
81        assert!("invalid".parse::<Level>().is_err());
82    }
83
84    #[test]
85    fn display() {
86        assert_eq!(Level::Lite.to_string(), "lite");
87        assert_eq!(Level::Full.to_string(), "full");
88        assert_eq!(Level::Ultra.to_string(), "ultra");
89    }
90}