use crate::{
error::{Error, IndexError, KeyError},
kind::QueryKind,
};
pub type State<'a> = (Option<&'a str>, Option<&'a str>);
pub trait Tokenizer {
fn index_parse(key: &str) -> Result<usize, IndexError>;
fn dict_parse(key: &str) -> Result<State, KeyError>;
}
pub trait Queryable
where
Self: Sized,
{
fn query<T>(&self, path: &str) -> Result<Self, Error>
where
T: Tokenizer,
{
let tokens = T::dict_parse(path)?;
match self.query_kind() {
Some(QueryKind::Dictionary) => match tokens {
(Some(key), Some(next)) => self
.query_dict(key)
.and_then(move |child| child.query::<T>(next)),
(Some(key), None) => self.query_dict(key),
_ => Err(Error::EmptyPath(QueryKind::Dictionary)),
},
Some(QueryKind::Array) => match tokens {
(Some(key), Some(next)) => {
let index = T::index_parse(key)?;
match self.query_array(index) {
Ok(child) => child.query::<T>(next),
_ => Err(Error::IndexNotExist(index)),
}
}
(Some(key), None) => {
let index = T::index_parse(key)?;
self.query_array(index)
}
_ => Err(Error::EmptyPath(QueryKind::Array)),
},
_ => Err(Error::UnknownType(String::from(path))),
}
}
fn query_kind(&self) -> Option<QueryKind>;
fn query_dict(&self, path: &str) -> Result<Self, Error>;
fn query_array(&self, idx: usize) -> Result<Self, Error>;
}