aboutsummaryrefslogtreecommitdiffstats
path: root/src/document
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
commit0a870df1ca78ce732134853a512d958eecf84032 (patch)
treeced395c3aae885b0c97a13ab9dceb340bd68db71 /src/document
parent422056962f0c53e36d00501d54f710365bc21f65 (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.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,