From dbe7f2d50b13f4478d4d827b2b624e1c25e9b712 Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Sat, 1 Aug 2020 14:33:22 -0400 Subject: [PATCH] use `Unit` rather than string as key to unit conversion map --- src/parse/value/eval.rs | 31 +---- src/unit/conversion.rs | 249 ++++++++++++++++++++-------------------- src/value/mod.rs | 19 +-- src/value/number/mod.rs | 2 +- 4 files changed, 133 insertions(+), 168 deletions(-) diff --git a/src/parse/value/eval.rs b/src/parse/value/eval.rs index 20ccfbd..acb9ef3 100644 --- a/src/parse/value/eval.rs +++ b/src/parse/value/eval.rs @@ -9,7 +9,7 @@ use crate::{ args::CallArgs, common::{Op, QuoteKind}, error::SassResult, - unit::{Unit, UNIT_CONVERSION_TABLE}, + unit::Unit, value::{SassFunction, Value}, }; @@ -228,16 +228,7 @@ impl<'a, 'b: 'a> ValueVisitor<'a, 'b> { } else if unit2 == Unit::None { Value::Dimension(Some(num + num2), unit, true) } else { - Value::Dimension( - Some( - num + num2 - * UNIT_CONVERSION_TABLE[unit.to_string().as_str()] - [unit2.to_string().as_str()] - .clone(), - ), - unit, - true, - ) + Value::Dimension(Some(num + num2.convert(&unit2, &unit)), unit, true) } } Value::String(s, q) => Value::String(format!("{}{}{}", num, unit, s), q), @@ -341,16 +332,7 @@ impl<'a, 'b: 'a> ValueVisitor<'a, 'b> { } else if unit2 == Unit::None { Value::Dimension(Some(num - num2), unit, true) } else { - Value::Dimension( - Some( - num - num2 - * UNIT_CONVERSION_TABLE[unit.to_string().as_str()] - [unit2.to_string().as_str()] - .clone(), - ), - unit, - true, - ) + Value::Dimension(Some(num - num2.convert(&unit2, &unit)), unit, true) } } Value::List(..) @@ -529,12 +511,7 @@ impl<'a, 'b: 'a> ValueVisitor<'a, 'b> { // `unit(1in / 1px)` => `""` } else if unit.comparable(&unit2) { Value::Dimension( - Some( - num / (num2 - * UNIT_CONVERSION_TABLE[unit.to_string().as_str()] - [unit2.to_string().as_str()] - .clone()), - ), + Some(num / num2.convert(&unit2, &unit)), Unit::None, true, ) diff --git a/src/unit/conversion.rs b/src/unit/conversion.rs index b848d19..8862d14 100644 --- a/src/unit/conversion.rs +++ b/src/unit/conversion.rs @@ -7,152 +7,151 @@ use std::{collections::HashMap, f64::consts::PI}; use num_traits::One; use once_cell::sync::Lazy; -use crate::value::Number; +use crate::{unit::Unit, value::Number}; -pub(crate) static UNIT_CONVERSION_TABLE: Lazy< - HashMap<&'static str, HashMap<&'static str, Number>>, -> = Lazy::new(|| { - let mut from_in = HashMap::new(); - from_in.insert("in", Number::one()); - from_in.insert("cm", Number::one() / Number::from(2.54)); - from_in.insert("pc", Number::small_ratio(1, 6)); - from_in.insert("mm", Number::one() / Number::from(25.4)); - from_in.insert("q", Number::one() / Number::from(101.6)); - from_in.insert("pt", Number::small_ratio(1, 72)); - from_in.insert("px", Number::small_ratio(1, 96)); +pub(crate) static UNIT_CONVERSION_TABLE: Lazy>> = + Lazy::new(|| { + let mut from_in = HashMap::new(); + from_in.insert(Unit::In, Number::one()); + from_in.insert(Unit::Cm, Number::one() / Number::from(2.54)); + from_in.insert(Unit::Pc, Number::small_ratio(1, 6)); + from_in.insert(Unit::Mm, Number::one() / Number::from(25.4)); + from_in.insert(Unit::Q, Number::one() / Number::from(101.6)); + from_in.insert(Unit::Pt, Number::small_ratio(1, 72)); + from_in.insert(Unit::Px, Number::small_ratio(1, 96)); - let mut from_cm = HashMap::new(); - from_cm.insert("in", Number::from(2.54)); - from_cm.insert("cm", Number::one()); - from_cm.insert("pc", Number::from(2.54) / Number::from(6)); - from_cm.insert("mm", Number::small_ratio(1, 10)); - from_cm.insert("q", Number::small_ratio(1, 40)); - from_cm.insert("pt", Number::from(2.54) / Number::from(72)); - from_cm.insert("px", Number::from(2.54) / Number::from(96)); + let mut from_cm = HashMap::new(); + from_cm.insert(Unit::In, Number::from(2.54)); + from_cm.insert(Unit::Cm, Number::one()); + from_cm.insert(Unit::Pc, Number::from(2.54) / Number::from(6)); + from_cm.insert(Unit::Mm, Number::small_ratio(1, 10)); + from_cm.insert(Unit::Q, Number::small_ratio(1, 40)); + from_cm.insert(Unit::Pt, Number::from(2.54) / Number::from(72)); + from_cm.insert(Unit::Px, Number::from(2.54) / Number::from(96)); - let mut from_pc = HashMap::new(); - from_pc.insert("in", Number::from(6)); - from_pc.insert("cm", Number::from(6) / Number::from(2.54)); - from_pc.insert("pc", Number::one()); - from_pc.insert("mm", Number::from(6) / Number::from(25.4)); - from_pc.insert("q", Number::from(6) / Number::from(101.6)); - from_pc.insert("pt", Number::small_ratio(1, 12)); - from_pc.insert("px", Number::small_ratio(1, 16)); + let mut from_pc = HashMap::new(); + from_pc.insert(Unit::In, Number::from(6)); + from_pc.insert(Unit::Cm, Number::from(6) / Number::from(2.54)); + from_pc.insert(Unit::Pc, Number::one()); + from_pc.insert(Unit::Mm, Number::from(6) / Number::from(25.4)); + from_pc.insert(Unit::Q, Number::from(6) / Number::from(101.6)); + from_pc.insert(Unit::Pt, Number::small_ratio(1, 12)); + from_pc.insert(Unit::Px, Number::small_ratio(1, 16)); - let mut from_mm = HashMap::new(); - from_mm.insert("in", Number::from(25.4)); - from_mm.insert("cm", Number::from(10)); - from_mm.insert("pc", Number::from(25.4) / Number::from(6)); - from_mm.insert("mm", Number::one()); - from_mm.insert("q", Number::small_ratio(1, 4)); - from_mm.insert("pt", Number::from(25.4) / Number::from(72)); - from_mm.insert("px", Number::from(25.4) / Number::from(96)); + let mut from_mm = HashMap::new(); + from_mm.insert(Unit::In, Number::from(25.4)); + from_mm.insert(Unit::Cm, Number::from(10)); + from_mm.insert(Unit::Pc, Number::from(25.4) / Number::from(6)); + from_mm.insert(Unit::Mm, Number::one()); + from_mm.insert(Unit::Q, Number::small_ratio(1, 4)); + from_mm.insert(Unit::Pt, Number::from(25.4) / Number::from(72)); + from_mm.insert(Unit::Px, Number::from(25.4) / Number::from(96)); - let mut from_q = HashMap::new(); - from_q.insert("in", Number::from(101.6)); - from_q.insert("cm", Number::from(40)); - from_q.insert("pc", Number::from(101.6) / Number::from(6)); - from_q.insert("mm", Number::from(4)); - from_q.insert("q", Number::one()); - from_q.insert("pt", Number::from(101.6) / Number::from(72)); - from_q.insert("px", Number::from(101.6) / Number::from(96)); + let mut from_q = HashMap::new(); + from_q.insert(Unit::In, Number::from(101.6)); + from_q.insert(Unit::Cm, Number::from(40)); + from_q.insert(Unit::Pc, Number::from(101.6) / Number::from(6)); + from_q.insert(Unit::Mm, Number::from(4)); + from_q.insert(Unit::Q, Number::one()); + from_q.insert(Unit::Pt, Number::from(101.6) / Number::from(72)); + from_q.insert(Unit::Px, Number::from(101.6) / Number::from(96)); - let mut from_pt = HashMap::new(); - from_pt.insert("in", Number::from(72)); - from_pt.insert("cm", Number::from(72) / Number::from(2.54)); - from_pt.insert("pc", Number::from(12)); - from_pt.insert("mm", Number::from(72) / Number::from(25.4)); - from_pt.insert("q", Number::from(72) / Number::from(101.6)); - from_pt.insert("pt", Number::one()); - from_pt.insert("px", Number::small_ratio(3, 4)); + let mut from_pt = HashMap::new(); + from_pt.insert(Unit::In, Number::from(72)); + from_pt.insert(Unit::Cm, Number::from(72) / Number::from(2.54)); + from_pt.insert(Unit::Pc, Number::from(12)); + from_pt.insert(Unit::Mm, Number::from(72) / Number::from(25.4)); + from_pt.insert(Unit::Q, Number::from(72) / Number::from(101.6)); + from_pt.insert(Unit::Pt, Number::one()); + from_pt.insert(Unit::Px, Number::small_ratio(3, 4)); - let mut from_px = HashMap::new(); - from_px.insert("in", Number::from(96)); - from_px.insert("cm", Number::from(96) / Number::from(2.54)); - from_px.insert("pc", Number::from(16)); - from_px.insert("mm", Number::from(96) / Number::from(25.4)); - from_px.insert("q", Number::from(96) / Number::from(101.6)); - from_px.insert("pt", Number::small_ratio(4, 3)); - from_px.insert("px", Number::one()); + let mut from_px = HashMap::new(); + from_px.insert(Unit::In, Number::from(96)); + from_px.insert(Unit::Cm, Number::from(96) / Number::from(2.54)); + from_px.insert(Unit::Pc, Number::from(16)); + from_px.insert(Unit::Mm, Number::from(96) / Number::from(25.4)); + from_px.insert(Unit::Q, Number::from(96) / Number::from(101.6)); + from_px.insert(Unit::Pt, Number::small_ratio(4, 3)); + from_px.insert(Unit::Px, Number::one()); - let mut from_deg = HashMap::new(); - from_deg.insert("deg", Number::one()); - from_deg.insert("grad", Number::small_ratio(9, 10)); - from_deg.insert("rad", Number::from(180) / Number::from(PI)); - from_deg.insert("turn", Number::from(360)); + let mut from_deg = HashMap::new(); + from_deg.insert(Unit::Deg, Number::one()); + from_deg.insert(Unit::Grad, Number::small_ratio(9, 10)); + from_deg.insert(Unit::Rad, Number::from(180) / Number::from(PI)); + from_deg.insert(Unit::Turn, Number::from(360)); - let mut from_grad = HashMap::new(); - from_grad.insert("deg", Number::small_ratio(10, 9)); - from_grad.insert("grad", Number::one()); - from_grad.insert("rad", Number::from(200) / Number::from(PI)); - from_grad.insert("turn", Number::from(400)); + let mut from_grad = HashMap::new(); + from_grad.insert(Unit::Deg, Number::small_ratio(10, 9)); + from_grad.insert(Unit::Grad, Number::one()); + from_grad.insert(Unit::Rad, Number::from(200) / Number::from(PI)); + from_grad.insert(Unit::Turn, Number::from(400)); - let mut from_rad = HashMap::new(); - from_rad.insert("deg", Number::from(PI) / Number::from(180)); - from_rad.insert("grad", Number::from(PI) / Number::from(200)); - from_rad.insert("rad", Number::one()); - from_rad.insert("turn", Number::from(2.0 * PI)); + let mut from_rad = HashMap::new(); + from_rad.insert(Unit::Deg, Number::from(PI) / Number::from(180)); + from_rad.insert(Unit::Grad, Number::from(PI) / Number::from(200)); + from_rad.insert(Unit::Rad, Number::one()); + from_rad.insert(Unit::Turn, Number::from(2.0 * PI)); - let mut from_turn = HashMap::new(); - from_turn.insert("deg", Number::small_ratio(1, 360)); - from_turn.insert("grad", Number::small_ratio(1, 400)); - from_turn.insert("rad", Number::one() / Number::from(2.0 * PI)); - from_turn.insert("turn", Number::one()); + let mut from_turn = HashMap::new(); + from_turn.insert(Unit::Deg, Number::small_ratio(1, 360)); + from_turn.insert(Unit::Grad, Number::small_ratio(1, 400)); + from_turn.insert(Unit::Rad, Number::one() / Number::from(2.0 * PI)); + from_turn.insert(Unit::Turn, Number::one()); - let mut from_s = HashMap::new(); - from_s.insert("s", Number::one()); - from_s.insert("ms", Number::small_ratio(1, 1000)); + let mut from_s = HashMap::new(); + from_s.insert(Unit::S, Number::one()); + from_s.insert(Unit::Ms, Number::small_ratio(1, 1000)); - let mut from_ms = HashMap::new(); - from_ms.insert("s", Number::from(1000)); - from_ms.insert("ms", Number::one()); + let mut from_ms = HashMap::new(); + from_ms.insert(Unit::S, Number::from(1000)); + from_ms.insert(Unit::Ms, Number::one()); - let mut from_hz = HashMap::new(); - from_hz.insert("Hz", Number::one()); - from_hz.insert("kHz", Number::from(1000)); + let mut from_hz = HashMap::new(); + from_hz.insert(Unit::Hz, Number::one()); + from_hz.insert(Unit::Khz, Number::from(1000)); - let mut from_khz = HashMap::new(); - from_khz.insert("Hz", Number::small_ratio(1, 1000)); - from_khz.insert("kHz", Number::one()); + let mut from_khz = HashMap::new(); + from_khz.insert(Unit::Hz, Number::small_ratio(1, 1000)); + from_khz.insert(Unit::Khz, Number::one()); - let mut from_dpi = HashMap::new(); - from_dpi.insert("dpi", Number::one()); - from_dpi.insert("dpcm", Number::from(2.54)); - from_dpi.insert("dppx", Number::from(96)); + let mut from_dpi = HashMap::new(); + from_dpi.insert(Unit::Dpi, Number::one()); + from_dpi.insert(Unit::Dpcm, Number::from(2.54)); + from_dpi.insert(Unit::Dppx, Number::from(96)); - let mut from_dpcm = HashMap::new(); - from_dpcm.insert("dpi", Number::one() / Number::from(2.54)); - from_dpcm.insert("dpcm", Number::one()); - from_dpcm.insert("dppx", Number::from(96) / Number::from(2.54)); + let mut from_dpcm = HashMap::new(); + from_dpcm.insert(Unit::Dpi, Number::one() / Number::from(2.54)); + from_dpcm.insert(Unit::Dpcm, Number::one()); + from_dpcm.insert(Unit::Dppx, Number::from(96) / Number::from(2.54)); - let mut from_dppx = HashMap::new(); - from_dppx.insert("dpi", Number::small_ratio(1, 96)); - from_dppx.insert("dpcm", Number::from(2.54) / Number::from(96)); - from_dppx.insert("dppx", Number::one()); + let mut from_dppx = HashMap::new(); + from_dppx.insert(Unit::Dpi, Number::small_ratio(1, 96)); + from_dppx.insert(Unit::Dpcm, Number::from(2.54) / Number::from(96)); + from_dppx.insert(Unit::Dppx, Number::one()); - let mut m = HashMap::new(); - m.insert("in", from_in); - m.insert("cm", from_cm); - m.insert("pc", from_pc); - m.insert("mm", from_mm); - m.insert("q", from_q); - m.insert("pt", from_pt); - m.insert("px", from_px); + let mut m = HashMap::new(); + m.insert(Unit::In, from_in); + m.insert(Unit::Cm, from_cm); + m.insert(Unit::Pc, from_pc); + m.insert(Unit::Mm, from_mm); + m.insert(Unit::Q, from_q); + m.insert(Unit::Pt, from_pt); + m.insert(Unit::Px, from_px); - m.insert("deg", from_deg); - m.insert("grad", from_grad); - m.insert("rad", from_rad); - m.insert("turn", from_turn); + m.insert(Unit::Deg, from_deg); + m.insert(Unit::Grad, from_grad); + m.insert(Unit::Rad, from_rad); + m.insert(Unit::Turn, from_turn); - m.insert("s", from_s); - m.insert("ms", from_ms); + m.insert(Unit::S, from_s); + m.insert(Unit::Ms, from_ms); - m.insert("Hz", from_hz); - m.insert("kHz", from_khz); + m.insert(Unit::Hz, from_hz); + m.insert(Unit::Khz, from_khz); - m.insert("dpi", from_dpi); - m.insert("dpcm", from_dpcm); - m.insert("dppx", from_dppx); + m.insert(Unit::Dpi, from_dpi); + m.insert(Unit::Dpcm, from_dpcm); + m.insert(Unit::Dppx, from_dppx); - m -}); + m + }); diff --git a/src/value/mod.rs b/src/value/mod.rs index f88c6c5..d9b13b3 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -10,7 +10,7 @@ use crate::{ error::SassResult, parse::Parser, selector::Selector, - unit::{Unit, UNIT_CONVERSION_TABLE}, + unit::Unit, utils::hex_char_for, {Cow, Token}, }; @@ -58,10 +58,7 @@ impl PartialEq for Value { } else if unit == &Unit::None || unit2 == &Unit::None { false } else { - n == &(n2.clone() - * UNIT_CONVERSION_TABLE[unit.to_string().as_str()] - [unit2.to_string().as_str()] - .clone()) + n == &n2.clone().convert(unit2, unit) } } _ => false, @@ -352,12 +349,7 @@ impl Value { if unit == unit2 || unit == &Unit::None || unit2 == &Unit::None { num.cmp(num2) } else { - num.cmp( - &(num2.clone() - * UNIT_CONVERSION_TABLE[unit.to_string().as_str()] - [unit2.to_string().as_str()] - .clone()), - ) + num.cmp(&num2.clone().convert(unit2, unit)) } } v => { @@ -412,10 +404,7 @@ impl Value { } else if unit == &Unit::None || unit2 == &Unit::None { true } else { - n != &(n2.clone() - * UNIT_CONVERSION_TABLE[unit.to_string().as_str()] - [unit2.to_string().as_str()] - .clone()) + n != &n2.clone().convert(unit2, unit) } } _ => true, diff --git a/src/value/number/mod.rs b/src/value/number/mod.rs index cff80a5..c8d552d 100644 --- a/src/value/number/mod.rs +++ b/src/value/number/mod.rs @@ -139,7 +139,7 @@ impl Number { /// Invariants: `from.comparable(&to)` must be true pub fn convert(self, from: &Unit, to: &Unit) -> Self { - self * UNIT_CONVERSION_TABLE[to.to_string().as_str()][from.to_string().as_str()].clone() + self * UNIT_CONVERSION_TABLE[to][from].clone() } }