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)]
16#[typed_value(derive_fields)]
17pub enum NoCalcNumeric {
18    /// A `<length>` value.
19    ///
20    /// <https://drafts.csswg.org/css-values/#lengths>
21    Length(NoCalcLength),
22
23    /// A `<time>` value.
24    ///
25    /// <https://drafts.csswg.org/css-values/#time>
26    Time(Time),
27
28    /// A `<number>` value.
29    ///
30    /// <https://drafts.csswg.org/css-values/#number-value>
31    Number(Number),
32
33    /// A `<percentage>` value.
34    ///
35    /// <https://drafts.csswg.org/css-values/#percentages>
36    Percentage(Percentage),
37    // TODO: Add other values.
38}
39
40impl NoCalcNumeric {
41    /// Return the unitless, raw value.
42    pub fn unitless_value(&self) -> CSSFloat {
43        match *self {
44            Self::Length(v) => v.unitless_value(),
45            Self::Time(v) => v.unitless_value(),
46            Self::Number(v) => v.get(),
47            Self::Percentage(v) => v.get(),
48        }
49    }
50
51    /// Return the unit, as a string.
52    ///
53    /// TODO: Investigate returning SortKey or adding a new variant for
54    /// returning the unit as SortKey. Tracked in
55    /// <https://bugzilla.mozilla.org/show_bug.cgi?id=2015863>
56    pub fn unit(&self) -> &'static str {
57        match *self {
58            Self::Length(v) => v.unit(),
59            Self::Time(v) => v.unit(),
60            Self::Number(v) => v.unit(),
61            Self::Percentage(v) => v.unit(),
62        }
63    }
64
65    /// Return the canonical unit for this value, if one exists.
66    ///
67    /// TODO: Investigate returning SortKey. Tracked in
68    /// <https://bugzilla.mozilla.org/show_bug.cgi?id=2015863>
69    pub fn canonical_unit(&self) -> Option<&'static str> {
70        match *self {
71            Self::Length(v) => v.canonical_unit(),
72            Self::Time(v) => v.canonical_unit(),
73            Self::Number(v) => v.canonical_unit(),
74            Self::Percentage(v) => v.canonical_unit(),
75        }
76    }
77
78    /// Convert this value to the specified unit, if possible.
79    ///
80    /// TODO: Investigate using SortKey. Tracked in
81    /// <https://bugzilla.mozilla.org/show_bug.cgi?id=2015863>
82    pub fn to(&self, unit: &str) -> Result<Self, ()> {
83        match self {
84            Self::Length(v) => Ok(Self::Length(v.to(unit)?)),
85            Self::Time(v) => Ok(Self::Time(v.to(unit)?)),
86            Self::Number(v) => Ok(Self::Number(v.to(unit)?)),
87            Self::Percentage(v) => Ok(Self::Percentage(v.to(unit)?)),
88        }
89    }
90
91    /// Parse a given unit value.
92    pub fn parse_unit_value(value: CSSFloat, unit: &str) -> Result<Self, ()> {
93        if let Ok(length) = NoCalcLength::parse_dimension_with_flags(
94            ParsingMode::DEFAULT,
95            /* in_page_rule = */ false,
96            value,
97            unit,
98        ) {
99            return Ok(NoCalcNumeric::Length(length));
100        }
101
102        if let Ok(time) = Time::parse_dimension(value, unit) {
103            return Ok(NoCalcNumeric::Time(time));
104        }
105
106        match_ignore_ascii_case! { unit,
107            "number" => Ok(NoCalcNumeric::Number(Number::new(value))),
108            "percent" => Ok(NoCalcNumeric::Percentage(Percentage::new(value))),
109            _ => Err(()),
110        }
111
112        // TODO: Add support for other values.
113    }
114}