int-interval 0.8.0

A small, no_std half-open interval algebra library for primitive integer types.
Documentation
// -----------------------------------------------------------------------------
// @generated by xtask/codegen (unsigned)
// DO NOT EDIT MANUALLY.
// Changes will be overwritten.
// -----------------------------------------------------------------------------

use super::*;

mod unit_tests {
    use super::*;

    fn span(lo: u64, hi: u64) -> U64CO {
        U64CO::try_new(lo, hi).unwrap()
    }

    #[test]
    fn basic_overlap() {
        let a = span(2, 6);
        let b = span(4, 8);
        assert_eq!(a.intersection(b), Some(span(4, 6)));
    }

    #[test]
    fn disjoint() {
        let a = span(1, 3);
        let b = span(5, 7);
        assert_eq!(a.intersection(b), None);
    }

    #[test]
    fn containment() {
        let a = span(2, 10);
        let b = span(4, 6);
        assert_eq!(a.intersection(b), Some(b));
    }

    #[test]
    fn identical() {
        let a = span(3, 7);
        assert_eq!(a.intersection(a), Some(a));
    }
}

mod prop_tests {
    use std::{vec, vec::Vec};

    use super::*;
    use proptest::prelude::*;

    fn span(a: u64, b: u64) -> Option<U64CO> {
        let lo = a.min(b);
        let hi = a.max(b);
        U64CO::try_new(lo, hi)
    }

    fn edge_values() -> Vec<u64> {
        let mut v = vec![u64::MIN, u64::MAX, 0, 1];

        if u64::MIN < u64::MAX {
            v.push(u64::MIN.saturating_add(1));
            v.push(u64::MAX.saturating_sub(1));
        }

        v.sort_unstable();
        v.dedup();
        v
    }

    fn edge_scalar() -> impl Strategy<Value = u64> {
        prop::sample::select(edge_values())
    }

    fn mixed_scalar() -> impl Strategy<Value = u64> {
        prop_oneof! {
            3 => edge_scalar(),
            7 => any::<u64>(),
        }
    }

    fn span_strategy() -> impl Strategy<Value = U64CO> {
        (mixed_scalar(), mixed_scalar()).prop_filter_map("non-empty interval", |(a, b)| span(a, b))
    }

    proptest! {
        #![proptest_config(ProptestConfig {
            cases: 64,
            .. ProptestConfig::default()
        })]

        #[test]
        fn intersection_subset(
            x in span_strategy(),
            y in span_strategy(),
            p in mixed_scalar(),
        ) {
            let i = x.intersection(y);

            if let Some(i) = i {
                if i.contains(p) {
                    prop_assert!(x.contains(p));
                    prop_assert!(y.contains(p));
                }
            }
        }

        #[test]
        fn common_points_preserved(
            x in span_strategy(),
            y in span_strategy(),
            p in mixed_scalar(),
        ) {
            if x.contains(p) && y.contains(p) {
                let i = x.intersection(y);
                prop_assert!(i.unwrap().contains(p));
            }
        }

        #[test]
        fn membership_law(
            x in span_strategy(),
            y in span_strategy(),
            p in mixed_scalar(),
        ) {
            let i = x.intersection(y);

            let expected = x.contains(p) && y.contains(p);

            prop_assert_eq!(
                i.map(|z| z.contains(p)).unwrap_or(false),
                expected
            );
        }

        #[test]
        fn bounds_correct(
            x in span_strategy(),
            y in span_strategy(),
        ) {
            let lo = x.start().max(y.start());
            let hi = x.end_excl().min(y.end_excl());

            let expected = U64CO::try_new(lo, hi);

            prop_assert_eq!(x.intersection(y), expected);
        }

        #[test]
        fn empty_iff_no_common_point(
            x in span_strategy(),
            y in span_strategy(),
        ) {
            let lo = x.start().max(y.start());
            let hi = x.end_excl().min(y.end_excl());

            let expected = lo < hi;

            prop_assert_eq!(
                x.intersection(y).is_some(),
                expected
            );
        }

        #[test]
        fn commutative(
            x in span_strategy(),
            y in span_strategy(),
        ) {
            prop_assert_eq!(x.intersection(y), y.intersection(x));
        }

        #[test]
        fn idempotent(
            x in span_strategy(),
        ) {
            prop_assert_eq!(x.intersection(x), Some(x));
        }
    }
}