// except according to those terms.
use bitvec::BitMatrix;
+use stable_hasher::{HashStable, StableHasher, StableHasherResult};
+use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use std::cell::RefCell;
use std::fmt::Debug;
use std::mem;
+
+
#[derive(Clone)]
pub struct TransitiveRelation<T: Debug + PartialEq> {
// List of elements. This is used to map from a T to a usize. We
closure: RefCell<Option<BitMatrix>>,
}
-#[derive(Clone, PartialEq, PartialOrd)]
+#[derive(Clone, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)]
struct Index(usize);
-#[derive(Clone, PartialEq)]
+#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
struct Edge {
source: Index,
target: Index,
}
}
+ pub fn is_empty(&self) -> bool {
+ self.edges.is_empty()
+ }
+
fn index(&self, a: &T) -> Option<Index> {
self.elements.iter().position(|e| *e == *a).map(Index)
}
}
}
+impl<T> Encodable for TransitiveRelation<T>
+ where T: Encodable + Debug + PartialEq
+{
+ fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+ s.emit_struct("TransitiveRelation", 2, |s| {
+ s.emit_struct_field("elements", 0, |s| self.elements.encode(s))?;
+ s.emit_struct_field("edges", 1, |s| self.edges.encode(s))?;
+ Ok(())
+ })
+ }
+}
+
+impl<T> Decodable for TransitiveRelation<T>
+ where T: Decodable + Debug + PartialEq
+{
+ fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+ d.read_struct("TransitiveRelation", 2, |d| {
+ let elements = d.read_struct_field("elements", 0, |d| Decodable::decode(d))?;
+ let edges = d.read_struct_field("edges", 1, |d| Decodable::decode(d))?;
+ Ok(TransitiveRelation { elements, edges, closure: RefCell::new(None) })
+ })
+ }
+}
+
+impl<CTX, T> HashStable<CTX> for TransitiveRelation<T>
+ where T: HashStable<CTX> + PartialEq + Debug
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ // We are assuming here that the relation graph has been built in a
+ // deterministic way and we can just hash it the way it is.
+ let TransitiveRelation {
+ ref elements,
+ ref edges,
+ // "closure" is just a copy of the data above
+ closure: _
+ } = *self;
+
+ elements.hash_stable(hcx, hasher);
+ edges.hash_stable(hcx, hasher);
+ }
+}
+
+impl<CTX> HashStable<CTX> for Edge {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ let Edge {
+ ref source,
+ ref target,
+ } = *self;
+
+ source.hash_stable(hcx, hasher);
+ target.hash_stable(hcx, hasher);
+ }
+}
+
+impl<CTX> HashStable<CTX> for Index {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ let Index(idx) = *self;
+ idx.hash_stable(hcx, hasher);
+ }
+}
+
#[test]
fn test_one_step() {
let mut relation = TransitiveRelation::new();