switch(index; v1, v2, v3, ...) draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 08 May 2020 01:13:36 +0200 (2020-05-07)
changeset 2878216 3744db19fd416ec99fbf96962811527f21e069e5
parent 2878215 07b89e261008bd2a5ab8acf14b60561905754b59
child 2878217 fe96acc4986d3644ad0b5897aa4ce3c22f6533c9
push id533539
push useremilio@crisal.io
push dateThu, 07 May 2020 23:40:37 +0000 (2020-05-07)
treeherdertry@fe96acc4986d [default view] [failures only]
milestone78.0a1
switch(index; v1, v2, v3, ...)
servo/components/style/values/specified/calc.rs
--- a/servo/components/style/values/specified/calc.rs
+++ b/servo/components/style/values/specified/calc.rs
@@ -26,16 +26,18 @@ pub enum MathFunction {
     /// `calc()`: https://drafts.csswg.org/css-values-4/#funcdef-calc
     Calc,
     /// `min()`: https://drafts.csswg.org/css-values-4/#funcdef-min
     Min,
     /// `max()`: https://drafts.csswg.org/css-values-4/#funcdef-max
     Max,
     /// `clamp()`: https://drafts.csswg.org/css-values-4/#funcdef-clamp
     Clamp,
+    /// `switch()`: no spec yet.
+    Switch,
 }
 
 /// A leaf node inside a `Calc` expression's AST.
 #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
 pub enum Leaf {
     /// `<length>`
     Length(NoCalcLength),
     /// `<angle>`
@@ -340,16 +342,35 @@ impl CalcNode {
                     let op = match function {
                         MathFunction::Min => MinMaxOp::Min,
                         MathFunction::Max => MinMaxOp::Max,
                         _ => unreachable!(),
                     };
 
                     Ok(Self::MinMax(arguments.into(), op))
                 },
+                MathFunction::Switch => {
+                    let index = match Self::parse_argument(context, input, CalcUnit::Number)?.to_number() {
+                        Ok(n) => n,
+                        Err(()) => return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
+                    };
+
+                    input.expect_semicolon()?;
+
+                    let mut arguments = input.parse_comma_separated(|input| {
+                        Self::parse_argument(context, input, expected_unit)
+                    })?;
+
+                    let index = std::cmp::max(index.round() as i32, 0) as usize;
+                    Ok(if index < arguments.len() {
+                        arguments.remove(index)
+                    } else {
+                        arguments.pop().unwrap()
+                    })
+                },
             }
         })
     }
 
     fn parse_argument<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
         expected_unit: CalcUnit,
@@ -535,16 +556,17 @@ impl CalcNode {
         if !comparison_functions_enabled() {
             return Err(location.new_unexpected_token_error(Token::Function(name.clone())));
         }
 
         Ok(match_ignore_ascii_case! { &*name,
             "min" => MathFunction::Min,
             "max" => MathFunction::Max,
             "clamp" => MathFunction::Clamp,
+            "switch" => MathFunction::Switch,
             _ => return Err(location.new_unexpected_token_error(Token::Function(name.clone()))),
         })
     }
 
     /// Convenience parsing function for integers.
     pub fn parse_integer<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,