use thiserror::Error; use uuid::Uuid; use wasm_bindgen::prelude::*; use crate::{ doc::{ApplyOpError, Doc}, op::{CreateGrid, 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), } #[wasm_bindgen] pub struct State { actor_id: Uuid, ops: Vec, } impl State { pub fn new() -> Self { let actor_id = Uuid::now_v7(); Self { actor_id, ops: vec![], } } pub fn append_op(&mut self, kind: OpKind) { let clock = self .ops .last() .map(|op| op.clock.inc(&self.actor_id)) .unwrap_or_else(|| VectorClock::new().inc(&self.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) } } #[wasm_bindgen] pub fn make_state() -> State { State::new() } #[wasm_bindgen] pub fn create_grid(state: &mut State) { state.append_op(OpKind::CreateGrid(CreateGrid { rows: 4, base_cells_per_row: 16 })); } pub fn realize(state: &State) -> JsValue { let doc = state.realize().unwrap(); serde_wasm_bindgen::to_value(&doc).unwrap() } #[cfg(test)] mod tests { use crate::op::CreateGrid; use super::*; #[test] fn test() { let mut state = State::new(); state.append_op(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); } }