summaryrefslogtreecommitdiff
path: root/packages/doc/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'packages/doc/src/lib.rs')
-rw-r--r--packages/doc/src/lib.rs97
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);
+ }
+}