From 57562b52d3fb7126b0d0ea1eaf4ef6516a4c1092 Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Tue, 7 Jul 2020 01:06:22 -0400 Subject: [PATCH] map equality is independent of order --- src/atrule/function.rs | 8 ++++++++ src/builtin/mod.rs | 7 +++++++ src/color/mod.rs | 6 +++--- src/common.rs | 6 +++--- src/unit/mod.rs | 4 ++-- src/value/map.rs | 14 ++++++++++++-- src/value/mod.rs | 2 +- src/value/number/mod.rs | 2 +- src/value/sass_function.rs | 2 +- tests/map.rs | 7 ++++++- 10 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/atrule/function.rs b/src/atrule/function.rs index 5a451e2..2985c9a 100644 --- a/src/atrule/function.rs +++ b/src/atrule/function.rs @@ -1,3 +1,5 @@ +use std::hash::{Hash, Hasher}; + use codemap::Span; use crate::{args::FuncArgs, scope::Scope, Token}; @@ -10,6 +12,12 @@ pub(crate) struct Function { pos: Span, } +impl Hash for Function { + fn hash(&self, state: &mut H) { + self.pos.hash(state) + } +} + impl PartialEq for Function { fn eq(&self, other: &Self) -> bool { self.pos == other.pos diff --git a/src/builtin/mod.rs b/src/builtin/mod.rs index 2e8d8e7..325c7e1 100644 --- a/src/builtin/mod.rs +++ b/src/builtin/mod.rs @@ -1,5 +1,6 @@ use std::{ collections::HashMap, + hash::{Hash, Hasher}, sync::atomic::{AtomicUsize, Ordering}, }; @@ -29,6 +30,12 @@ pub(crate) struct Builtin( usize, ); +impl Hash for Builtin { + fn hash(&self, state: &mut H) { + self.1.hash(state) + } +} + impl Builtin { pub fn new(body: fn(CallArgs, &mut Parser<'_>) -> SassResult) -> Builtin { let count = FUNCTION_COUNT.fetch_add(1, Ordering::Relaxed); diff --git a/src/color/mod.rs b/src/color/mod.rs index b099013..2df8d69 100644 --- a/src/color/mod.rs +++ b/src/color/mod.rs @@ -27,7 +27,7 @@ use num_traits::{One, Signed, ToPrimitive, Zero}; mod name; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] pub(crate) struct Color { rgba: Rgba, hsla: Option, @@ -65,7 +65,7 @@ impl Color { } } -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] struct Rgba { red: Number, green: Number, @@ -88,7 +88,7 @@ impl Rgba { } } -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] struct Hsla { hue: Number, saturation: Number, diff --git a/src/common.rs b/src/common.rs index 7fb916d..ccf472c 100644 --- a/src/common.rs +++ b/src/common.rs @@ -61,7 +61,7 @@ impl Op { } } -#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub(crate) enum QuoteKind { Quoted, None, @@ -77,13 +77,13 @@ impl Display for QuoteKind { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(crate) enum Brackets { None, Bracketed, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(crate) enum ListSeparator { Space, Comma, diff --git a/src/unit/mod.rs b/src/unit/mod.rs index 97ef6c6..3785366 100644 --- a/src/unit/mod.rs +++ b/src/unit/mod.rs @@ -7,7 +7,7 @@ pub(crate) use conversion::UNIT_CONVERSION_TABLE; mod conversion; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub(crate) enum Unit { // Absolute units /// Pixels @@ -122,7 +122,7 @@ pub(crate) enum UnitKind { None, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub(crate) struct DivUnit { numer: Unit, denom: Unit, diff --git a/src/value/map.rs b/src/value/map.rs index 820f4e2..55d207b 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -1,4 +1,4 @@ -use std::{slice::Iter, vec::IntoIter}; +use std::{collections::HashSet, slice::Iter, vec::IntoIter}; use crate::{ common::{Brackets, ListSeparator}, @@ -6,9 +6,19 @@ use crate::{ value::Value, }; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Hash)] pub(crate) struct SassMap(Vec<(Value, Value)>); +impl PartialEq for SassMap { + fn eq(&self, other: &Self) -> bool { + let set_one: HashSet<&Value> = self.0.iter().map(|(v1, _)| v1).collect(); + let set_two: HashSet<&Value> = other.0.iter().map(|(v1, _)| v1).collect(); + set_one == set_two + } +} + +impl Eq for SassMap {} + impl SassMap { pub const fn new() -> SassMap { SassMap(Vec::new()) diff --git a/src/value/mod.rs b/src/value/mod.rs index 3c17d2d..47049f4 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -24,7 +24,7 @@ mod number; mod sass_function; // todo: remove Eq and PartialEq impls -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub(crate) enum Value { Important, True, diff --git a/src/value/number/mod.rs b/src/value/number/mod.rs index 00152b5..d3bfcfe 100644 --- a/src/value/number/mod.rs +++ b/src/value/number/mod.rs @@ -16,7 +16,7 @@ mod integer; const PRECISION: usize = 10; -#[derive(Clone, Eq, PartialEq, Ord)] +#[derive(Clone, Eq, PartialEq, Ord, Hash)] pub(crate) enum Number { Small(Rational64), Big(Box), diff --git a/src/value/sass_function.rs b/src/value/sass_function.rs index 1dfc87b..929e55e 100644 --- a/src/value/sass_function.rs +++ b/src/value/sass_function.rs @@ -22,7 +22,7 @@ use crate::{ /// /// The function name is stored in addition to the body /// for use in the builtin function `inspect()` -#[derive(Clone)] +#[derive(Clone, Hash)] pub(crate) enum SassFunction { Builtin(Builtin, Identifier), UserDefined(Box, Identifier), diff --git a/tests/map.rs b/tests/map.rs index 5710b57..3733623 100644 --- a/tests/map.rs +++ b/tests/map.rs @@ -184,6 +184,11 @@ test!( ); test!( map_merge_not_exactly_equal, - "a {\n color: inspect(map-merge((0cm: a), (0mm: b)));;\n}\n", + "a {\n color: inspect(map-merge((0cm: a), (0mm: b)));\n}\n", "a {\n color: (0cm: b);\n}\n" ); +test!( + map_equality_is_independent_of_order, + "a {\n color: (c: d, a: b)==(a: b, c: d);\n}\n", + "a {\n color: true;\n}\n" +);