use std::{
borrow::Borrow,
cmp::Ordering,
collections::BTreeSet,
fmt::Debug,
ops::{Bound, Deref},
};
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(transparent)]
pub(super) struct Active<T>(pub(super) T);
impl<T> Active<T> {
pub(super) fn active_ref(t: &T) -> &Active<T> {
unsafe { std::mem::transmute(t) }
}
}
impl<T> Borrow<T> for Active<T> {
fn borrow(&self) -> &T {
&self.0
}
}
impl<T> Deref for Active<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: PartialEq> Eq for Active<T> {}
impl<T: PartialOrd + Debug> Ord for Active<T> {
fn cmp(&self, other: &Self) -> Ordering {
if let Some(c) = T::partial_cmp(self, other) {
c
} else {
warn!("could not compare segments:\n\t{self:?}\n\t{other:?}");
panic!("unable to compare active segments!");
}
}
}
impl<T: PartialOrd + Debug> PartialOrd for Active<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub(super) trait ActiveSet: Default {
type Seg;
fn previous_find<F: FnMut(&Active<Self::Seg>) -> bool>(
&self,
segment: &Self::Seg,
f: F,
) -> Option<&Active<Self::Seg>>;
fn previous(&self, segment: &Self::Seg) -> Option<&Active<Self::Seg>> {
self.previous_find(segment, |_| true)
}
fn next_find<F: FnMut(&Active<Self::Seg>) -> bool>(
&self,
segment: &Self::Seg,
f: F,
) -> Option<&Active<Self::Seg>>;
fn next(&self, segment: &Self::Seg) -> Option<&Active<Self::Seg>> {
self.next_find(segment, |_| true)
}
fn insert_active(&mut self, segment: Self::Seg);
fn remove_active(&mut self, segment: &Self::Seg);
}
impl<T: PartialOrd + Debug> ActiveSet for BTreeSet<Active<T>> {
type Seg = T;
fn previous_find<F: FnMut(&Active<Self::Seg>) -> bool>(
&self,
segment: &Self::Seg,
mut f: F,
) -> Option<&Active<Self::Seg>> {
self.range::<Active<_>, _>((
Bound::Unbounded,
Bound::Excluded(Active::active_ref(segment)),
))
.rev()
.find(|&a| f(a))
}
fn next_find<F: FnMut(&Active<Self::Seg>) -> bool>(
&self,
segment: &Self::Seg,
mut f: F,
) -> Option<&Active<Self::Seg>> {
self.range::<Active<_>, _>((
Bound::Excluded(Active::active_ref(segment)),
Bound::Unbounded,
))
.find(|&a| f(a))
}
fn insert_active(&mut self, segment: Self::Seg) {
let result = self.insert(Active(segment));
debug_assert!(result);
}
fn remove_active(&mut self, segment: &Self::Seg) {
let result = self.remove(Active::active_ref(segment));
debug_assert!(result);
}
}