use crate::{Value, mapping, private};
use std::ops;
pub trait Index: private::Sealed {
#[doc(hidden)]
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
}
impl Index for usize {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
match v.untag_ref() {
Value::Sequence(vec) => vec.get(*self),
Value::Mapping(vec) => vec.get(Value::Number((*self).into(), None)),
_ => None,
}
}
}
fn index_into_mapping<'v, I>(index: &I, v: &'v Value) -> Option<&'v Value>
where
I: ?Sized + mapping::Index,
{
match v.untag_ref() {
Value::Mapping(map) => map.get(index),
_ => None,
}
}
impl Index for Value {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
index_into_mapping(self, v)
}
}
impl Index for str {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
index_into_mapping(self, v)
}
}
impl Index for String {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
self.as_str().index_into(v)
}
}
impl<T> Index for &T
where
T: ?Sized + Index,
{
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
(**self).index_into(v)
}
}
impl<I> ops::Index<I> for Value
where
I: Index,
{
type Output = Value;
fn index(&self, index: I) -> &Value {
static NULL: Value = Value::Null(None);
index.index_into(self).unwrap_or(&NULL)
}
}