diff options
Diffstat (limited to 'packages/doc/src/lib.rs')
| -rw-r--r-- | packages/doc/src/lib.rs | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/packages/doc/src/lib.rs b/packages/doc/src/lib.rs new file mode 100644 index 0000000..a1d7497 --- /dev/null +++ b/packages/doc/src/lib.rs @@ -0,0 +1,97 @@ +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<Op>, +} + +#[wasm_bindgen] +impl State { + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + let actor_id = Uuid::now_v7(); + + Self { + actor_id, + ops: vec![], + } + } + + pub fn create_grid(&mut self) { + self.append_op(OpKind::CreateGrid(CreateGrid { + rows: 4, + base_cells_per_row: 16, + })); + } + + pub fn to_json(&self) -> JsValue { + let doc = self.realize().unwrap(); + serde_wasm_bindgen::to_value(&doc).unwrap() + } +} + +impl State { + 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<Doc, Error> { + 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 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); + } +} |
