use {
core::iter::FromIterator,
crate::{Array, ArrayIndexes, Error, Json, Result},
};
macro_rules! at_or_mut_at { ($self: ident, $indexes: ident, $code: tt) => {{
let indexes = $indexes.into();
let mut value = Some($self);
for (nth, idx) in indexes.iter().enumerate() {
match value {
Some(Json::Array(array)) => {
value = array.$code(*idx);
if nth + 1 == indexes.len() {
return value.ok_or_else(|| err!("Indexes are invalid: {indexes:?}"));
}
},
Some(_) => return Err(Error::from(match nth {
0 => e!("Json is not an Array"),
_ => err!("Json at {:?} is not an Array", indexes.index_with_range_to(..nth)),
})),
None => return Err(err!("There is no value at {:?}", indexes.index_with_range_to(..nth))),
};
}
Err(e!("Indexes must not be empty"))
}}}
impl Json {
pub fn push<T>(&mut self, value: T) -> Result<()> where T: Into<Self> {
match self {
Json::Array(array) => Ok(crate::push(array, value)),
_ => Err(e!("Json is not an Array")),
}
}
pub fn at<'a, I, const N: usize>(&self, indexes: I) -> Result<&Self> where I: Into<ArrayIndexes<'a, N>> {
at_or_mut_at!(self, indexes, get)
}
pub fn mut_at<'a, I, const N: usize>(&mut self, indexes: I) -> Result<&mut Self> where I: Into<ArrayIndexes<'a, N>> {
at_or_mut_at!(self, indexes, get_mut)
}
pub fn take_at<'a, I, const N: usize>(&mut self, indexes: I) -> Result<Self> where I: Into<ArrayIndexes<'a, N>> {
let mut value = Some(self);
let indexes = indexes.into();
for (nth, idx) in indexes.iter().enumerate() {
match value {
Some(Json::Array(array)) => if nth + 1 == indexes.len() {
return if idx >= &0 && idx < &array.len() {
Ok(array.remove(*idx))
} else {
Err(err!("Invalid indexes: {indexes:?}"))
};
} else {
value = array.get_mut(*idx);
},
Some(_) => return Err(Error::from(match nth {
0 => e!("Json is not an Array"),
_ => err!("Json at {:?} is not an Array", indexes.index_with_range_to(..nth)),
})),
None => return Err(err!("There is no value at {:?}", indexes.index_with_range_to(..nth))),
};
}
Err(e!("Indexes must not be empty"))
}
pub fn as_array(&self) -> Result<&Array> {
match self {
Json::Array(array) => Ok(array),
_ => Err(e!("Json is not an Array")),
}
}
pub fn as_mut_array(&mut self) -> Result<&mut Array> {
match self {
Json::Array(array) => Ok(array),
_ => Err(e!("Json is not an Array")),
}
}
}
impl From<Array> for Json {
fn from(values: Array) -> Self {
Json::Array(values)
}
}
impl<T> FromIterator<T> for Json where T: Into<Self> {
fn from_iter<I>(iter: I) -> Self where I: IntoIterator<Item=T> {
Self::Array(iter.into_iter().map(|i| i.into()).collect())
}
}
impl TryFrom<Json> for Array {
type Error = Error;
fn try_from(value: Json) -> core::result::Result<Self, Self::Error> {
match value {
Json::Array(array) => Ok(array),
_ => Err(e!("Json is not an Array")),
}
}
}
impl<const N: usize> TryFrom<Json> for [Json; N] {
type Error = Error;
fn try_from(value: Json) -> Result<Self> {
match value {
Json::Array(array) => Self::try_from(array).map_err(|array|
err!("Vector of {size} cannot be converted into array of {N}", size=array.len()),
),
_ => Err(e!("Not an Array")),
}
}
}