ranges 0.4.0

This crate provides a generic alternative to core/std ranges, set-operations to work with them and a range set that can efficiently store them with the least amount of memory possible.
Documentation
use core::{
    hash::{Hash, Hasher},
    ops::Bound,
};

use crate::{Domain, GenericRange};

impl<T: Domain + Hash> Hash for GenericRange<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        if <T as Domain>::DISCRETE {
            // canonicalize start and end
            match self.start {
                Bound::Included(_) | Bound::Unbounded => self.start.hash(state),
                Bound::Excluded(ref start) => match start.successor() {
                    None => self.start.hash(state),
                    Some(succ) => Bound::Included(succ).hash(state),
                },
            }

            match self.end {
                Bound::Included(_) | Bound::Unbounded => self.end.hash(state),
                Bound::Excluded(ref end) => match end.predecessor() {
                    None => self.end.hash(state),
                    Some(pre) => Bound::Included(pre).hash(state),
                },
            }
        } else {
            self.start.hash(state);
            self.end.hash(state);
        }
    }
}

#[cfg(test)]
mod tests {
    use core::hash::{Hash, Hasher};
    use std::collections::hash_map::DefaultHasher;

    use proptest::prelude::*;

    use crate::GenericRange;

    fn calculate_hash<T: Hash>(t: &T) -> u64 {
        let mut s = DefaultHasher::new();
        t.hash(&mut s);
        s.finish()
    }

    #[test]
    fn differing_range_same_hash() {
        let range1 = GenericRange::from(5..10);
        let range2 = GenericRange::new_open_closed(4, 9);

        assert_eq!(range1, range2);
        assert_eq!(calculate_hash(&range1), calculate_hash(&range2));
    }

    proptest! {
        #[ignore]
        #[test]
        fn unique_hashes(range1 in any::<GenericRange<u8>>(), range2 in any::<GenericRange<u8>>()) {
            let equality = range1.eq(&range2);
            let hash1 = calculate_hash(&range1);
            let hash2 = calculate_hash(&range2);

            if equality {
                prop_assert_eq!(hash1, hash2);
            } else {
                prop_assert_ne!(hash1, hash2);
            }
        }
    }
}