Skip to content

Commit

Permalink
feat(value): Convinience eq/cmp impls
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Dec 5, 2018
1 parent ea5ac0a commit 78f7a95
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 53 deletions.
138 changes: 108 additions & 30 deletions liquid-value/src/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ impl<'s> ScalarCow<'s> {
}
}

impl<'s> fmt::Display for ScalarCow<'s> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let data = self.to_str();
write!(f, "{}", data)
}
}

impl<'s> From<i32> for ScalarCow<'s> {
fn from(s: i32) -> Self {
ScalarCow {
Expand Down Expand Up @@ -206,46 +213,117 @@ impl<'s> From<borrow::Cow<'s, str>> for ScalarCow<'s> {

impl<'s> PartialEq<ScalarCow<'s>> for ScalarCow<'s> {
fn eq(&self, other: &Self) -> bool {
match (&self.0, &other.0) {
(&ScalarCowEnum::Integer(x), &ScalarCowEnum::Integer(y)) => x == y,
(&ScalarCowEnum::Integer(x), &ScalarCowEnum::Float(y)) => (f64::from(x)) == y,
(&ScalarCowEnum::Float(x), &ScalarCowEnum::Integer(y)) => x == (f64::from(y)),
(&ScalarCowEnum::Float(x), &ScalarCowEnum::Float(y)) => x == y,
(&ScalarCowEnum::Bool(x), &ScalarCowEnum::Bool(y)) => x == y,
(&ScalarCowEnum::Date(x), &ScalarCowEnum::Date(y)) => x == y,
(&ScalarCowEnum::Str(ref x), &ScalarCowEnum::Str(ref y)) => x == y,
// encode Ruby truthiness: all values except false and nil are true
(_, &ScalarCowEnum::Bool(b)) | (&ScalarCowEnum::Bool(b), _) => b,
_ => false,
}
scalar_eq(self, other)
}
}

impl<'s> PartialEq<i32> for ScalarCow<'s> {
fn eq(&self, other: &i32) -> bool {
let other = (*other).into();
scalar_eq(self, &other)
}
}

impl<'s> PartialEq<f64> for ScalarCow<'s> {
fn eq(&self, other: &f64) -> bool {
let other = (*other).into();
scalar_eq(self, &other)
}
}

impl<'s> PartialEq<bool> for ScalarCow<'s> {
fn eq(&self, other: &bool) -> bool {
let other = (*other).into();
scalar_eq(self, &other)
}
}

impl<'s> PartialEq<Date> for ScalarCow<'s> {
fn eq(&self, other: &Date) -> bool {
let other = (*other).into();
scalar_eq(self, &other)
}
}

impl<'s> PartialEq<str> for ScalarCow<'s> {
fn eq(&self, other: &str) -> bool {
let other = other.into();
scalar_eq(self, &other)
}
}

impl<'s> Eq for ScalarCow<'s> {}

impl<'s> PartialOrd<ScalarCow<'s>> for ScalarCow<'s> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (&self.0, &other.0) {
(&ScalarCowEnum::Integer(x), &ScalarCowEnum::Integer(y)) => x.partial_cmp(&y),
(&ScalarCowEnum::Integer(x), &ScalarCowEnum::Float(y)) => {
(f64::from(x)).partial_cmp(&y)
}
(&ScalarCowEnum::Float(x), &ScalarCowEnum::Integer(y)) => {
x.partial_cmp(&(f64::from(y)))
}
(&ScalarCowEnum::Float(x), &ScalarCowEnum::Float(y)) => x.partial_cmp(&y),
(&ScalarCowEnum::Bool(x), &ScalarCowEnum::Bool(y)) => x.partial_cmp(&y),
(&ScalarCowEnum::Date(x), &ScalarCowEnum::Date(y)) => x.partial_cmp(&y),
(&ScalarCowEnum::Str(ref x), &ScalarCowEnum::Str(ref y)) => x.partial_cmp(y),
_ => None,
}
scalar_cmp(self, other)
}
}

impl<'s> fmt::Display for ScalarCow<'s> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let data = self.to_str();
write!(f, "{}", data)
impl<'s> PartialOrd<i32> for ScalarCow<'s> {
fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
let other = (*other).into();
scalar_cmp(self, &other)
}
}

impl<'s> PartialOrd<f64> for ScalarCow<'s> {
fn partial_cmp(&self, other: &f64) -> Option<Ordering> {
let other = (*other).into();
scalar_cmp(self, &other)
}
}

impl<'s> PartialOrd<bool> for ScalarCow<'s> {
fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
let other = (*other).into();
scalar_cmp(self, &other)
}
}

impl<'s> PartialOrd<Date> for ScalarCow<'s> {
fn partial_cmp(&self, other: &Date) -> Option<Ordering> {
let other = (*other).into();
scalar_cmp(self, &other)
}
}

