From f57b08069d6a3501f058526db554eea30a3b0e2b Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Mon, 16 Mar 2020 21:29:00 -0400 Subject: [PATCH] Handle unit multiplication --- src/units.rs | 9 +++++++++ src/value/mod.rs | 8 +++++++- src/value/ops.rs | 15 ++++----------- tests/units.rs | 25 +++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/units.rs b/src/units.rs index 4314ccb..4a8738e 100644 --- a/src/units.rs +++ b/src/units.rs @@ -91,6 +91,11 @@ pub(crate) enum Unit { Unknown(String), /// Unspecified unit None, + + /// Two units multiplied together + Mul(Box, Box), + /// A unit divided by another + Div(Box, Box), } #[derive(Debug, Copy, Clone, Eq, PartialEq)] @@ -223,6 +228,8 @@ impl Into for Unit { Unit::X => "x", Unit::Fr => "fr", Unit::None => "", + Unit::Mul(l, r) => return format!("{}*{}", l, r), + Unit::Div(l, r) => return format!("{}/{}", l, r), Unit::Unknown(ref s) => s, } .into() @@ -269,6 +276,8 @@ impl fmt::Display for Unit { Unit::Fr => write!(f, "fr"), Unit::Unknown(s) => write!(f, "{}", s), Unit::None => write!(f, ""), + Unit::Mul(l, r) => write!(f, "{}*{}", l, r), + Unit::Div(l, r) => write!(f, "{}/{}", l, r), } } } diff --git a/src/value/mod.rs b/src/value/mod.rs index 988b282..d57e5dd 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -29,7 +29,13 @@ impl Display for Value { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Important => write!(f, "!important"), - Self::Dimension(num, unit) => write!(f, "{}{}", num, unit), + Self::Dimension(num, unit) => match unit { + Unit::Mul(..) | Unit::Div(..) => { + eprintln!("Error: {}{} isn't a valid CSS value.", num, unit); + std::process::exit(1); + } + _ => write!(f, "{}{}", num, unit), + }, Self::List(vals, sep) => write!( f, "{}", diff --git a/src/value/ops.rs b/src/value/ops.rs index d2c10f6..a7f4f5f 100644 --- a/src/value/ops.rs +++ b/src/value/ops.rs @@ -200,19 +200,12 @@ impl Mul for Value { Self::Null => todo!(), Self::Dimension(num, unit) => match other { Self::Dimension(num2, unit2) => { - if unit2 != Unit::None && unit != Unit::None { - return Err(format!( - "{}{}*{} isn't a valid CSS value.", - num * num2, - unit, - unit2 - ) - .into()); - } - if unit == unit2 { + if unit == Unit::None { + Value::Dimension(num * num2, unit2) + } else if unit2 == Unit::None { Value::Dimension(num * num2, unit) } else { - todo!("unit conversions") + Value::Dimension(num * num2, Unit::Mul(Box::new(unit), Box::new(unit2))) } } _ => { diff --git a/tests/units.rs b/tests/units.rs index 5b70eea..1582fa5 100644 --- a/tests/units.rs +++ b/tests/units.rs @@ -9,3 +9,28 @@ test!(unit_px, "a {\n height: 1px;\n}\n"); test!(unit_em, "a {\n height: 1em;\n}\n"); test!(unit_rem, "a {\n height: 1rem;\n}\n"); test!(unit_percent, "a {\n height: 1%;\n}\n"); +test!( + unit_times_none, + "a {\n color: 3px * 2;\n}\n", + "a {\n color: 6px;\n}\n" +); +test!( + none_times_unit, + "a {\n color: 2 * 3px;\n}\n", + "a {\n color: 6px;\n}\n" +); +test!( + unit_fn_unit_times_none, + "a {\n color: unit(1px * 1);\n}\n", + "a {\n color: \"px\";\n}\n" +); +test!( + unit_fn_none_times_unit, + "a {\n color: unit(1 * 1px);\n}\n", + "a {\n color: \"px\";\n}\n" +); +test!( + unit_fn_unit_times_unit, + "a {\n color: unit(1px*1px);\n}\n", + "a {\n color: \"px*px\";\n}\n" +);