diff options
| author | tv <tv@krebsco.de> | 2026-10-31 03:50:43 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-31 03:50:43 +0100 |
| commit | 4015c292ed83702c518cdb6dc9158bf11abf250a (patch) | |
| tree | 36ea5c530394e16dded83d9cebbbeb0e2f5eb359 /src | |
| parent | 43230f03f7b7bd3ed3b4d45c04529ab3527a5ceb (diff) | |
unify path walkers
Diffstat (limited to 'src')
| -rw-r--r-- | src/document/store.rs | 39 |
1 files changed, 7 insertions, 32 deletions
diff --git a/src/document/store.rs b/src/document/store.rs index a55f95d..9134795 100644 --- a/src/document/store.rs +++ b/src/document/store.rs @@ -355,7 +355,7 @@ pub(crate) fn read_shallow( } /// The resolved value at `path` (the empty path is the root map), through maps and -/// lists (`step`). `resolve_at` goes through maps only. +/// lists (`step`). fn resolve_through(doc: &AutoCommit, path: &[String]) -> Result<Option<Resolved>, StoreError> { let mut current = Resolved::Maps(vec![automerge::ROOT]); for segment in path { @@ -558,35 +558,6 @@ pub(crate) fn insert_path( Ok(()) } -/// The merged maps at `path`, creating missing maps on the way. -fn ensure_maps(doc: &mut AutoCommit, path: &[String]) -> Result<Vec<ObjId>, StoreError> { - let mut maps = vec![automerge::ROOT]; - for segment in path { - maps = match resolve(doc, &maps, segment, None)? { - Some(Resolved::Maps(next)) => next, - Some(Resolved::Other(..)) => return Err(StoreError::Conflict), - // A concurrent creation elsewhere is merged on read. - None => vec![doc.put_object(&maps[0], segment.as_str(), ObjType::Map)?], - }; - } - Ok(maps) -} - -/// The resolved value at `path` (the empty path is the root map). -fn resolve_at(doc: &AutoCommit, path: &[String]) -> Result<Option<Resolved>, StoreError> { - let mut current = Resolved::Maps(vec![automerge::ROOT]); - for segment in path { - let Resolved::Maps(maps) = ¤t else { - return Ok(None); - }; - match resolve(doc, maps, segment, None)? { - Some(next) => current = next, - None => return Ok(None), - } - } - Ok(Some(current)) -} - /// Makes `dst` hold at `path` what `src`'s merged view holds there: a type-preserving /// copy (see `materialize_into`) if it exists, a delete otherwise. Replaces the whole /// subtree at `path`; the path must not be empty. @@ -607,14 +578,18 @@ pub(crate) fn copy_path_to( ) -> Result<(), StoreError> { let (leaf, parents) = to.split_last().ok_or(StoreError::NotFound)?; - let Some(resolved) = resolve_at(src, from)? else { + let Some(resolved) = resolve_through(src, from)? else { return match delete_path(dst, to, false) { Ok(()) | Err(StoreError::NotFound) => Ok(()), Err(error) => Err(error), }; }; - let maps = ensure_maps(dst, parents)?; + // Into a map: what is copied are map entries (delta replay names nothing inside a + // list: a list is copied whole). + let Parent::Maps(maps) = parent_for_write(dst, parents)? else { + return Err(StoreError::Conflict); + }; delete_in_all(dst, &maps, leaf)?; let mut trace = from.to_vec(); copy_resolved( |
