use crate::{Error, Json, ObjectIndexes, Result};
macro_rules! maybe_by_or_mut_by { ($value: ident, $keys: ident, $code: tt) => {{
let keys = $keys.into();
if keys.len() == 0 {
return Err(err!("Keys must not be empty"));
}
let mut value = Some($value);
for (nth, key) in keys.iter().enumerate() {
match value {
Some(Json::Object(object)) => value = object.$code(key),
Some(_) => return Err(Error::from(match nth {
0 => e!("Json is not an Object"),
_ => err!("Json at {:?} is not an Object", keys.index_with_range_to(..nth)),
})),
None => return Err(err!("There is no value at {:?}", keys.index_with_range_to(..nth))),
};
}
Ok((value, keys))
}}}
pub (super) fn maybe_by<'a, K, const N: usize>(value: &Json, keys: K) -> Result<(Option<&Json>, ObjectIndexes<'a, N>)>
where K: Into<ObjectIndexes<'a, N>> {
maybe_by_or_mut_by!(value, keys, get)
}
pub (super) fn maybe_mut_by<'a, K, const N: usize>(value: &mut Json, keys: K) -> Result<(Option<&mut Json>, ObjectIndexes<'a, N>)>
where K: Into<ObjectIndexes<'a, N>> {
maybe_by_or_mut_by!(value, keys, get_mut)
}
pub (super) fn maybe_take_by<'a, K, const N: usize>(value: &mut Json, keys: K) -> Result<(Option<Json>, ObjectIndexes<'a, N>)>
where K: Into<ObjectIndexes<'a, N>> {
let keys = keys.into();
if keys.len() == 0 {
return Err(e!("Keys must not be empty"));
}
let mut result = None;
let mut value = Some(value);
for (nth, key) in keys.iter().enumerate() {
match value {
Some(Json::Object(object)) => if nth + 1 == keys.len() {
result = object.remove(key);
break;
} else {
value = object.get_mut(key);
},
Some(_) => return Err(match nth {
0 => e!("Json is not an Object"),
_ => err!("Json at {:?} is not an Object", keys.index_with_range_to(..nth)),
}),
None => return Err(err!("There is no value at {:?}", keys.index_with_range_to(..nth))),
};
}
Ok((result, keys))
}