use std::collections::BTreeMap;
use std::collections::BTreeSet;
use serde::Deserialize;
use serde::Serialize;
use crate::algebra::JoinSemilattice;
use crate::dht::Did;
use crate::error::Error;
use crate::error::Result;
use crate::message::Encoded;
#[derive(
Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
pub struct EntryVersion {
#[serde(alias = "epoch_ms")]
pub logical_time_ms: u128,
pub actor: Did,
#[serde(default)]
pub operation: Did,
}
impl EntryVersion {
pub fn new(logical_time_ms: u128, actor: Did, operation: Did) -> Self {
Self {
logical_time_ms,
actor,
operation,
}
}
pub fn issued_by(actor: Did, operation: Did) -> Self {
Self::new(crate::utils::get_epoch_ms(), actor, operation)
}
pub(super) fn after(self, floor: Option<Self>) -> Self {
let Some(floor) = floor else {
return self;
};
if self > floor {
return self;
}
Self {
logical_time_ms: floor.logical_time_ms.saturating_add(1),
actor: self.actor,
operation: self.operation,
}
}
}
#[derive(
Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
pub struct EntryDot {
pub version: EntryVersion,
pub index: u32,
}
impl EntryDot {
pub(super) fn for_index(version: EntryVersion, index: usize) -> Result<Self> {
let index = u32::try_from(index).map_err(|_| Error::EntryDotIndexOutOfBounds { index })?;
Ok(Self { version, index })
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct EntryCrdt {
pub register: Option<EntryVersion>,
pub dots: Vec<EntryDot>,
pub tombstones: Vec<EntryDot>,
}
impl EntryCrdt {
pub(super) fn has_write_witness(&self) -> bool {
self.register.is_some() || !self.dots.is_empty()
}
pub(super) fn legacy_floor(&self) -> EntryVersion {
self.register.unwrap_or_default()
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct GSet<T: Ord> {
members: BTreeSet<T>,
}
impl<T: Ord> GSet<T> {
pub fn new() -> Self {
Self {
members: BTreeSet::new(),
}
}
pub fn insert(&mut self, member: T) {
self.members.insert(member);
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.members.iter()
}
}
impl<T: Ord> JoinSemilattice for GSet<T> {
fn join(mut self, other: Self) -> Self {
self.members.extend(other.members);
self
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct DataTopicBuffer {
pub(super) register: Option<EntryVersion>,
pub(super) values: BTreeMap<Encoded, EntryDot>,
}
impl DataTopicBuffer {
pub(super) fn new(
register: Option<EntryVersion>,
mut values: BTreeMap<Encoded, EntryDot>,
) -> Self {
if let Some(floor) = register {
values.retain(|_, dot| dot.version >= floor);
}
Self { register, values }
}
}
impl JoinSemilattice for DataTopicBuffer {
fn join(mut self, other: Self) -> Self {
self.register = self.register.max(other.register);
for (value, dot) in other.values {
self.values
.entry(value)
.and_modify(|current| *current = (*current).max(dot))
.or_insert(dot);
}
Self::new(self.register, self.values)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct RelayMessageSet {
pub(super) adds: DataTopicBuffer,
pub(super) removes: BTreeSet<EntryDot>,
}
impl RelayMessageSet {
pub(super) fn new(mut adds: DataTopicBuffer, removes: BTreeSet<EntryDot>) -> Self {
adds.values.retain(|_, dot| !removes.contains(dot));
Self { adds, removes }
}
}
impl JoinSemilattice for RelayMessageSet {
fn join(mut self, other: Self) -> Self {
self.adds = self.adds.join(other.adds);
self.removes.extend(other.removes);
Self::new(self.adds, self.removes)
}
}
pub type SubringMemberSet = GSet<Did>;