tailwind_css_fixes/systems/units/length_only/
mod.rs

1use super::*;
2
3mod traits;
4
5#[derive(Clone, Debug)]
6pub enum UnitValue {
7    Number { n: f32, is_negative: bool },
8    Length(LengthUnit),
9    Keyword(String),
10    Arbitrary(TailwindArbitrary),
11}
12
13impl Display for UnitValue {
14    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
15        match self {
16            Self::Number { n, .. } => write!(f, "{}", n.abs()),
17            Self::Length(n) => write!(f, "{}", n),
18            Self::Keyword(s) => write!(f, "{}", s),
19            Self::Arbitrary(s) => write!(f, "{}", s),
20        }
21    }
22}
23
24// noinspection DuplicatedCode
25impl UnitValue {
26    pub fn px(x: f32) -> Self {
27        Self::Length(LengthUnit::px(x))
28    }
29    pub fn ratio(a: u32, b: u32) -> Self {
30        Self::Length(LengthUnit::ratio(a, b))
31    }
32    pub fn get_properties(&self, number: impl FnOnce(&f32) -> String) -> String {
33        match self {
34            Self::Number { n, .. } => number(n),
35            Self::Length(n) => n.get_properties(),
36            Self::Keyword(s) => s.to_string(),
37            Self::Arbitrary(s) => s.get_properties(),
38        }
39    }
40    pub fn get_properties_rem(&self) -> String {
41        self.get_properties(|f| format!("{}rem", f / 4.0))
42    }
43    pub fn write_negative(&self, f: &mut Formatter) -> std::fmt::Result {
44        match is_negative(self) {
45            true => write!(f, "-"),
46            false => write!(f, ""),
47        }
48    }
49    pub fn write_class(&self, f: &mut Formatter, before: &str) -> std::fmt::Result {
50        write!(f, "{}{}", before, self)
51    }
52}
53
54pub fn is_negative(value: &UnitValue) -> bool {
55    match *value {
56        UnitValue::Number { n, is_negative } if is_negative => n < 0.0,
57        _ => false,
58    }
59}
60
61impl UnitValue {
62    pub fn negative_parser(
63        id: &'static str,
64        check_valid: impl Fn(&str) -> bool,
65        is_length: bool,
66        is_integer: bool,
67        allow_fraction: bool,
68    ) -> impl Fn(&[&str], &TailwindArbitrary, Negative) -> Result<Self> {
69        move |pattern: &[&str], arbitrary: &TailwindArbitrary, negative: Negative| {
70            let kind = match pattern {
71                [] => Self::parse_arbitrary(arbitrary)?,
72                [s] if check_valid(s) => Self::Keyword(s.to_string()),
73                [n] => Self::parse_number(n, negative, is_length, is_integer, allow_fraction)?,
74                _ => {
75                    let msg = format!("Unknown {} instructions: {}", id, pattern.join("-"));
76                    return Err(TailwindError::syntax_error(msg));
77                },
78            };
79            Ok(kind)
80        }
81    }
82    pub fn positive_parser(
83        id: &'static str,
84        check_valid: impl Fn(&str) -> bool,
85        is_length: bool,
86        is_integer: bool,
87        allow_fraction: bool,
88    ) -> impl Fn(&[&str], &TailwindArbitrary) -> Result<Self> {
89        move |pattern: &[&str], arbitrary: &TailwindArbitrary| {
90            let kind = match pattern {
91                [] => Self::parse_arbitrary(arbitrary)?,
92                [s] if check_valid(s) => Self::Keyword(s.to_string()),
93                [n] => Self::parse_number(n, Negative::from(false), is_length, is_integer, allow_fraction)?,
94                _ => {
95                    let msg = format!("Unknown {} instructions: {}", id, pattern.join("-"));
96                    return Err(TailwindError::syntax_error(msg));
97                },
98            };
99            Ok(kind)
100        }
101    }
102    pub fn parse_arbitrary(arbitrary: &TailwindArbitrary) -> Result<Self> {
103        Ok(Self::Arbitrary(TailwindArbitrary::new(arbitrary)?))
104    }
105    pub fn parse_number(n: &str, negative: Negative, is_length: bool, is_integer: bool, can_be_fraction: bool) -> Result<Self> {
106        let a = TailwindArbitrary::from(n);
107        match is_length {
108            true => Self::maybe_length(&a, can_be_fraction),
109            false => Self::maybe_angle(&a),
110        }
111        .or_else(|_| Self::maybe_number(&a, negative, is_integer))
112    }
113    fn maybe_number(arbitrary: &TailwindArbitrary, negative: Negative, is_integer: bool) -> Result<Self> {
114        let mut n = match is_integer {
115            true => arbitrary.as_integer()? as f32,
116            false => arbitrary.as_float()?,
117        };
118        if negative.0 {
119            n = -n
120        };
121        Ok(Self::Number { n, is_negative: negative.0 })
122    }
123    fn maybe_length(arbitrary: &TailwindArbitrary, allow_fraction: bool) -> Result<Self> {
124        let n = match allow_fraction {
125            true => arbitrary.as_length_or_fraction(),
126            false => arbitrary.as_length(),
127        }?;
128        Ok(Self::Length(n))
129    }
130    fn maybe_angle(arbitrary: &TailwindArbitrary) -> Result<Self> {
131        Ok(Self::Length(arbitrary.as_angle()?))
132    }
133}