Skip to main content

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