//! This crate defines the distributed state management system for //! Notive. The state is an operation-based CRDT, which given the same //! set of operations on any client, will realize the same state. use thiserror::Error; use uuid::Uuid; use crate::{ doc::{ApplyOpError, Doc}, op::{Op, OpKind}, vector_clock::VectorClock, }; mod doc; mod op; mod vector_clock; #[derive(Error, Debug)] pub enum Error { #[error("error while realizing state")] RealizeError(#[from] ApplyOpError), } #[derive(Default)] pub struct State { ops: Vec, } impl State { pub fn append_op(&mut self, actor_id: &Uuid, kind: OpKind) { let clock = self .ops .last() .map(|op| op.clock.inc(actor_id)) .unwrap_or_else(|| VectorClock::new().inc(actor_id)); self.ops.push(Op { id: Uuid::now_v7(), clock, kind, }); } pub fn realize(&self) -> Result { let mut doc = Doc::default(); for op in &self.ops { doc.apply_op(op)?; } Ok(doc) } } #[cfg(test)] mod tests { use crate::op::CreateGrid; use super::*; #[test] fn test() { let alice = Uuid::now_v7(); let mut state = State::default(); state.append_op( &alice, OpKind::CreateGrid(CreateGrid { rows: 4, base_cells_per_row: 16, }), ); let doc = state.realize().unwrap(); let grid = doc.grids.first().unwrap(); assert_eq!(grid.rows.len(), 4); } }