impl<'s> PartialOrd<str> for ScalarCow<'s> {
fn partial_cmp(&self, other: &str) -> Option<Ordering> {
let other = other.into();
scalar_cmp(self, &other)
}
}

fn scalar_eq<'s>(lhs: &ScalarCow<'s>, rhs: &ScalarCow<'s>) -> bool {
match (&lhs.0, &rhs.0) {
(&ScalarCowEnum::Integer(x), &ScalarCowEnum::Integer(y)) => x == y,
(&ScalarCowEnum::Integer(x), &ScalarCowEnum::Float(y)) => (f64::from(x)) == y,
(&ScalarCowEnum::Float(x), &ScalarCowEnum::Integer(y)) => x == (f64::from(y)),
(&ScalarCowEnum::Float(x), &ScalarCowEnum::Float(y)) => x == y,
(&ScalarCowEnum::Bool(x), &ScalarCowEnum::Bool(y)) => x == y,
(&ScalarCowEnum::Date(x), &ScalarCowEnum::Date(y)) => x == y,
(&ScalarCowEnum::Str(ref x), &ScalarCowEnum::Str(ref y)) => x == y,
// encode Ruby truthiness: all values except false and nil are true
(_, &ScalarCowEnum::Bool(b)) | (&ScalarCowEnum::Bool(b), _) => b,
_ => false,
}
}

fn scalar_cmp<'s>(lhs: &ScalarCow<'s>, rhs: &ScalarCow<'s>) -> Option<Ordering> {
match (&lhs.0, &rhs.0) {
(&ScalarCowEnum::Integer(x), &ScalarCowEnum::Integer(y)) => x.partial_cmp(&y),
(&ScalarCowEnum::Integer(x), &ScalarCowEnum::Float(y)) => {
(f64::from(x)).partial_cmp(&y)
}
(&ScalarCowEnum::Float(x), &ScalarCowEnum::Integer(y)) => {
x.partial_cmp(&(f64::from(y)))
}
(&ScalarCowEnum::Float(x), &ScalarCowEnum::Float(y)) => x.partial_cmp(&y),
(&ScalarCowEnum::Bool(x), &ScalarCowEnum::Bool(y)) => x.partial_cmp(&y),
(&ScalarCowEnum::Date(x), &ScalarCowEnum::Date(y)) => x.partial_cmp(&y),
(&ScalarCowEnum::Str(ref x), &ScalarCowEnum::Str(ref y)) => x.partial_cmp(y),
_ => None,
}
}

Expand Down
54 changes: 31 additions & 23 deletions liquid-value/src/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,42 +300,50 @@ impl Default for Value {
}
}

impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let data = self.to_str();
write!(f, "{}", data)
}
}

impl PartialEq<Value> for Value {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(&Value::Scalar(ref x), &Value::Scalar(ref y)) => x == y,
(&Value::Array(ref x), &Value::Array(ref y)) => x == y,
(&Value::Object(ref x), &Value::Object(ref y)) => x == y,
(&Value::Nil, &Value::Nil) => true,

// encode Ruby truthiness: all values except false and nil are true
(&Value::Nil, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), &Value::Nil) => {
!b.to_bool().unwrap_or(true)
}
(_, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), _) => b.to_bool().unwrap_or(false),

_ => false,
}
value_eq(self, other)
}
}

impl Eq for Value {}

impl PartialOrd<Value> for Value {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (self, other) {
(&Value::Scalar(ref x), &Value::Scalar(ref y)) => x.partial_cmp(y),
(&Value::Array(ref x), &Value::Array(ref y)) => x.iter().partial_cmp(y.iter()),
(&Value::Object(ref x), &Value::Object(ref y)) => x.iter().partial_cmp(y.iter()),
_ => None,
value_cmp(self, other)
}
}

fn value_eq(lhs: &Value, rhs: &Value) -> bool {
match (lhs, rhs) {
(&Value::Scalar(ref x), &Value::Scalar(ref y)) => x == y,
(&Value::Array(ref x), &Value::Array(ref y)) => x == y,
(&Value::Object(ref x), &Value::Object(ref y)) => x == y,
(&Value::Nil, &Value::Nil) => true,

// encode Ruby truthiness: all values except false and nil are true
(&Value::Nil, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), &Value::Nil) => {
!b.to_bool().unwrap_or(true)
}
(_, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), _) => b.to_bool().unwrap_or(false),

_ => false,
}
}

impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let data = self.to_str();
write!(f, "{}", data)
fn value_cmp(lhs: &Value, rhs: &Value) -> Option<Ordering> {
match (lhs, rhs) {
(&Value::Scalar(ref x), &Value::Scalar(ref y)) => x.partial_cmp(y),
(&Value::Array(ref x), &Value::Array(ref y)) => x.iter().partial_cmp(y.iter()),
(&Value::Object(ref x), &Value::Object(ref y)) => x.iter().partial_cmp(y.iter()),
_ => None,
}
}

Expand Down

0 comments on commit 78f7a95

Please sign in to comment.