use super::*;
pub trait Index<I> {
type Output;
fn get_index(&self, index: &I) -> Self::Output;
}
impl Index<BigInt> for Value {
type Output = Result<Self>;
fn get_index(&self, index: &BigInt) -> Self::Output {
match self {
Self::Null | Self::Boolean(_) | Self::Integer(_) | Self::Decimal(_) => {
Err(NoteError::type_mismatch(format!("Can not take `Integer` index of type `{}`", self.get_type_name())))
}
Self::String(s) => {
let i = if index.is_negative() {
match index.neg().to_usize() {
Some(u) => {
let max = s.chars().count();
if u <= max { Some(max) } else { None }
}
None => None,
}
}
else {
index.to_usize()
};
match i.and_then(|e| s.chars().nth(e)) {
Some(s) => Ok(Value::string(s)),
None => Err(NoteError::runtime_error(format!("Index `{}` of `String` out of range.", index))),
}
}
Self::Set(v) => {
let out = if index.is_negative() {
index.neg().to_usize().and_then(|i| v.iter().rev().nth(i))
}
else {
index.to_usize().and_then(|i| v.iter().nth(i))
};
match out {
Some(s) => Ok(s.value.to_owned()),
None => Err(NoteError::runtime_error(format!("Index `{}` of `Set` out of range.", index))),
}
}
Self::Array(v) => {
let out = if index.is_negative() {
todo!()
}
else {
index.to_biguint().and_then(|i| v.get(&i))
};
match out {
Some(s) => Ok(s.value.to_owned()),
None => Err(NoteError::runtime_error(format!("Index `{}` of `Array` out of range.", index))),
}
}
Self::Object(v) => {
let out = if index.is_negative() {
index.neg().to_usize().and_then(|i| v.values().rev().nth(i))
}
else {
index.to_usize().and_then(|i| v.values().nth(i))
};
match out {
Some(s) => Ok(s.value.to_owned()),
None => Err(NoteError::runtime_error(format!("Index `{}` of `Object` out of range.", index))),
}
}
}
}
}
impl Index<String> for Value {
type Output = Result<Self>;
fn get_index(&self, index: &String) -> Self::Output {
match self {
Self::Object(v) => {
match v.get(index) {
Some(s) => Ok(s.value.to_owned()),
None => Err(NoteError::runtime_error(format!("Index `{}` of `Object` not found.", index))),
}
}
_ => Err(NoteError::type_mismatch(format!("Can not take `String` index of type `{}`", self.get_type_name()))),
}
}
}