diff options
Diffstat (limited to 'src/document/store.rs')
| -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, |
