#[derive(Debug, PartialEq, Copy, Clone)]
pub struct ZRange {
pub min: u64,
pub max: u64,
}
impl ZRange {
#[must_use]
pub const fn mid(&self) -> u64 {
self.min + ((self.max - self.min) >> 1)
}
#[must_use]
pub const fn length(&self) -> u64 {
(self.max - self.min).saturating_add(1)
}
#[must_use]
pub const fn contains(&self, bits: u64) -> bool {
bits >= self.min && bits <= self.max
}
#[must_use]
pub const fn contains_zrange(&self, r: ZRange) -> bool {
self.contains(r.min) && self.contains(r.max)
}
#[must_use]
pub const fn overlaps(&self, other: ZRange) -> bool {
self.min <= other.max && other.min <= self.max
}
}
#[cfg(kani)]
mod kani_proofs {
use super::*;
#[kani::proof]
fn contains_endpoints() {
let min: u64 = kani::any();
let max: u64 = kani::any();
kani::assume(min <= max);
let r = ZRange { min, max };
assert!(r.contains(min));
assert!(r.contains(max));
}
#[kani::proof]
fn contains_zrange_is_pointwise() {
let min: u64 = kani::any();
let max: u64 = kani::any();
kani::assume(min <= max);
let outer = ZRange { min, max };
let r_min: u64 = kani::any();
let r_max: u64 = kani::any();
kani::assume(r_min <= r_max);
let inner = ZRange {
min: r_min,
max: r_max,
};
kani::assume(outer.contains_zrange(inner));
let bits: u64 = kani::any();
kani::assume(bits >= r_min && bits <= r_max);
assert!(outer.contains(bits));
}
#[kani::proof]
fn mid_within_range() {
let min: u64 = kani::any();
let max: u64 = kani::any();
kani::assume(min <= max);
let r = ZRange { min, max };
let m = r.mid();
assert!(m >= min && m <= max);
}
#[kani::proof]
fn length_at_least_one() {
let min: u64 = kani::any();
let max: u64 = kani::any();
kani::assume(min <= max);
let r = ZRange { min, max };
assert!(r.length() >= 1);
}
#[kani::proof]
fn overlaps_is_symmetric() {
let a_min: u64 = kani::any();
let a_max: u64 = kani::any();
kani::assume(a_min <= a_max);
let a = ZRange {
min: a_min,
max: a_max,
};
let b_min: u64 = kani::any();
let b_max: u64 = kani::any();
kani::assume(b_min <= b_max);
let b = ZRange {
min: b_min,
max: b_max,
};
assert_eq!(a.overlaps(b), b.overlaps(a));
}
}