From ca6ad97159b89666e1ce821b3cbed9bd8321745b Mon Sep 17 00:00:00 2001 From: David Shin Date: Mon, 20 Jun 2022 17:45:03 +0000 Subject: [PATCH] style: Refactor function parsing branches for `specified::easing::TimingFunction` Differential Revision: https://phabricator.services.mozilla.com/D149756 --- components/style/values/specified/easing.rs | 142 +++++++++++--------- 1 file changed, 78 insertions(+), 64 deletions(-) diff --git a/components/style/values/specified/easing.rs b/components/style/values/specified/easing.rs index 2166fffdba6..b6883627cea 100644 --- a/components/style/values/specified/easing.rs +++ b/components/style/values/specified/easing.rs @@ -53,74 +53,88 @@ impl Parse for TimingFunction { let location = input.current_source_location(); let function = input.expect_function()?.clone(); input.parse_nested_block(move |i| { - (match_ignore_ascii_case! { &function, - "cubic-bezier" => { - let x1 = Number::parse(context, i)?; - i.expect_comma()?; - let y1 = Number::parse(context, i)?; - i.expect_comma()?; - let x2 = Number::parse(context, i)?; - i.expect_comma()?; - let y2 = Number::parse(context, i)?; - - if x1.get() < 0.0 || x1.get() > 1.0 || x2.get() < 0.0 || x2.get() > 1.0 { - return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)); - } - - Ok(GenericTimingFunction::CubicBezier { x1, y1, x2, y2 }) - }, - "steps" => { - let steps = Integer::parse_positive(context, i)?; - let position = i.try_parse(|i| { - i.expect_comma()?; - StepPosition::parse(context, i) - }).unwrap_or(StepPosition::End); - - // jump-none accepts a positive integer greater than 1. - // FIXME(emilio): The spec asks us to avoid rejecting it at parse - // time except until computed value time. - // - // It's not totally clear it's worth it though, and no other browser - // does this. - if position == StepPosition::JumpNone && 2 > steps.value() { - return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)); - } - Ok(GenericTimingFunction::Steps(steps, position)) - }, - "linear" => { - if !linear_timing_function_enabled() { - return Err(i.new_custom_error(StyleParseErrorKind::ExperimentalProperty)); - } - if i.is_exhausted() { - return Ok(GenericTimingFunction::LinearFunction(crate::OwnedSlice::default())) - } - let entries = i.parse_comma_separated(|i| { - let mut input_start = i.try_parse(|i| Percentage::parse(context, i)).ok(); - let mut input_end = i.try_parse(|i| Percentage::parse(context, i)).ok(); - - let output = Number::parse(context, i)?; - if input_start.is_none() { - debug_assert!(input_end.is_none(), "Input end parsed without input start?"); - input_start = i.try_parse(|i| Percentage::parse(context, i)).ok(); - input_end = i.try_parse(|i| Percentage::parse(context, i)).ok(); - } - Ok(GenericLinearStop { - output, - input_start: input_start.into(), - input_end: input_end.into() - }) - })?; - Ok(GenericTimingFunction::LinearFunction(crate::OwnedSlice::from(entries))) - }, - _ => Err(()), - }) - .map_err(|()| { - location.new_custom_error(StyleParseErrorKind::UnexpectedFunction(function.clone())) - }) + match_ignore_ascii_case! { &function, + "cubic-bezier" => Self::parse_cubic_bezier(context, i), + "steps" => Self::parse_steps(context, i), + "linear" => Self::parse_linear_function(context, i), + _ => Err(location.new_custom_error(StyleParseErrorKind::UnexpectedFunction(function.clone()))), + } }) } } +impl TimingFunction { + fn parse_cubic_bezier<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + let x1 = Number::parse(context, input)?; + input.expect_comma()?; + let y1 = Number::parse(context, input)?; + input.expect_comma()?; + let x2 = Number::parse(context, input)?; + input.expect_comma()?; + let y2 = Number::parse(context, input)?; + + if x1.get() < 0.0 || x1.get() > 1.0 || x2.get() < 0.0 || x2.get() > 1.0 { + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + + Ok(GenericTimingFunction::CubicBezier { x1, y1, x2, y2 }) + } + + fn parse_steps<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + let steps = Integer::parse_positive(context, input)?; + let position = input.try_parse(|i| { + i.expect_comma()?; + StepPosition::parse(context, i) + }).unwrap_or(StepPosition::End); + + // jump-none accepts a positive integer greater than 1. + // FIXME(emilio): The spec asks us to avoid rejecting it at parse + // time except until computed value time. + // + // It's not totally clear it's worth it though, and no other browser + // does this. + if position == StepPosition::JumpNone && steps.value() <= 1 { + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + Ok(GenericTimingFunction::Steps(steps, position)) + } + + fn parse_linear_function<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + if !linear_timing_function_enabled() { + return Err(input.new_custom_error(StyleParseErrorKind::ExperimentalProperty)); + } + if input.is_exhausted() { + return Ok(GenericTimingFunction::LinearFunction(crate::OwnedSlice::default())) + } + let entries = input.parse_comma_separated(|i| { + let mut input_start = i.try_parse(|i| Percentage::parse(context, i)).ok(); + let mut input_end = i.try_parse(|i| Percentage::parse(context, i)).ok(); + + let output = Number::parse(context, i)?; + if input_start.is_none() { + debug_assert!(input_end.is_none(), "Input end parsed without input start?"); + input_start = i.try_parse(|i| Percentage::parse(context, i)).ok(); + input_end = i.try_parse(|i| Percentage::parse(context, i)).ok(); + } + Ok(GenericLinearStop { + output, + input_start: input_start.into(), + input_end: input_end.into() + }) + })?; + Ok(GenericTimingFunction::LinearFunction(crate::OwnedSlice::from(entries))) + } +} + // We need this for converting the specified TimingFunction into computed TimingFunction without // Context (for some FFIs in glue.rs). In fact, we don't really need Context to get the computed // value of TimingFunction.