use super::{Dot, DotSet, DotStore, Dotted, Received};
mod condense;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Composer<S> {
station: u32,
state: Dotted<S>,
}
impl<S: DotStore + Clone> Composer<S> {
#[must_use]
pub fn new(station: u32) -> Self {
Self {
station,
state: Dotted::new(),
}
}
#[must_use]
pub const fn adopt(station: u32, state: Dotted<S>) -> Self {
Self { station, state }
}
#[must_use]
pub const fn station(&self) -> u32 {
self.station
}
#[must_use]
pub const fn state(&self) -> &Dotted<S> {
&self.state
}
pub fn compose(&mut self, weave: impl FnOnce(Dot) -> (S, DotSet)) -> (Dot, Dotted<S>) {
let dot = self.state.next_dot(self.station);
let (store, superseded) = weave(dot);
let delta = Self::assemble(store, superseded);
self.state.merge_from(&delta);
(dot, delta)
}
pub fn compose_super(
&mut self,
weave: impl FnOnce(Dot) -> S,
superseded: impl FnOnce(&S) -> DotSet,
) -> (Dot, Dotted<S>) {
let dot = self.state.next_dot(self.station);
let displaced = superseded(self.state.store());
let store = weave(dot);
let delta = Self::assemble(store, displaced);
self.state.merge_from(&delta);
(dot, delta)
}
fn assemble(store: S, superseded: DotSet) -> Dotted<S> {
let mut context = superseded.clone();
for held in store.dots() {
let _ = context.insert(held);
}
Dotted::try_new(store, context).unwrap_or_else(|_| Dotted::from_context(superseded))
}
pub fn retract(&mut self, superseded: DotSet) -> Dotted<S> {
let delta = Dotted::from_context(superseded);
self.state.merge_from(&delta);
delta
}
pub fn absorb(&mut self, from: u32, delta: &Dotted<S>) -> Received {
self.state.merge_from(delta);
Received::witness(from, delta.context().clone())
}
#[must_use]
pub fn owed_to(&self, peer_context: &DotSet) -> Dotted<S> {
self.state.delta_for(peer_context)
}
#[must_use]
pub fn owed_to_witnessed(&self, peer_context: &DotSet, peer_recording: &DotSet) -> Dotted<S> {
self.state.delta_for_witnessed(peer_context, peer_recording)
}
}