extern crate alloc;
use alloc::boxed::Box;
use alloc::vec;
use alloc::vec::Vec;
use crate::kairos::{Clock, Kairos, TickCounter};
use crate::metis::{Anchor, Dot, DotSet, Dotted, Locus, Metatheses, Metathesis, Retired, Rhapsody};
use super::super::{Note, OldDelta};
use super::{Replica, Text, fold_native};
impl Replica {
fn next_dot(&mut self) -> Dot {
self.counter += 1;
Dot::from_parts(self.id, self.counter).expect("a pre-incremented counter is nonzero")
}
pub fn insert_visible(&mut self, at: usize, out: &mut Vec<Note>) -> Dot {
if self.transition.is_some() {
return self.insert_native(at, out);
}
let dot = self.next_dot();
let (delta, _) = weave_delta(self.text.store(), &self.clock, dot, at);
self.commit_old(vec![dot], OldDelta::Text(Box::new(delta)), out);
dot
}
pub fn insert_disciplined(&mut self, at: usize, out: &mut Vec<Note>) -> Dot {
assert!(
self.transition.is_none(),
"replica {}: the disciplined weave is an old-plane operation",
self.id
);
let mut oath = self.text.store().clone();
let _ = oath.condense(&Retired::trust(self.acked.clone()));
let dot = self.next_dot();
let (delta, _) = weave_delta_disciplined(self.text.store(), &oath, &self.clock, dot, at);
self.commit_old(vec![dot], OldDelta::Text(Box::new(delta)), out);
dot
}
pub fn delete_visible(&mut self, at: usize, out: &mut Vec<Note>) -> Option<Dot> {
if self.transition.is_some() {
return self.delete_native(at, out);
}
let order = self.text.store().order();
if order.is_empty() {
return None;
}
let target = order[at % order.len()];
let marker = self.next_dot();
let delta = removal_delta(marker, target);
self.commit_old(vec![marker], OldDelta::Text(Box::new(delta)), out);
Some(target)
}
pub fn move_visible(
&mut self,
from: usize,
to_after: Option<usize>,
out: &mut Vec<Note>,
) -> Option<Dot> {
assert!(
self.transition.is_none(),
"replica {}: old-plane moves are a pre-adoption operation",
self.id
);
let order = self.text.store().recension(self.moves.store()).order();
if order.is_empty() {
return None;
}
let target = order[from % order.len()];
let after = to_after
.map(|index| order[index % order.len()])
.filter(|&dot| dot != target);
let anchor = after.map_or(Anchor::Origin, |dot| Anchor::After(dot.into()));
let rank = self.rank_above(anchor);
let dot = self.next_dot();
let delta = Dotted::from_store(Metatheses::singleton(
dot,
Metathesis {
target: target.into(),
to: Locus { anchor, rank },
},
));
self.commit_old(vec![dot], OldDelta::Moves(delta), out);
Some(dot)
}
pub fn condense(&mut self) -> usize {
assert!(
self.transition.is_none(),
"replica {}: condense is an old-plane operation",
self.id
);
let retired = self.retirement.retired();
let mut store = self.text.store().clone();
let excised = store.condense(&retired);
let context = self.text.context().clone();
self.text = Text::try_new(store, context)
.expect("condense trims only the skeleton, so the context still covers the store");
excised
}
pub fn retire_orphans(&mut self, out: &mut Vec<Note>) -> Option<Dot> {
assert!(
self.transition.is_none(),
"replica {}: orphan retirement is an old-plane operation",
self.id
);
let mut orphaned = DotSet::new();
for (dot, testimony) in self.moves.store() {
let Ok(target) = Dot::try_from(testimony.target) else {
continue;
};
if self.text.store().locus(target).is_none() && self.text.context().contains(target) {
let _ = orphaned.insert(dot);
}
}
let _ = orphaned.dots().next()?;
let marker = self.next_dot();
let mut context = orphaned;
let _ = context.insert(marker);
self.commit_old(
vec![marker],
OldDelta::Moves(Dotted::from_context(context)),
out,
);
Some(marker)
}
fn rank_above(&self, anchor: Anchor) -> Kairos {
let top = {
let store = self.text.store();
store
.children_of(anchor)
.next()
.and_then(|dot| store.locus(dot))
.map(|locus| locus.rank)
};
if let Some(rank) = top {
self.clock.observe(rank);
}
self.clock.now(0u16)
}
fn insert_native(&mut self, at: usize, out: &mut Vec<Note>) -> Dot {
let transition = self.transition.as_mut().expect("routed by phase");
transition.native_counter += 1;
let dot = Dot::from_parts(self.id, transition.native_counter)
.expect("a pre-incremented counter is nonzero");
let (delta, stamp) = weave_delta(transition.native_text.store(), &self.clock, dot, at);
let delta = OldDelta::Text(Box::new(delta));
let dots = vec![dot];
fold_native(transition, &dots, &delta, Some(stamp));
let note = Note::Native {
epoch: transition.adopted.address(),
stamp,
dots,
delta,
};
self.emit_mint(out, note);
self.poll(out);
dot
}
fn delete_native(&mut self, at: usize, out: &mut Vec<Note>) -> Option<Dot> {
let stamp = self.clock.now(0u16);
let transition = self.transition.as_mut().expect("routed by phase");
let order = transition.native_text.store().order();
if order.is_empty() {
return None;
}
let target = order[at % order.len()];
transition.native_counter += 1;
let marker = Dot::from_parts(self.id, transition.native_counter)
.expect("a pre-incremented counter is nonzero");
let delta = OldDelta::Text(Box::new(removal_delta(marker, target)));
let dots = vec![marker];
fold_native(transition, &dots, &delta, Some(stamp));
let note = Note::Native {
epoch: transition.adopted.address(),
stamp,
dots,
delta,
};
self.emit_mint(out, note);
self.poll(out);
Some(target)
}
fn commit_old(&mut self, dots: Vec<Dot>, delta: OldDelta, out: &mut Vec<Note>) {
for &dot in &dots {
let _ = self.have.insert(dot);
let _ = self.recorded.insert(dot);
}
self.fold_current(&delta);
self.log.push((dots.clone(), delta.clone()));
let note = Note::Old {
generation: self.generation,
dots,
delta,
};
self.emit_mint(out, note);
self.poll(out);
}
}
fn weave_delta(
plane: &Rhapsody,
clock: &Clock<TickCounter>,
dot: Dot,
at: usize,
) -> (Text, Kairos) {
let order = plane.order();
let after = if order.is_empty() {
None
} else {
at.checked_sub(1).map(|index| order[index % order.len()])
};
let anchor = plane.anchor_for_visual_insert(after.map(Into::into));
let top = plane
.children_of(anchor)
.next()
.and_then(|child| plane.locus(child))
.map(|locus| locus.rank);
if let Some(rank) = top {
clock.observe(rank);
}
let rank = clock.now(0u16);
let mut delta = Rhapsody::new();
assert!(delta.weave(dot, Locus { anchor, rank }));
(Text::from_store(delta), rank)
}
fn weave_delta_disciplined(
plane: &Rhapsody,
oath: &Rhapsody,
clock: &Clock<TickCounter>,
dot: Dot,
at: usize,
) -> (Text, Kairos) {
let order = plane.order();
let after = if order.is_empty() {
None
} else {
at.checked_sub(1).map(|index| order[index % order.len()])
};
let anchor = oath.anchor_for_visual_insert(after.map(Into::into));
let top = plane
.children_of(anchor)
.next()
.and_then(|child| plane.locus(child))
.map(|locus| locus.rank);
if let Some(rank) = top {
clock.observe(rank);
}
let rank = clock.now(0u16);
let mut delta = Rhapsody::new();
assert!(delta.weave(dot, Locus { anchor, rank }));
(Text::from_store(delta), rank)
}
fn removal_delta(marker: Dot, target: Dot) -> Text {
let mut context = DotSet::new();
let _ = context.insert(marker);
let _ = context.insert(target);
Dotted::from_context(context)
}