summaryrefslogtreecommitdiff
path: root/packages/doc/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/doc/src')
-rw-r--r--packages/doc/src/doc.rs67
-rw-r--r--packages/doc/src/lib.rs5
-rw-r--r--packages/doc/src/vector_clock.rs47
3 files changed, 52 insertions, 67 deletions
diff --git a/packages/doc/src/doc.rs b/packages/doc/src/doc.rs
index fcca1d8..22ef703 100644
--- a/packages/doc/src/doc.rs
+++ b/packages/doc/src/doc.rs
@@ -1,14 +1,17 @@
use serde::{Deserialize, Serialize};
use thiserror::Error;
+use tsify::Tsify;
use uuid::Uuid;
use crate::op::{ChangeSubdivisions, CreateGrid, Op, OpKind};
/// An deterministically derived ID, e.g. a grid ID derived from the
/// op ID which creates it.
+#[derive(Tsify)]
+#[tsify(type = "string")]
pub struct DerivedId {
base: String,
- tag: &'static str,
+ tag: String,
index: usize,
}
@@ -19,24 +22,24 @@ impl ToString for DerivedId {
}
trait DerivableId {
- fn derive_id(&self, tag: &'static str, index: usize) -> DerivedId;
+ fn derive_id(&self, tag: &str, index: usize) -> DerivedId;
}
impl DerivableId for Uuid {
- fn derive_id(&self, tag: &'static str, index: usize) -> DerivedId {
+ fn derive_id(&self, tag: &str, index: usize) -> DerivedId {
DerivedId {
base: self.to_string(),
- tag,
+ tag: tag.to_string(),
index,
}
}
}
impl DerivableId for DerivedId {
- fn derive_id(&self, tag: &'static str, index: usize) -> DerivedId {
+ fn derive_id(&self, tag: &str, index: usize) -> DerivedId {
DerivedId {
base: self.to_string(),
- tag,
+ tag: tag.to_string(),
index,
}
}
@@ -51,26 +54,56 @@ impl Serialize for DerivedId {
}
}
-#[derive(Default, Serialize)]
+impl<'de> Deserialize<'de> for DerivedId {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ let s = String::deserialize(deserializer)?;
+ let parts: Vec<&str> = s.split(':').collect();
+ if parts.len() != 2 {
+ return Err(serde::de::Error::custom("Invalid DerivedId format"));
+ }
+
+ let base = parts[0].to_string();
+ let tag_index: Vec<&str> = parts[1].split('=').collect();
+ if tag_index.len() != 2 {
+ return Err(serde::de::Error::custom("Invalid DerivedId format"));
+ }
+
+ let tag = tag_index[0].to_string();
+ let index = tag_index[1]
+ .parse()
+ .map_err(|_| serde::de::Error::custom("Invalid index"))?;
+
+ Ok(DerivedId { base, tag, index })
+ }
+}
+
+#[derive(Default, Serialize, Deserialize, Tsify)]
+#[tsify(into_wasm_abi)]
pub struct Doc {
- pub(crate) grids: Vec<Grid>,
+ pub grids: Vec<Grid>,
}
-#[derive(Serialize)]
+#[derive(Serialize, Deserialize, Tsify)]
+#[tsify(into_wasm_abi)]
pub struct Grid {
- pub(crate) id: DerivedId,
- pub(crate) rows: Vec<Row>,
+ pub id: DerivedId,
+ pub rows: Vec<Row>,
}
-#[derive(Serialize)]
+#[derive(Serialize, Deserialize, Tsify)]
+#[tsify(into_wasm_abi)]
pub struct Row {
- pub(crate) id: DerivedId,
- pub(crate) cells: Vec<Cell>,
+ pub id: DerivedId,
+ pub cells: Vec<Cell>,
}
-#[derive(Serialize)]
+#[derive(Serialize, Deserialize, Tsify)]
+#[tsify(into_wasm_abi)]
pub struct Cell {
- pub(crate) id: DerivedId,
+ pub id: DerivedId,
}
#[derive(Error, Debug)]
@@ -109,6 +142,6 @@ fn apply_create_grid(doc: &mut Doc, op_id: &Uuid, data: &CreateGrid) -> ApplyOpR
Ok(())
}
-fn apply_change_subdivisions(doc: &mut Doc, data: &ChangeSubdivisions) -> ApplyOpResult {
+fn apply_change_subdivisions(_doc: &mut Doc, _data: &ChangeSubdivisions) -> ApplyOpResult {
todo!()
}
diff --git a/packages/doc/src/lib.rs b/packages/doc/src/lib.rs
index a1d7497..93c008a 100644
--- a/packages/doc/src/lib.rs
+++ b/packages/doc/src/lib.rs
@@ -43,9 +43,8 @@ impl State {
}));
}
- pub fn to_json(&self) -> JsValue {
- let doc = self.realize().unwrap();
- serde_wasm_bindgen::to_value(&doc).unwrap()
+ pub fn to_json(&self) -> Doc {
+ self.realize().unwrap()
}
}
diff --git a/packages/doc/src/vector_clock.rs b/packages/doc/src/vector_clock.rs
index f6ded56..5e0b669 100644
--- a/packages/doc/src/vector_clock.rs
+++ b/packages/doc/src/vector_clock.rs
@@ -22,11 +22,6 @@ impl VectorClock {
m.insert(actor_id.clone(), self.get(actor_id) + 1);
VectorClock(m)
}
-
- /// Returns true if this clock is concurrent with another (neither happens before the other)
- pub fn is_concurrent_with(&self, other: &VectorClock) -> bool {
- self.partial_cmp(other).is_none()
- }
}
impl PartialOrd for VectorClock {
@@ -111,46 +106,4 @@ mod tests {
assert!(!(clock_a > clock_b));
assert!(!(clock_a < clock_b));
}
-
- #[test]
- fn concurrent_clocks() {
- let alice_id = Uuid::now_v7();
- let bob_id = Uuid::now_v7();
- let carol_id = Uuid::now_v7();
-
- // Equal clocks are not concurrent
- let clock1 = VectorClock::new();
- let clock2 = VectorClock::new();
- assert!(!clock1.is_concurrent_with(&clock2));
-
- // Causally ordered clocks are not concurrent
- let clock_before = VectorClock::new().inc(&alice_id);
- let clock_after = VectorClock::new().inc(&alice_id).inc(&bob_id);
- assert!(!clock_before.is_concurrent_with(&clock_after));
- assert!(!clock_after.is_concurrent_with(&clock_before));
-
- // Clocks from different actors are concurrent
- let alice_clock = VectorClock::new().inc(&alice_id);
- let bob_clock = VectorClock::new().inc(&bob_id);
- assert!(alice_clock.is_concurrent_with(&bob_clock));
- assert!(bob_clock.is_concurrent_with(&alice_clock));
-
- // Complex concurrent case: diverged branches
- let clock_a = VectorClock::new()
- .inc(&alice_id)
- .inc(&alice_id)
- .inc(&bob_id)
- .inc(&carol_id);
-
- let clock_b = VectorClock::new()
- .inc(&alice_id)
- .inc(&alice_id)
- .inc(&bob_id)
- .inc(&bob_id);
-
- // clock_a: {alice: 2, bob: 1, carol: 1}
- // clock_b: {alice: 2, bob: 2}
- // carol: 1 > 0, but bob: 1 < 2 → concurrent
- assert!(clock_a.is_concurrent_with(&clock_b));
- }
}