Skip to main content

cssbox_core/
values.rs

1//! CSS value types and resolution.
2
3/// A CSS length-percentage value.
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub enum LengthPercentage {
6    /// An absolute length in pixels.
7    Length(f32),
8    /// A percentage (0.0 to 1.0 internally, specified as 0-100%).
9    Percentage(f32),
10}
11
12impl LengthPercentage {
13    pub fn resolve(&self, reference: f32) -> f32 {
14        match self {
15            LengthPercentage::Length(px) => *px,
16            LengthPercentage::Percentage(pct) => reference * pct,
17        }
18    }
19
20    pub fn px(value: f32) -> Self {
21        LengthPercentage::Length(value)
22    }
23
24    pub fn percent(value: f32) -> Self {
25        LengthPercentage::Percentage(value / 100.0)
26    }
27}
28
29impl Default for LengthPercentage {
30    fn default() -> Self {
31        LengthPercentage::Length(0.0)
32    }
33}
34
35/// A CSS length-percentage-auto value.
36#[derive(Debug, Clone, Copy, PartialEq, Default)]
37pub enum LengthPercentageAuto {
38    Length(f32),
39    Percentage(f32),
40    #[default]
41    Auto,
42}
43
44impl LengthPercentageAuto {
45    pub fn resolve(&self, reference: f32) -> Option<f32> {
46        match self {
47            LengthPercentageAuto::Length(px) => Some(*px),
48            LengthPercentageAuto::Percentage(pct) => Some(reference * pct),
49            LengthPercentageAuto::Auto => None,
50        }
51    }
52
53    pub fn resolve_or(&self, reference: f32, default: f32) -> f32 {
54        self.resolve(reference).unwrap_or(default)
55    }
56
57    pub fn is_auto(&self) -> bool {
58        matches!(self, LengthPercentageAuto::Auto)
59    }
60
61    pub fn px(value: f32) -> Self {
62        LengthPercentageAuto::Length(value)
63    }
64
65    pub fn percent(value: f32) -> Self {
66        LengthPercentageAuto::Percentage(value / 100.0)
67    }
68}
69
70/// A CSS dimension that may be `none` (used for max-width/max-height).
71#[derive(Debug, Clone, Copy, PartialEq, Default)]
72pub enum LengthPercentageNone {
73    Length(f32),
74    Percentage(f32),
75    #[default]
76    None,
77}
78
79impl LengthPercentageNone {
80    pub fn resolve(&self, reference: f32) -> Option<f32> {
81        match self {
82            LengthPercentageNone::Length(px) => Some(*px),
83            LengthPercentageNone::Percentage(pct) => Some(reference * pct),
84            LengthPercentageNone::None => None,
85        }
86    }
87
88    pub fn px(value: f32) -> Self {
89        LengthPercentageNone::Length(value)
90    }
91
92    pub fn percent(value: f32) -> Self {
93        LengthPercentageNone::Percentage(value / 100.0)
94    }
95}
96
97/// Number or auto (used for z-index, flex-grow, etc.).
98#[derive(Debug, Clone, Copy, PartialEq, Default)]
99pub enum NumberOrAuto {
100    Number(f32),
101    #[default]
102    Auto,
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108
109    #[test]
110    fn test_length_percentage_resolve() {
111        let lp = LengthPercentage::px(20.0);
112        assert_eq!(lp.resolve(100.0), 20.0);
113
114        let lp = LengthPercentage::percent(50.0);
115        assert_eq!(lp.resolve(200.0), 100.0);
116    }
117
118    #[test]
119    fn test_length_percentage_auto_resolve() {
120        let v = LengthPercentageAuto::Auto;
121        assert_eq!(v.resolve(100.0), None);
122
123        let v = LengthPercentageAuto::px(30.0);
124        assert_eq!(v.resolve(100.0), Some(30.0));
125
126        let v = LengthPercentageAuto::percent(25.0);
127        assert_eq!(v.resolve(200.0), Some(50.0));
128    }
129}