pub enum EditOp {
ReplaceValue {
path: Vec<Seg>,
value: Value,
},
DeleteKey {
path: Vec<Seg>,
},
RemoveItem {
seq_path: Vec<Seg>,
index: usize,
},
InsertKey {
map_path: Vec<Seg>,
key: String,
value: Value,
},
AppendItem {
seq_path: Vec<Seg>,
value: Value,
},
MoveItem {
seq_path: Vec<Seg>,
from: usize,
to: usize,
},
ReorderKeys {
map_path: Vec<Seg>,
keys: Vec<String>,
},
RenameKey {
path: Vec<Seg>,
new_key: String,
},
}Expand description
One path-addressed edit. The vocabulary grows as Model gains operations
(insert, reorder, comments, …); today it covers what the editor issues.
§Contract
These hold for every variant, and conformance::check tests them:
- Atomic. On
Errthe document is byte-for-byte what it was. - Addressed by the pre-edit tree. Every path and index is resolved against the document as it stands before the op — an empty path is the root.
- Local. Nothing outside the addressed node changes: sibling values, sibling order, comments, and formatting all survive.
- Unresolvable is an error, not a guess. A path that doesn’t resolve, or
that names the wrong kind of node (a key step into a sequence, an index into
a mapping), is an
Err— with the two documented exceptions below.
Two cases are deliberately unspecified, because backends differ on them and
Model never relies on either: what ReplaceValue does
at an absent path, and what InsertKey does at a key that
already exists. A backend over an upserting editor collapses both onto “write
it anyway”; one over a stricter editor errors. A caller that wants a value to
exist regardless must therefore not lean on the coincidence — it should read
the tree first (tree::value_at) and pick the op that fits.
Variants§
ReplaceValue
Replace the scalar/subtree at path with value, in place: the node keeps
its position among its siblings and its key (or index).
path must resolve to an existing node. Unspecified for an absent path
— an upserting backend creates it, a strict one errors. Use
InsertKey or AppendItem to
create.
DeleteKey
Delete the mapping entry at path, closing the gap in its parent’s key
order. path must end in a Seg::Key and must resolve; use
RemoveItem for a sequence item.
RemoveItem
Remove item index from the sequence at seq_path, shifting every later
item down one. index must be < len.
InsertKey
Insert key = value into the mapping at map_path (the root when empty),
appended after its existing entries.
Unspecified when key is already present — an upserting backend
overwrites in place, a strict one errors.
AppendItem
Append value to the sequence at seq_path, at index len.
MoveItem
Move the item at from to to in the sequence at seq_path: a removal
followed by a reinsertion, so to is read against the sequence with the
item already taken out, and the items between the two shift by one. The
length is unchanged and both indices must be < len.
An editor with no native move lowers this through
move_permutation rather than deriving the index arithmetic again.
ReorderKeys
Reorder the mapping at map_path so its entries follow keys. keys is a
permutation of the mapping’s current keys: reordering moves entries, it
never adds, drops, or renames one.
RenameKey
Rename the mapping entry at path to new_key, keeping its value and its
position in the key order. path must end in a Seg::Key; new_key must
not collide with an existing sibling.