aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-01 22:32:24 +0100
committertv <tv@krebsco.de>2026-11-01 22:32:24 +0100
commit7b80ee727153798898f4432a6dbd678ff74df4ca (patch)
tree0c6910870287cb989a19237c0160de4e2b254b7e /src
parentd7433f9d34c299e7ce31542aede80d2530c1e45f (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')
-rw-r--r--src/document/store.rs40
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,