math_core_renderer_internal/
length.rs

1//! Lengths, both absolute and relative to font size.
2
3// use std::fmt::Write;
4
5#[cfg(feature = "serde")]
6use serde::Serialize;
7use strum_macros::IntoStaticStr;
8
9#[derive(Debug, Clone, Copy, PartialEq, IntoStaticStr)]
10#[cfg_attr(feature = "serde", derive(Serialize))]
11pub enum LengthUnit {
12    // absolute unit
13    #[strum(serialize = "rem")]
14    Rem,
15    // relative units
16    #[strum(serialize = "em")]
17    Em,
18    #[strum(serialize = "ex")]
19    Ex,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq)]
23#[cfg_attr(feature = "serde", derive(Serialize))]
24pub struct Length {
25    value: LengthValue,
26    pub(crate) unit: LengthUnit,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq)]
30#[cfg_attr(feature = "serde", derive(Serialize))]
31#[repr(transparent)]
32#[cfg_attr(feature = "serde", serde(transparent))]
33pub struct LengthValue(pub(crate) f32);
34
35impl Length {
36    pub const fn new(value: f32, unit: LengthUnit) -> Self {
37        Length {
38            value: LengthValue(value),
39            unit,
40        }
41    }
42
43    pub fn push_to_string(&self, output: &mut String) {
44        let mut buffer = dtoa::Buffer::new();
45        let result = buffer.format(self.value.0);
46        // let _ = write!(output, "{}", self.value.0).is_ok();
47        output.push_str(result.strip_suffix(".0").unwrap_or(result));
48        if self.value.0 != 0.0 {
49            output.push_str(<&'static str>::from(self.unit));
50        }
51    }
52
53    pub const fn none() -> Self {
54        Length {
55            value: LengthValue(f32::NAN),
56            unit: LengthUnit::Rem,
57        }
58    }
59
60    pub const fn zero() -> Self {
61        Length {
62            value: LengthValue(0.0),
63            unit: LengthUnit::Rem,
64        }
65    }
66
67    pub const fn into_parts(self) -> (LengthValue, LengthUnit) {
68        (self.value, self.unit)
69    }
70
71    pub fn from_parts(value: LengthValue, unit: LengthUnit) -> Option<Self> {
72        if value.0.is_finite() {
73            Some(Length { value, unit })
74        } else {
75            None
76        }
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83    use LengthUnit::*;
84
85    #[test]
86    fn write() {
87        let mut output = String::new();
88        Length::new(0.0, Rem).push_to_string(&mut output);
89        assert_eq!(&output, "0");
90        output.clear();
91        Length::new(1.0, Rem).push_to_string(&mut output);
92        assert_eq!(&output, "1rem");
93        output.clear();
94        Length::new(10.0, Rem).push_to_string(&mut output);
95        assert_eq!(&output, "10rem");
96        output.clear();
97        Length::new(5965232.0, Rem).push_to_string(&mut output);
98        assert_eq!(&output, "5965232rem");
99        output.clear();
100        Length::new(-5965232.0, Rem).push_to_string(&mut output);
101        assert_eq!(&output, "-5965232rem");
102    }
103
104    #[test]
105    fn write_relative() {
106        let mut output = String::new();
107        Length::new(0.0, Em).push_to_string(&mut output);
108        assert_eq!(&output, "0");
109        output.clear();
110        Length::new(0.0, Ex).push_to_string(&mut output);
111        assert_eq!(&output, "0");
112        output.clear();
113        Length::new(1.0, Em).push_to_string(&mut output);
114        assert_eq!(&output, "1em");
115        output.clear();
116        Length::new(1.0, Ex).push_to_string(&mut output);
117        assert_eq!(&output, "1ex");
118        output.clear();
119        Length::new(546.0, Em).push_to_string(&mut output);
120        assert_eq!(&output, "546em");
121        output.clear();
122        Length::new(546.0, Ex).push_to_string(&mut output);
123        assert_eq!(&output, "546ex");
124        output.clear();
125        Length::new(-546.0, Em).push_to_string(&mut output);
126        assert_eq!(&output, "-546em");
127        output.clear();
128        Length::new(-546.0, Ex).push_to_string(&mut output);
129        assert_eq!(&output, "-546ex");
130        output.clear();
131    }
132}