teo_runtime/value/
index.rsuse std::ops;
use indexmap::IndexMap;
use super::value::Value;
pub trait Index {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
}
impl Index for usize {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
match v {
Value::Array(vec) => vec.get(*self),
Value::Tuple(vec) => vec.get(*self),
_ => None,
}
}
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
match v {
Value::Array(vec) => vec.get_mut(*self),
Value::Tuple(vec) => vec.get_mut(*self),
_ => None,
}
}
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
match v {
Value::Array(vec) => {
let len = vec.len();
vec.get_mut(*self).unwrap_or_else(|| {
panic!(
"cannot access index {} of Teon array of length {}",
self, len
)
})
},
Value::Tuple(vec) => {
let len = vec.len();
vec.get_mut(*self).unwrap_or_else(|| {
panic!(
"cannot access index {} of Teon tuple of length {}",
self, len
)
})
},
_ => panic!("cannot access index {} of Teon {}", self, v.type_hint()),
}
}
}
impl Index for str {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
match v {
Value::Dictionary(map) => map.get(self),
_ => None,
}
}
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
match v {
Value::Dictionary(map) => map.get_mut(self),
_ => None,
}
}
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
if let Value::Null = v {
*v = Value::Dictionary(IndexMap::new());
}
match v {
Value::Dictionary(map) => map.entry(self.to_owned()).or_insert(Value::Null),
_ => panic!("cannot access key {:?} in Teon {}", self, v.type_hint()),
}
}
}
impl Index for String {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
self[..].index_into(v)
}
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
self[..].index_into_mut(v)
}
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
self[..].index_or_insert(v)
}
}
impl<'a, T> Index for &'a T where T: ?Sized + Index, {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
(**self).index_into(v)
}
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
(**self).index_into_mut(v)
}
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
(**self).index_or_insert(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;
index.index_into(self).unwrap_or(&NULL)
}
}
impl<I> ops::IndexMut<I> for Value where I: Index {
fn index_mut(&mut self, index: I) -> &mut Value {
index.index_or_insert(self)
}
}