diff --git a/src/annotation.rs b/src/annotation.rs index 93f976e..6a0ebc7 100644 --- a/src/annotation.rs +++ b/src/annotation.rs @@ -63,15 +63,21 @@ impl PyAnnotation { self.map(|annotation| Ok(annotation.id() == Some(other))) } - fn __richcmp__(&self, other: PyRef, op: CompareOp) -> Py { - let py = other.py(); + fn __richcmp__(&self, other: PyRef, op: CompareOp) -> bool { match op { - CompareOp::Eq => (self.handle == other.handle).into_py(py), - CompareOp::Ne => (self.handle != other.handle).into_py(py), - _ => py.NotImplemented(), + CompareOp::Eq => self.handle == other.handle, + CompareOp::Ne => self.handle != other.handle, + CompareOp::Lt => self.handle < other.handle, + CompareOp::Gt => self.handle > other.handle, + CompareOp::Le => self.handle <= other.handle, + CompareOp::Ge => self.handle >= other.handle, } } + fn __hash__(&self) -> usize { + self.handle.as_usize() + } + /// Returns a generator over all data in this annotation fn __iter__(&self) -> PyResult { Ok(PyDataIter { diff --git a/src/annotationdata.rs b/src/annotationdata.rs index eaf429d..9b6ee27 100644 --- a/src/annotationdata.rs +++ b/src/annotationdata.rs @@ -2,6 +2,7 @@ use pyo3::exceptions::{PyRuntimeError, PyValueError}; use pyo3::prelude::*; use pyo3::pyclass::CompareOp; use pyo3::types::*; +use std::hash::{Hash, Hasher}; use std::ops::FnOnce; use std::sync::{Arc, RwLock}; @@ -66,12 +67,19 @@ impl PyDataKey { fn __richcmp__(&self, other: PyRef, op: CompareOp) -> Py { let py = other.py(); match op { - CompareOp::Eq => (self.handle == other.handle).into_py(py), - CompareOp::Ne => (self.handle != other.handle).into_py(py), + CompareOp::Eq => (self.set == other.set && self.handle == other.handle).into_py(py), + CompareOp::Ne => (self.set != other.set || self.handle != other.handle).into_py(py), _ => py.NotImplemented(), } } + fn __hash__(&self) -> u64 { + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + let h = (self.set.as_usize(), self.handle.as_usize()); + h.hash(&mut hasher); + hasher.finish() + } + /// Returns the AnnotationDataSet this key is part of fn dataset(&self) -> PyResult { Ok(PyAnnotationDataSet { @@ -424,12 +432,19 @@ impl PyAnnotationData { fn __richcmp__(&self, other: PyRef, op: CompareOp) -> Py { let py = other.py(); match op { - CompareOp::Eq => (self.handle == other.handle).into_py(py), - CompareOp::Ne => (self.handle != other.handle).into_py(py), + CompareOp::Eq => (self.set == other.set && self.handle == other.handle).into_py(py), + CompareOp::Ne => (self.set != other.set || self.handle != other.handle).into_py(py), _ => py.NotImplemented(), } } + fn __hash__(&self) -> u64 { + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + let h = (self.set.as_usize(), self.handle.as_usize()); + h.hash(&mut hasher); + hasher.finish() + } + /// Returns the AnnotationDataSet this data is part of fn annotationset(&self) -> PyResult { Ok(PyAnnotationDataSet::new(self.set, &self.store)) diff --git a/src/annotationdataset.rs b/src/annotationdataset.rs index c94af92..4295723 100644 --- a/src/annotationdataset.rs +++ b/src/annotationdataset.rs @@ -55,15 +55,21 @@ impl PyAnnotationDataSet { self.map(|annotationset| Ok(annotationset.id() == Some(other))) } - fn __richcmp__(&self, other: PyRef, op: CompareOp) -> Py { - let py = other.py(); + fn __richcmp__(&self, other: PyRef, op: CompareOp) -> bool { match op { - CompareOp::Eq => (self.handle == other.handle).into_py(py), - CompareOp::Ne => (self.handle != other.handle).into_py(py), - _ => py.NotImplemented(), + CompareOp::Eq => self.handle == other.handle, + CompareOp::Ne => self.handle != other.handle, + CompareOp::Lt => self.handle < other.handle, + CompareOp::Gt => self.handle > other.handle, + CompareOp::Le => self.handle <= other.handle, + CompareOp::Ge => self.handle >= other.handle, } } + fn __hash__(&self) -> usize { + self.handle.as_usize() + } + /// Save the annotation dataset to a STAM JSON file fn to_json_file(&self, filename: &str) -> PyResult<()> { self.map(|annotationset| { diff --git a/src/resources.rs b/src/resources.rs index efa4c3b..c0a1429 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -56,15 +56,21 @@ impl PyTextResource { self.map(|res| Ok(res.id() == Some(other))) } - fn __richcmp__(&self, other: PyRef, op: CompareOp) -> Py { - let py = other.py(); + fn __richcmp__(&self, other: PyRef, op: CompareOp) -> bool { match op { - CompareOp::Eq => (self.handle == other.handle).into_py(py), - CompareOp::Ne => (self.handle != other.handle).into_py(py), - _ => py.NotImplemented(), + CompareOp::Eq => self.handle == other.handle, + CompareOp::Ne => self.handle != other.handle, + CompareOp::Lt => self.handle < other.handle, + CompareOp::Gt => self.handle > other.handle, + CompareOp::Le => self.handle <= other.handle, + CompareOp::Ge => self.handle >= other.handle, } } + fn __hash__(&self) -> usize { + self.handle.as_usize() + } + /// Returns the full text of the resource (by value, aka a copy) fn __str__<'py>(&self, py: Python<'py>) -> PyResult<&'py PyString> { self.text(py) diff --git a/src/textselection.rs b/src/textselection.rs index 6f94a57..9b343ce 100644 --- a/src/textselection.rs +++ b/src/textselection.rs @@ -2,6 +2,7 @@ use pyo3::exceptions::PyRuntimeError; use pyo3::prelude::*; use pyo3::pyclass::CompareOp; use pyo3::types::*; +use std::hash::{Hash, Hasher}; use std::ops::FnOnce; use std::sync::{Arc, RwLock}; @@ -108,6 +109,13 @@ impl PyTextSelection { } } + fn __hash__(&self) -> u64 { + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + let h = (self.resource_handle.as_usize(), self.textselection); + h.hash(&mut hasher); + hasher.finish() + } + /// Returns the resource this textselections points at fn resource(&self) -> PyResult { Ok(PyTextResource {