use crate::derives::*;
use crate::parser::{Parse, ParserContext};
use crate::typed_om::numeric::NoCalcNumeric;
use crate::values::generics::calc::CalcUnits;
use crate::values::specified::calc::{CalcNode, CalcParseFlags};
use crate::values::specified::{
NoCalcAngle, NoCalcLength, NoCalcNumber, NoCalcPercentage, NoCalcTime,
};
use cssparser::{Parser, Token};
use style_traits::values::specified::AllowedNumericType;
use style_traits::{ParseError, StyleParseErrorKind};
#[derive(Clone, ToTyped)]
pub enum NumericDeclaration {
NoCalc(NoCalcNumeric),
Calc(CalcNode),
}
impl Parse for NumericDeclaration {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let token = input.next()?;
match *token {
Token::Number { value, .. } => Ok(Self::NoCalc(NoCalcNumeric::Number(
NoCalcNumber::new(value),
))),
Token::Percentage { unit_value, .. } => Ok(Self::NoCalc(NoCalcNumeric::Percentage(
NoCalcPercentage::new(unit_value),
))),
Token::Dimension {
value, ref unit, ..
} => {
if let Ok(length) = NoCalcLength::parse_dimension_with_context(context, value, unit)
{
return Ok(Self::NoCalc(NoCalcNumeric::Length(length)));
}
if let Ok(angle) = NoCalcAngle::parse_dimension(value, unit) {
return Ok(Self::NoCalc(NoCalcNumeric::Angle(angle)));
}
if let Ok(time) = NoCalcTime::parse_dimension(value, unit) {
return Ok(Self::NoCalc(NoCalcNumeric::Time(time)));
}
Err(location.new_unexpected_token_error(token.clone()))
},
Token::Function(ref name) => {
let function = CalcNode::math_function(context, name, location)?;
let allow_all_units = CalcParseFlags::new(CalcUnits::ALL);
let node = CalcNode::parse(context, input, function, allow_all_units)?;
let allow_all_types = AllowedNumericType::All;
let _ = node
.clone()
.into_length_or_percentage(allow_all_types)
.map_err(|()| {
location.new_custom_error(StyleParseErrorKind::UnspecifiedError)
})?;
Ok(Self::Calc(node))
},
ref token => return Err(location.new_unexpected_token_error(token.clone())),
}
}
}