use super::forms::{Form, key, same_name};
use super::path::{MAX_SEGMENTS, MAX_SELECTED, escape, position, segments};
use super::value::{Map, Value};
use super::{Error, ErrorKind};
use alloc::format;
use alloc::rc::Rc;
use alloc::string::{String, ToString};
use alloc::vec;
use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct Root<'a> {
pub name: &'a str,
pub stands_for: &'a [&'a str],
pub required: bool,
}
impl<'a> Root<'a> {
pub const NONE: Root<'static> = Root {
name: "",
stands_for: &[],
required: false,
};
pub const fn new(name: &'a str, stands_for: &'a [&'a str], required: bool) -> Self {
Self {
name,
stands_for,
required,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Edit {
Set,
Remove,
Insert,
Open,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Key {
Name(String),
Position(usize),
End,
}
#[derive(Debug)]
struct Link {
key: Key,
before: Option<Rc<Link>>,
}
#[derive(Debug, Clone)]
pub struct Place<'v, S> {
value: Option<&'v Value>,
shape: S,
at: Option<Rc<Link>>,
}
impl<'v, S> Place<'v, S> {
pub fn value(&self) -> Option<&'v Value> {
self.value
}
pub fn shape(&self) -> &S {
&self.shape
}
}
#[derive(Debug)]
pub struct Next<'v, S> {
found: Vec<Place<'v, S>>,
from: Option<Rc<Link>>,
tracking: bool,
edit: Option<Edit>,
last: bool,
opened: Vec<(Option<Rc<Link>>, Value)>,
}
impl<'v, S> Next<'v, S> {
fn link(&self, key: impl FnOnce() -> Key) -> Option<Rc<Link>> {
self.tracking.then(|| {
Rc::new(Link {
key: key(),
before: self.from.clone(),
})
})
}
pub fn member(&mut self, name: &str, value: &'v Value, shape: S) {
let at = self.link(|| Key::Name(name.to_string()));
let value = Some(value);
self.found.push(Place { value, shape, at });
}
pub fn entry(&mut self, position: usize, value: &'v Value, shape: S) {
let at = self.link(|| Key::Position(position));
let value = Some(value);
self.found.push(Place { value, shape, at });
}
pub fn absent(&mut self, name: &str, shape: S) {
let at = self.link(|| Key::Name(name.to_string()));
let value = None;
self.found.push(Place { value, shape, at });
}
pub fn end(&mut self, shape: S) {
let at = self.link(|| Key::End);
self.found.push(Place {
value: None,
shape,
at,
});
}
pub fn absent_once(&mut self, name: &str, shape: S)
where
S: PartialEq,
{
let known = |place: &Place<'v, S>| place.value.is_none() && place.shape == shape;
if !self.found.iter().any(known) {
self.absent(name, shape);
}
}
pub fn stay(&mut self, place: &Place<'v, S>, shape: S) {
let (value, at) = (place.value, place.at.clone());
self.found.push(Place { value, shape, at });
}
pub fn open(&mut self, place: &Place<'v, S>, value: Value) {
self.opened.push((place.at.clone(), value));
}
pub fn through<R>(
&mut self,
place: &Place<'v, S>,
name: &str,
shape: S,
step: impl FnOnce(&Place<'v, S>, &mut Self) -> R,
) -> R {
let members = place.value.and_then(Value::as_object);
let held = members.and_then(|members| {
let name = key(members, name)?;
Some((name, &members[name]))
});
let at = self.link(|| Key::Name(held.map_or(name, |(name, _)| name).to_string()));
let inside = Place {
value: held.map(|(_, value)| value),
shape,
at,
};
let from = core::mem::replace(&mut self.from, inside.at.clone());
let taken = step(&inside, self);
self.from = from;
taken
}
pub fn edit(&self) -> Option<Edit> {
self.edit
}
pub fn is_last(&self) -> bool {
self.last
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum Step<S> {
Taken,
Plain,
Through(String, S),
}
#[derive(Debug)]
#[non_exhaustive]
pub enum Absent<S> {
Unknown,
Optional(S),
Refused(Error),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Listed {
Member,
As(&'static str),
Hidden,
Through,
Root,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Removal {
Take,
Null,
}
pub trait Family {
type Shape: Clone + Default;
fn root(&self) -> Root<'_> {
Root::NONE
}
fn start(&self, tree: &Value, rooted: bool) -> Self::Shape {
let _ = (tree, rooted);
Self::Shape::default()
}
fn step<'v>(
&self,
place: &Place<'v, Self::Shape>,
segment: &str,
next: &mut Next<'v, Self::Shape>,
) -> Result<Step<Self::Shape>, Error> {
let _ = (place, segment, next);
Ok(Step::Plain)
}
fn member(&self, shape: &Self::Shape, name: &str, value: Option<&Value>) -> Self::Shape {
let _ = (shape, name, value);
Self::Shape::default()
}
fn entry(&self, shape: &Self::Shape, value: Option<&Value>) -> Self::Shape {
let _ = (shape, value);
Self::Shape::default()
}
fn absent(&self, shape: &Self::Shape, name: &str) -> Absent<Self::Shape> {
let _ = (shape, name);
Absent::Unknown
}
fn listed(&self, shape: &Self::Shape, name: &str) -> Listed {
let _ = (shape, name);
Listed::Member
}
fn entry_names(&self, shape: &Self::Shape, list: &[Value]) -> Option<Vec<Option<String>>> {
let _ = (shape, list);
None
}
fn removal(&self, shape: &Self::Shape) -> Removal {
let _ = shape;
Removal::Take
}
fn form(&self, shape: &Self::Shape, value: &Value) -> Form {
let _ = (shape, value);
Form::Plain
}
fn null_is_value(&self, shape: &Self::Shape) -> bool {
let _ = shape;
false
}
fn edited(&self, tree: &mut Value, at: &[Key], shape: &Self::Shape, edit: Edit) {
let _ = (tree, at, shape, edit);
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Plain;
impl Family for Plain {
type Shape = ();
}
fn resolve(root: Root<'_>, path: &str) -> Result<(Vec<String>, bool), Error> {
let mut parts = segments(path)?;
if root.name.is_empty() {
return Ok((parts, false));
}
let rooted = parts
.first()
.is_some_and(|first| same_name(first, root.name));
if rooted {
let stands_for = root.stands_for.iter().map(|part| part.to_string());
parts.splice(..1, stands_for);
} else if root.required {
let reason = format!(
"{path} is not a path of this tree: it starts with /{}",
root.name
);
return Err(Error::new(ErrorKind::Path, path, reason));
}
Ok((parts, rooted))
}
fn no_member(members: &Map, part: &str, path: &str) -> Error {
const SHOWN: usize = 12;
let mut names: Vec<&str> = members.keys().take(SHOWN).map(String::as_str).collect();
if members.len() > SHOWN {
names.push("…");
}
let reason = match names.is_empty() {
true => format!("{part:?} is not a member of this value, which has none"),
false => format!(
"{part:?} is not a member of this value, which has {}",
names.join(", ")
),
};
Error::new(ErrorKind::NoSuchMember, path, reason)
}
fn plain<'v, F: Family>(
family: &F,
place: &Place<'v, F::Shape>,
part: &str,
path: &str,
next: &mut Next<'v, F::Shape>,
) -> Result<(), Error> {
let shape = &place.shape;
match place.value {
None => Ok(()),
Some(Value::Null) if !family.null_is_value(shape) => Ok(()),
Some(Value::Object(members)) => {
if part == "*" {
for (name, value) in members {
if family.listed(shape, name) != Listed::Hidden {
next.member(name, value, family.member(shape, name, Some(value)));
}
}
return Ok(());
}
if let Some(name) = key(members, part) {
let value = &members[name];
next.member(name, value, family.member(shape, name, Some(value)));
return Ok(());
}
match family.absent(shape, part) {
Absent::Optional(shape) => next.absent(part, shape),
Absent::Refused(error) => return Err(error),
Absent::Unknown if next.last && next.edit == Some(Edit::Set) => {
next.absent(part, family.member(shape, part, None));
}
Absent::Unknown => return Err(no_member(members, part, path)),
}
Ok(())
}
Some(Value::Array(entries)) => {
if part == "*" {
for (position, entry) in entries.iter().enumerate() {
next.entry(position, entry, family.entry(shape, Some(entry)));
}
} else if part == "-" && next.last && next.edit == Some(Edit::Insert) {
next.end(family.entry(shape, None));
} else if let Some(position) = position(part) {
if let Some(entry) = entries.get(position) {
next.entry(position, entry, family.entry(shape, Some(entry)));
}
} else {
let reason = format!(
"{part:?} is no position in a list: a position is a number as decimal \
writes it, or \"*\" for each entry"
);
return Err(Error::new(ErrorKind::NotAList, path, reason));
}
Ok(())
}
Some(_) => {
let reason = format!("{part:?} is not a member of this value, which has none");
Err(Error::new(ErrorKind::Scalar, path, reason))
}
}
}
fn advance<'v, F: Family>(
family: &F,
place: &Place<'v, F::Shape>,
part: &str,
path: &str,
next: &mut Next<'v, F::Shape>,
through: usize,
) -> Result<(), Error> {
next.from = place.at.clone();
match family.step(place, part, next)? {
Step::Taken if !next.opened.is_empty() && next.edit != Some(Edit::Open) => {
let reason = "the family opens a value where the edit is not to open one";
Err(Error::new(ErrorKind::Refused, path, reason))
}
Step::Taken => Ok(()),
Step::Plain => plain(family, place, part, path, next),
Step::Through(name, shape) => {
if through == MAX_SEGMENTS {
let reason = "the segment is taken through more members than a path has segments";
return Err(Error::new(ErrorKind::Refused, path, reason));
}
let members = place.value.and_then(Value::as_object);
let held = members.and_then(|members| {
let name = key(members, &name)?;
Some((name, &members[name]))
});
let at =
next.link(|| Key::Name(held.map_or(name.clone(), |(name, _)| name.to_string())));
let inside = Place {
value: held.map(|(_, value)| value),
shape,
at,
};
advance(family, &inside, part, path, next, through + 1)
}
}
}
fn walk<'v, F: Family>(
family: &F,
tree: &'v Value,
path: &str,
edit: Option<Edit>,
) -> Result<Vec<Place<'v, F::Shape>>, Error> {
match walk_to_open(family, tree, path, edit)? {
Walked::Places(places) => Ok(places),
Walked::Open(..) => Err(Error::new(
ErrorKind::Refused,
path,
"the family opens a value where the edit is not to open one",
)),
}
}
enum Walked<'v, S> {
Places(Vec<Place<'v, S>>),
Open(Vec<(Vec<Key>, Value)>),
}
fn walk_to_open<'v, F: Family>(
family: &F,
tree: &'v Value,
path: &str,
edit: Option<Edit>,
) -> Result<Walked<'v, F::Shape>, Error> {
let (parts, rooted) = resolve(family.root(), path)?;
let mut places = vec![Place {
value: Some(tree),
shape: family.start(tree, rooted),
at: None,
}];
for (index, part) in parts.iter().enumerate() {
let mut next = Next {
found: Vec::new(),
from: None,
tracking: edit.is_some(),
edit,
last: index + 1 == parts.len(),
opened: Vec::new(),
};
let mut refusal = None;
for place in &places {
match advance(family, place, part, path, &mut next, 0) {
Ok(()) => {}
Err(error) if error.kind() == ErrorKind::Refused => {
return Err(error.located(path));
}
Err(error) => refusal = refusal.or(Some(error.located(path))),
}
if next.found.len() + next.opened.len() > MAX_SELECTED {
let reason = format!("a path selects {MAX_SELECTED} values at most");
return Err(Error::new(ErrorKind::Limit, path, reason));
}
}
if !next.opened.is_empty() {
let opened = next.opened.into_iter();
return Ok(Walked::Open(
opened.map(|(at, value)| (keys(&at), value)).collect(),
));
}
if let (true, Some(refusal)) = (next.found.is_empty(), refusal) {
return Err(refusal);
}
places = next.found;
}
Ok(Walked::Places(places))
}
pub fn select_in<'v, F: Family>(
family: &F,
tree: &'v Value,
path: &str,
) -> Result<Vec<&'v Value>, Error> {
let places = walk(family, tree, path, None)?;
let values = places.into_iter().filter_map(|place| there(family, &place));
Ok(values.collect())
}
pub fn select_forms_in<'v, F: Family>(
family: &F,
tree: &'v Value,
path: &str,
) -> Result<Vec<(&'v Value, Form)>, Error> {
let places = walk(family, tree, path, None)?;
let selected = places.into_iter().filter_map(|place| {
let value = there(family, &place)?;
Some((value, family.form(&place.shape, value)))
});
Ok(selected.collect())
}
fn there<'v, F: Family>(family: &F, place: &Place<'v, F::Shape>) -> Option<&'v Value> {
let value = place.value?;
(!value.is_null() || family.null_is_value(&place.shape)).then_some(value)
}
pub fn places_in<'v, F: Family>(
family: &F,
tree: &'v Value,
path: &str,
) -> Result<Vec<Place<'v, F::Shape>>, Error> {
walk(family, tree, path, None)
}
pub fn select<'v>(tree: &'v Value, path: &str) -> Result<Vec<&'v Value>, Error> {
select_in(&Plain, tree, path)
}
pub fn paths_in<F: Family>(family: &F, tree: &Value) -> Vec<(String, Value)> {
let root = family.root();
let (mut path, depth) = match root.name.is_empty() || !root.stands_for.is_empty() {
true => (String::new(), 0),
false => (format!("/{}", root.name), 1),
};
let mut found = Vec::new();
let shape = family.start(tree, true);
if !tree.is_null() {
list(family, tree, &shape, &mut path, depth, &mut found);
}
found
}
pub fn paths(tree: &Value) -> Vec<(String, Value)> {
paths_in(&Plain, tree)
}
fn is_empty(value: &Value) -> bool {
match value {
Value::Object(members) => members.is_empty(),
Value::Array(entries) => entries.is_empty(),
_ => false,
}
}
fn inside<F: Family>(
family: &F,
segment: &str,
child: &Value,
shape: &F::Shape,
path: &mut String,
depth: usize,
found: &mut Vec<(String, Value)>,
) {
let length = path.len();
path.push('/');
path.push_str(&escape(segment));
list(family, child, shape, path, depth + 1, found);
path.truncate(length);
}
fn list<F: Family>(
family: &F,
value: &Value,
shape: &F::Shape,
path: &mut String,
depth: usize,
found: &mut Vec<(String, Value)>,
) {
match value {
_ if depth >= MAX_SEGMENTS => found.push((path.clone(), value.clone())),
Value::Object(members) if !members.is_empty() => {
for (name, member) in members.iter() {
let of_member = family.member(shape, name, Some(member));
if member.is_null() && !family.null_is_value(&of_member) {
continue;
}
match family.listed(shape, name) {
Listed::Member => inside(family, name, member, &of_member, path, depth, found),
Listed::As(other) => {
inside(family, other, member, &of_member, path, depth, found);
}
Listed::Hidden => {}
Listed::Through if is_empty(member) => {}
Listed::Through => list(family, member, &of_member, path, depth, found),
Listed::Root => {
let mut rooted = format!("/{}", family.root().name);
let before = found.len();
list(family, member, &of_member, &mut rooted, 1, found);
if found.len() == before {
found.push((rooted, member.clone()));
}
}
}
}
}
Value::Array(entries) if entries.iter().any(|e| e.is_object() || e.is_array()) => {
let names = family.entry_names(shape, entries);
for (index, entry) in entries.iter().enumerate() {
let of_entry = family.entry(shape, Some(entry));
if entry.is_null() && !family.null_is_value(&of_entry) {
continue;
}
let named = names
.as_ref()
.and_then(|names| names.get(index)?.as_deref());
match named {
Some(name) => inside(family, name, entry, &of_entry, path, depth, found),
None => {
let position = index.to_string();
inside(family, &position, entry, &of_entry, path, depth, found);
}
}
}
}
plain => found.push((path.clone(), plain.clone())),
}
}
pub fn set_in<F: Family>(
family: &F,
tree: &mut Value,
path: &str,
value: impl Into<Value>,
) -> Result<(), Error> {
match value.into() {
Value::Null if !null_is_value_at(family, tree, path) => {
edit(family, tree, path, Edit::Remove, None)
}
value => edit(family, tree, path, Edit::Set, Some(value)),
}
}
fn null_is_value_at<F: Family>(family: &F, tree: &Value, path: &str) -> bool {
match walk(family, tree, path, Some(Edit::Set)) {
Ok(places) => {
!places.is_empty()
&& places
.iter()
.all(|place| family.null_is_value(&place.shape))
}
Err(_) => false,
}
}
pub fn remove_in<F: Family>(family: &F, tree: &mut Value, path: &str) -> Result<(), Error> {
edit(family, tree, path, Edit::Remove, None)
}
pub fn insert_in<F: Family>(
family: &F,
tree: &mut Value,
path: &str,
value: impl Into<Value>,
) -> Result<(), Error> {
edit(family, tree, path, Edit::Insert, Some(value.into()))
}
pub fn set(tree: &mut Value, path: &str, value: impl Into<Value>) -> Result<(), Error> {
set_in(&Plain, tree, path, value)
}
pub fn remove(tree: &mut Value, path: &str) -> Result<(), Error> {
remove_in(&Plain, tree, path)
}
pub fn insert(tree: &mut Value, path: &str, value: impl Into<Value>) -> Result<(), Error> {
insert_in(&Plain, tree, path, value)
}
fn keys(at: &Option<Rc<Link>>) -> Vec<Key> {
let mut keys = Vec::new();
let mut link = at.as_deref();
while let Some(Link { key, before }) = link {
keys.push(key.clone());
link = before.as_deref();
}
keys.reverse();
keys
}
fn edit<F: Family>(
family: &F,
tree: &mut Value,
path: &str,
operation: Edit,
value: Option<Value>,
) -> Result<(), Error> {
let nothing = || Error::new(ErrorKind::NothingSelected, path, "the path selects nothing");
let places: Vec<(Vec<Key>, Removal, F::Shape)> = {
let places = walk(family, tree, path, Some(operation))?;
let edited = places.iter().filter(|place| match operation {
Edit::Set | Edit::Open => true,
Edit::Remove | Edit::Insert => {
there(family, place).is_some()
|| matches!(place.at.as_deref(), Some(Link { key: Key::End, .. }))
}
});
let places = edited.map(|place| {
let removal = family.removal(&place.shape);
(keys(&place.at), removal, place.shape.clone())
});
places.collect()
};
if places.is_empty() {
return Err(nothing());
}
if places.iter().any(|(keys, ..)| keys.is_empty()) {
let reason = "an edit takes a path into the tree, and this is the path of the tree itself";
return Err(Error::new(ErrorKind::Path, path, reason));
}
let mut undo = Vec::new();
for (keys, removal, _) in places.iter().rev() {
let done = apply(
tree,
keys,
operation,
value.as_ref(),
*removal,
path,
&mut undo,
);
if let Err(error) = done {
take_back(tree, undo);
return Err(error);
}
}
for (keys, _, shape) in &places {
family.edited(tree, keys, shape, operation);
}
Ok(())
}
pub fn open_in<F: Family>(family: &F, tree: &mut Value, path: &str) -> Result<(), Error> {
let mut undo = Vec::new();
for _ in 0..=MAX_SEGMENTS {
let walked = walk_to_open(family, tree, path, Some(Edit::Open));
let opened = match walked {
Ok(Walked::Places(_)) => return Ok(()),
Ok(Walked::Open(opened)) => opened,
Err(error) => {
take_back(tree, undo);
return Err(error);
}
};
for (at, value) in opened.into_iter().rev() {
let Some(place) = at_mut(tree, &at) else {
take_back(tree, undo);
let reason = "the family opens a value at a place that the tree does not have";
return Err(Error::new(ErrorKind::Refused, path, reason));
};
undo.push(Undo::Was(at, core::mem::replace(place, value)));
}
}
take_back(tree, undo);
let reason = format!("a path opens values at {MAX_SEGMENTS} segments at most");
Err(Error::new(ErrorKind::Limit, path, reason))
}
#[derive(Debug)]
enum Undo {
Was(Vec<Key>, Value),
Added(Vec<Key>),
Taken(Vec<Key>, usize, String, Value),
Removed(Vec<Key>, usize, Value),
Inserted(Vec<Key>, usize),
}
fn at_mut<'t>(tree: &'t mut Value, keys: &[Key]) -> Option<&'t mut Value> {
let mut holder = tree;
for key in keys {
holder = match (key, holder) {
(Key::Name(name), Value::Object(members)) => members.get_mut(name.as_str())?,
(Key::Position(position), Value::Array(entries)) => entries.get_mut(*position)?,
_ => return None,
};
}
Some(holder)
}
fn take_back(tree: &mut Value, undo: Vec<Undo>) {
for done in undo.into_iter().rev() {
match done {
Undo::Was(keys, was) => {
if let Some(value) = at_mut(tree, &keys) {
*value = was;
}
}
Undo::Added(keys) => {
if let Some((Key::Name(name), holder)) = keys.split_last()
&& let Some(Value::Object(members)) = at_mut(tree, holder)
{
members.shift_remove(name.as_str());
}
}
Undo::Taken(keys, position, name, was) => {
if let Some(Value::Object(members)) = at_mut(tree, &keys) {
members.shift_insert(position, name, was);
}
}
Undo::Removed(keys, position, was) => {
if let Some(Value::Array(entries)) = at_mut(tree, &keys) {
entries.insert(position, was);
}
}
Undo::Inserted(keys, position) => {
if let Some(Value::Array(entries)) = at_mut(tree, &keys) {
entries.remove(position);
}
}
}
}
}
fn apply(
tree: &mut Value,
keys: &[Key],
operation: Edit,
value: Option<&Value>,
removal: Removal,
path: &str,
undo: &mut Vec<Undo>,
) -> Result<(), Error> {
let gone = || Error::new(ErrorKind::NothingSelected, path, "the path selects nothing");
let Some((last, before)) = keys.split_last() else {
return Err(gone());
};
let mut holder = tree;
for (depth, key) in before.iter().enumerate() {
if holder.is_null() && matches!(key, Key::Name(_)) {
undo.push(Undo::Was(before[..depth].to_vec(), Value::Null));
*holder = Value::Object(Map::new());
}
holder = match (key, holder) {
(Key::Name(name), Value::Object(members)) => {
if !members.contains_key(name.as_str()) {
undo.push(Undo::Added(before[..=depth].to_vec()));
}
members.entry(name.as_str()).or_insert(Value::Null)
}
(Key::Position(position), Value::Array(entries)) => {
entries.get_mut(*position).ok_or_else(gone)?
}
_ => return Err(gone()),
};
}
if holder.is_null() && matches!(last, Key::Name(_)) && operation == Edit::Set {
undo.push(Undo::Was(before.to_vec(), Value::Null));
*holder = Value::Object(Map::new());
}
let not_a_list = || {
let reason = "insert adds to a list, and the path ends at a member";
Error::new(ErrorKind::NotAList, path, reason)
};
let written = || value.cloned().unwrap_or_default();
match (last, holder, operation) {
(Key::Name(name), Value::Object(members), Edit::Set) => {
match members.insert(name.clone(), written()) {
Some(was) => undo.push(Undo::Was(keys.to_vec(), was)),
None => undo.push(Undo::Added(keys.to_vec())),
}
}
(Key::Name(name), Value::Object(members), Edit::Remove) => match removal {
Removal::Take => {
let position = members.keys().position(|known| known == name);
let position = position.ok_or_else(gone)?;
let was = members.shift_remove(name.as_str()).ok_or_else(gone)?;
undo.push(Undo::Taken(before.to_vec(), position, name.clone(), was));
}
Removal::Null => {
let member = members.get_mut(name.as_str()).ok_or_else(gone)?;
undo.push(Undo::Was(keys.to_vec(), core::mem::take(member)));
}
},
(Key::Name(_), _, Edit::Insert) => return Err(not_a_list()),
(Key::Position(position), Value::Array(entries), _) if *position < entries.len() => {
match operation {
Edit::Set => {
let was = core::mem::replace(&mut entries[*position], written());
undo.push(Undo::Was(keys.to_vec(), was));
}
Edit::Remove => {
let was = entries.remove(*position);
undo.push(Undo::Removed(before.to_vec(), *position, was));
}
Edit::Insert => {
entries.insert(*position, written());
undo.push(Undo::Inserted(before.to_vec(), *position));
}
Edit::Open => return Err(gone()),
}
}
(Key::End, Value::Array(entries), Edit::Insert) => {
undo.push(Undo::Inserted(before.to_vec(), entries.len()));
entries.push(written());
}
_ => return Err(gone()),
}
Ok(())
}