Skip to main content

style/typed_om/
numeric_values.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Typed OM Numeric Values.
6
7use crate::derives::*;
8use crate::values::specified::{NoCalcLength, Number, Percentage, Time};
9use crate::values::CSSFloat;
10use cssparser::match_ignore_ascii_case;
11use style_traits::ParsingMode;
12
13/// A numeric value without a `calc` expression.
14#[derive(Clone, ToTyped)]
15#[repr(u8)]
16pub enum NoCalcNumeric {
17    /// A `<length>` value.
18    ///
19    /// <https://drafts.csswg.org/css-values/#lengths>
20    Length(NoCalcLength),
21
22    /// A `<time>` value.
23    ///
24    /// <https://drafts.csswg.org/css-values/#time>
25    Time(Time),
26
27    /// A `<number>` value.
28    ///
29    /// <https://drafts.csswg.org/css-values/#number-value>
30    Number(Number),
31
32    /// A `<percentage>` value.
33    ///
34    /// <https://drafts.csswg.org/css-values/#percentages>
35    Percentage(Percentage),
36    // TODO: Add other values.
37}
38
39impl NoCalcNumeric {
40    /// Return the unitless, raw value.
41    pub fn unitless_value(&self) -> CSSFloat {
42        match *self {
43            Self::Length(v) => v.unitless_value(),
44            Self::Time(v) => v.unitless_value(),
45            Self::Number(v) => v.get(),
46            Self::Percentage(v) => v.get(),
47        }
48    }
49
50    /// Return the unit, as a string.
51    ///
52    /// TODO: Investigate returning SortKey or adding a new variant for
53    /// returning the unit as SortKey. Tracked in
54    /// <https://bugzilla.mozilla.org/show_bug.cgi?id=2015863>
55    pub fn unit(&self) -> &'static str {
56        match *self {
57            Self::Length(v) => v.unit(),
58            Self::Time(v) => v.unit(),
59            Self::Number(v) => v.unit(),
60            Self::Percentage(v) => v.unit(),
61        }
62    }
63
64    /// Return the canonical unit for this value, if one exists.
65    ///
66    /// TODO: Investigate returning SortKey. Tracked in
67    /// <https://bugzilla.mozilla.org/show_bug.cgi?id=2015863>
68    pub fn canonical_unit(&self) -> Option<&'static str> {
69        match *self {
70            Self::Length(v) => v.canonical_unit(),
71            Self::Time(v) => v.canonical_unit(),
72            Self::Number(v) => v.canonical_unit(),
73            Self::Percentage(v) => v.canonical_unit(),
74        }
75    }
76
77    /// Convert this value to the specified unit, if possible.
78    ///
79    /// TODO: Investigate using SortKey. Tracked in
80    /// <https://bugzilla.mozilla.org/show_bug.cgi?id=2015863>
81    pub fn to(&self, unit: &str) -> Result<Self, ()> {
82        match self {
83            Self::Length(v) => Ok(Self::Length(v.to(unit)?)),
84            Self::Time(v) => Ok(Self::Time(v.to(unit)?)),
85            Self::Number(v) => Ok(Self::Number(v.to(unit)?)),
86            Self::Percentage(v) => Ok(Self::Percentage(v.to(unit)?)),
87        }
88    }
89
90    /// Parse a given unit value.
91    pub fn parse_unit_value(value: CSSFloat, unit: &str) -> Result<Self, ()> {
92        if let Ok(length) = NoCalcLength::parse_dimension_with_flags(
93            ParsingMode::DEFAULT,
94            /* in_page_rule = */ false,
95            value,
96            unit,
97        ) {
98            return Ok(NoCalcNumeric::Length(length));
99        }
100
101        if let Ok(time) = Time::parse_dimension(value, unit) {
102            return Ok(NoCalcNumeric::Time(time));
103        }
104
105        match_ignore_ascii_case! { unit,
106            "number" => Ok(NoCalcNumeric::Number(Number::new(value))),
107            "percent" => Ok(NoCalcNumeric::Percentage(Percentage::new(value))),
108            _ => Err(()),
109        }
110
111        // TODO: Add support for other values.
112    }
113}