style/typed_om/
numeric_declaration.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 Declaration.
6
7use crate::derives::*;
8use crate::parser::{Parse, ParserContext};
9use crate::typed_om::numeric_values::NoCalcNumeric;
10use crate::values::generics::calc::CalcUnits;
11use crate::values::specified::calc::{AllowParse, CalcNode};
12use crate::values::specified::NoCalcLength;
13use cssparser::{Parser, Token};
14use style_traits::values::specified::AllowedNumericType;
15use style_traits::{ParseError, StyleParseErrorKind};
16
17/// A numeric declaration, with or without a `calc()` expression.
18#[derive(Clone, ToTyped)]
19#[typed_value(derive_fields)]
20pub enum NumericDeclaration {
21    /// A numeric value without a `calc()` expression.
22    NoCalc(NoCalcNumeric),
23
24    /// A numeric value represented by a `calc()` expression.
25    ///
26    /// <https://drafts.csswg.org/css-values/#calc-notation>
27    Calc(CalcNode),
28}
29
30impl Parse for NumericDeclaration {
31    /// <https://drafts.css-houdini.org/css-typed-om-1/#dom-cssnumericvalue-parse>
32    fn parse<'i, 't>(
33        context: &ParserContext,
34        input: &mut Parser<'i, 't>,
35    ) -> Result<Self, ParseError<'i>> {
36        let location = input.current_source_location();
37
38        // Step 1.
39        let token = input.next()?;
40
41        // Step 2.
42        match *token {
43            Token::Dimension {
44                value, ref unit, ..
45            } => {
46                NoCalcLength::parse_dimension_with_context(context, value, unit)
47                    .map(NoCalcNumeric::Length)
48                    .map(Self::NoCalc)
49                    .map_err(|()| location.new_unexpected_token_error(token.clone()))
50
51                // TODO: Add support for other values.
52
53                // Step 3.
54
55                // TODO: A type should be created from unit and if that fails, the failure
56                // should be propagated here.
57            },
58
59            Token::Function(ref name) => {
60                let function = CalcNode::math_function(context, name, location)?;
61                let allow_all_units = AllowParse::new(CalcUnits::ALL);
62                let node = CalcNode::parse(context, input, function, allow_all_units)?;
63
64                let allow_all_types = AllowedNumericType::All;
65                let _ = node
66                    .clone()
67                    .into_length_or_percentage(allow_all_types)
68                    .map_err(|()| {
69                        location.new_custom_error(StyleParseErrorKind::UnspecifiedError)
70                    })?;
71
72                // TODO: Add support for other values represented by a `calc()` expression.
73
74                Ok(Self::Calc(node))
75            },
76
77            ref token => return Err(location.new_unexpected_token_error(token.clone())),
78        }
79    }
80}