extern crate alloc;
use alloc::collections::BTreeSet;
use core::num::NonZeroU64;
use crate::metis::{Dot, DotSet};
use super::DotStore;
mod delta;
mod uncovered;
pub use uncovered::UncoveredDot;
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct Dotted<S> {
store: S,
context: DotSet,
}
impl<S: DotStore> Dotted<S> {
#[must_use]
pub fn new() -> Self {
Self {
store: S::default(),
context: DotSet::new(),
}
}
#[must_use]
pub fn from_store(store: S) -> Self {
let mut context = DotSet::new();
for dot in store.dots() {
let _ = context.insert(dot);
}
Self { store, context }
}
#[must_use]
pub fn from_context(context: DotSet) -> Self {
Self {
store: S::default(),
context,
}
}
pub fn try_new(store: S, context: DotSet) -> Result<Self, UncoveredDot> {
for dot in store.dots() {
if !context.contains(dot) {
return Err(UncoveredDot { dot });
}
}
Ok(Self { store, context })
}
#[must_use]
pub fn merge(&self, other: &Self) -> Self {
Self {
store: self
.store
.causal_merge(&self.context, &other.store, &other.context),
context: self.context.merge(&other.context),
}
}
pub fn merge_from(&mut self, other: &Self) {
self.store
.causal_merge_from(&self.context, &other.store, &other.context);
self.context.merge_from(&other.context);
}
#[must_use]
pub fn next_dot(&self, station: u32) -> Dot {
let counter = NonZeroU64::MIN.saturating_add(self.context.high_water_of(station));
Dot::new(station, counter)
}
#[must_use]
pub const fn store(&self) -> &S {
&self.store
}
#[must_use]
pub const fn context(&self) -> &DotSet {
&self.context
}
#[must_use]
pub fn restrict(&self, roster: impl IntoIterator<Item = u32>) -> Self {
let roster: BTreeSet<u32> = roster.into_iter().collect();
Self {
store: self.store.restrict(roster.iter().copied()),
context: self.context.restrict(roster.iter().copied()),
}
}
}