diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-05-18 15:44:49 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-05-18 15:44:49 +0200 |
| commit | 6b08862b83950c32890858431a680f4069cee439 (patch) | |
| tree | 3cc6e11b6213156426ded9a59ec051fa57f67b19 /src/eval/value.rs | |
| parent | 8b58171d7ca036d71b32749286c251cc91bdd10e (diff) | |
Streamline value comparisons
Diffstat (limited to 'src/eval/value.rs')
| -rw-r--r-- | src/eval/value.rs | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/src/eval/value.rs b/src/eval/value.rs index 288e5ed7..84701b3d 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -1,4 +1,5 @@ use std::any::Any; +use std::cmp::Ordering; use std::collections::BTreeMap; use std::fmt::{self, Debug, Display, Formatter}; use std::ops::Deref; @@ -57,6 +58,14 @@ impl Value { Self::Template(vec![TemplateNode::Func(TemplateFunc::new(name, f))]) } + /// Try to cast the value into a specific type. + pub fn cast<T>(self) -> CastResult<T, Self> + where + T: Cast<Value>, + { + T::cast(self) + } + /// The name of the stored value's type. pub fn type_name(&self) -> &'static str { match self { @@ -79,12 +88,37 @@ impl Value { } } - /// Try to cast the value into a specific type. - pub fn cast<T>(self) -> CastResult<T, Self> - where - T: Cast<Value>, - { - T::cast(self) + /// Recursively compute whether two values are equal. + pub fn eq(&self, rhs: &Self) -> bool { + match (self, rhs) { + (&Self::Int(a), &Self::Float(b)) => a as f64 == b, + (&Self::Float(a), &Self::Int(b)) => a == b as f64, + (&Self::Length(a), &Self::Linear(b)) => a == b.abs && b.rel.is_zero(), + (&Self::Relative(a), &Self::Linear(b)) => a == b.rel && b.abs.is_zero(), + (&Self::Linear(a), &Self::Length(b)) => a.abs == b && a.rel.is_zero(), + (&Self::Linear(a), &Self::Relative(b)) => a.rel == b && a.abs.is_zero(), + (Self::Array(a), Self::Array(b)) => { + a.len() == b.len() && a.iter().zip(b).all(|(x, y)| x.eq(y)) + } + (Self::Dict(a), Self::Dict(b)) => { + a.len() == b.len() + && a.iter().all(|(k, x)| b.get(k).map_or(false, |y| x.eq(y))) + } + (a, b) => a == b, + } + } + + /// Compare a value with another value. + pub fn cmp(&self, rhs: &Self) -> Option<Ordering> { + match (self, rhs) { + (Self::Int(a), Self::Int(b)) => a.partial_cmp(b), + (Self::Int(a), Self::Float(b)) => (*a as f64).partial_cmp(b), + (Self::Float(a), Self::Int(b)) => a.partial_cmp(&(*b as f64)), + (Self::Float(a), Self::Float(b)) => a.partial_cmp(b), + (Self::Angle(a), Self::Angle(b)) => a.partial_cmp(b), + (Self::Length(a), Self::Length(b)) => a.partial_cmp(b), + _ => None, + } } } |
