diff --git a/src/types/mod.rs b/src/types/mod.rs index c44f492..188cc3f 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -15,17 +15,44 @@ pub struct Boolean(bool); #[derive(Clone, Copy, Debug, PartialEq)] pub struct Character(char); -pub trait Value: Debug + 'static { } -impl Value for Boolean { } -impl Value for Character { } +pub trait Value: Debug + ValueEq { + fn as_value(&self) -> &Value; +} -impl<'a,'b> PartialEq<&'a Value> for &'b Value { - fn eq(&self, other: &&Value) -> bool { - other.as_any().downcast_ref::().map_or(false, |x| x == self) +/// A trait on value types that makes it easier to compare values of disparate types. The methods +/// provided by this trait are used by the PartialEq implementation on Values. +pub trait ValueEq { + fn eq(&self, other: &Value) -> bool; + fn as_any(&self) -> &Any; +} + +impl<'lhs,'rhs> PartialEq for Value+'lhs { + fn eq(&self, other: &(Value+'rhs)) -> bool { + ValueEq::eq(self, other) } } -impl Value { +impl Value for Boolean { + fn as_value(&self) -> &Value { self } +} + +impl ValueEq for Boolean { + fn eq(&self, other: &Value) -> bool { + other.as_any().downcast_ref::().map_or(false, |x| x == self) + } + + fn as_any(&self) -> &Any { self } +} + +impl Value for Character { + fn as_value(&self) -> &Value { self } +} + +impl ValueEq for Character { + fn eq(&self, other: &Value) -> bool { + other.as_any().downcast_ref::().map_or(false, |x| x == self) + } + fn as_any(&self) -> &Any { self } } @@ -39,4 +66,15 @@ mod tests { assert_eq!(Boolean(false), Boolean(false)); assert_ne!(Boolean(true), Boolean(false)); } + + #[test] + fn equal_chars_are_equal() { + assert_eq!(Character('a'), Character('a')); + assert_eq!(Character('a').as_value(), Character('a').as_value()); + } + + #[test] + fn booleans_and_chars_are_not_equal() { + assert_ne!(Boolean(true).as_value(), Character('a').as_value()); + } }