use std::ptr::NonNull;
use serde_json::Value;
use serde_json::map::IterMut;
use super::MutFrame;
use super::OwnedLocation;
pub(in crate::value::traverse) enum MutChildCursor {
Array {
values: NonNull<Vec<Value>>,
next: usize,
},
Object {
iter: IterMut<'static>,
},
Empty,
}
impl MutChildCursor {
pub(in crate::value::traverse) fn new(mut value: NonNull<Value>) -> Self {
match unsafe { value.as_mut() } {
Value::Array(values) => Self::Array {
values: NonNull::from(values),
next: 0,
},
Value::Object(entries) => {
let iter = entries.iter_mut();
let iter = unsafe { std::mem::transmute::<IterMut<'_>, IterMut<'static>>(iter) };
Self::Object { iter }
}
Value::Null | Value::Bool(_) | Value::Number(_) | Value::String(_) => Self::Empty,
}
}
pub(in crate::value::traverse) fn next(&mut self, parent_depth: usize) -> Option<MutFrame> {
let depth = parent_depth
.checked_add(1)
.expect("a materialized JSON tree cannot have usize::MAX nesting depth");
match self {
Self::Array { values, next } => {
let values = unsafe { values.as_mut() };
let index = *next;
let child = values.get_mut(index)?;
*next = next.checked_add(1)?;
Some(MutFrame::child(OwnedLocation::ArrayElement(index), depth, child))
}
Self::Object { iter } => iter
.next()
.map(|(key, child)| MutFrame::child(OwnedLocation::ObjectValue(key.clone()), depth, child)),
Self::Empty => None,
}
}
}