diff options
| author | tv <tv@krebsco.de> | 2026-11-01 22:32:24 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-01 22:32:24 +0100 |
| commit | 0a870df1ca78ce732134853a512d958eecf84032 (patch) | |
| tree | ced395c3aae885b0c97a13ab9dceb340bd68db71 /src/document | |
| parent | 422056962f0c53e36d00501d54f710365bc21f65 (diff) | |
document: create new compound values at once
This speeds up large writes as new maps and lists are created in one
batch operation instead of one operation per value.
Diffstat (limited to 'src/document')
| -rw-r--r-- | src/document/store.rs | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/src/document/store.rs b/src/document/store.rs index 4d9bc74..cc67f77 100644 --- a/src/document/store.rs +++ b/src/document/store.rs @@ -1102,17 +1102,15 @@ fn write_value( value: &JsonValue, ) -> Result<(), StoreError> { match value { - JsonValue::Object(object) => { - let id = put_object(doc, parent, slot, ObjType::Map)?; - for (child_key, child_value) in object { - write_value(doc, &id, Slot::Key(child_key), child_value)?; - } - } - JsonValue::Array(items) => { - let id = put_object(doc, parent, slot, ObjType::List)?; - for (index, item) in items.iter().enumerate() { - write_value(doc, &id, Slot::Index(index), item)?; - } + JsonValue::Object(_) | JsonValue::Array(_) => { + // A new tree in one go, not an operation at a time. + let tree = hydrated(value)?; + let (prop, insert): (Prop, bool) = match slot { + Slot::Key(key) => (key.into(), false), + Slot::Index(index) => (index.into(), true), + Slot::At(index) => (index.into(), false), + }; + doc.batch_create_object(parent, prop, &tree, insert)?; } scalar => { let scalar = json_scalar(scalar)?.expect("neither an object nor an array"); @@ -1123,6 +1121,26 @@ fn write_value( Ok(()) } +/// `value` as Automerge holds it: maps, lists and scalars as `write_value` stores them. +fn hydrated(value: &JsonValue) -> Result<automerge::hydrate::Value, StoreError> { + use automerge::hydrate; + Ok(match value { + JsonValue::Object(object) => { + let mut map = std::collections::HashMap::new(); + for (key, value) in object { + map.insert(key.clone(), hydrated(value)?); + } + hydrate::Value::Map(hydrate::Map::from(map)) + } + JsonValue::Array(items) => { + hydrate::Value::from(items.iter().map(hydrated).collect::<Result<Vec<_>, _>>()?) + } + scalar => { + hydrate::Value::from(json_scalar(scalar)?.expect("neither an object nor an array")) + } + }) +} + fn json_to_automerge( doc: &mut impl Transactable, parent: &ObjId, |
