Skip to content

Commit

Permalink
feat(object): Implement Ord (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
andoriyu authored Apr 5, 2020
1 parent 542c912 commit 1fd4f73
Showing 1 changed file with 78 additions and 1 deletion.
79 changes: 78 additions & 1 deletion src/raw/object.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
//! Output of the parser.
//! Objects parsed by the parser.
//!
//! When you are done feeding the parser call `::get_object()` method on a parser. This will give you
//! an owned copy of an `Object`. Difference between `Object` and `ObjectRef` - internal reference count is only decreased for `Object` when dropped.
//!
//! ### Cloning
//!
//! Due to how rust std lib blanket impls work it's impossible to clone `ObjectRef` without converting it into owned `Object`.
//! `Object` implements clone by increasing reference count of object.
//!
//! #### Deep Cloning
//!
//! It's possible to create a deep copy of an `Object` and `ObjectRef` by calling `ObjectRef::deep_copy()`. Copy returned by that method is a completly different object with different address in memory.
//!
//! ### Equality and Ordering
//!
//! Literally all objects can be compared. The order:
//!
//! 1. Type of objects
//! 2. Size of objects
//! 3. Content of objects
//!
//! That means you can compare a string to float, and it will give some result. I'm not sure about usefulness of this, but it is totally possible.
use crate::raw::iterator::Iter;
use crate::raw::{utils, Priority};
use crate::traits::FromObject;
Expand All @@ -25,6 +47,7 @@ use std::num::TryFromIntError;
use std::ops::{Deref, DerefMut};
use std::path::PathBuf;
use std::time::Duration;
use bitflags::_core::cmp::Ordering;

/// Errors that could be returned by `Object` or `ObjectRef` functions.
#[derive(Eq, PartialEq, Debug, Clone)]
Expand Down Expand Up @@ -711,6 +734,35 @@ impl Clone for Object {
}
}

impl PartialOrd for ObjectRef {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let cmp = unsafe { ucl_object_compare(self.as_ptr(), other.as_ptr() )};
match cmp {
cmp if cmp == 0 => Some(Ordering::Equal),
cmp if cmp < 0 => Some(Ordering::Less),
cmp if cmp > 0 => Some(Ordering::Greater),
_ => unreachable!(),
}
}
}

impl Ord for ObjectRef {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}

impl PartialOrd for Object {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.as_ref().partial_cmp(other.as_ref())
}
}

impl Ord for Object {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
#[cfg(test)]
mod test {
use super::*;
Expand All @@ -732,4 +784,29 @@ mod test {
assert_eq!(left, right);
assert_ne!(left.as_ptr(), right.as_ptr());
}

#[test]
fn order_good() {
let left = Object::from(1);
let right = Object::from(2);

assert!(left < right);
}

#[test]
fn order_int_and_float() {

let left = Object::from(1);
let right = Object::from(1.5);

assert!(left < right);
}

#[test]
fn order_wtf() {
let left = Object::from("a string?");
let right = Object::from(2);

assert_ne!(left, right);
}
}

0 comments on commit 1fd4f73

Please sign in to comment.