use crate::*; /// Map EDN tokens to parameters of a given type for a given context /// TODO: Replace both [Context] and [TryFromDsl] with this trait /// which returns a [Result]. pub trait Dsl: Sized { fn take <'state, 'source> (_: &'state Self, _: &mut TokenIter<'source>) -> Perhaps { Ok(None) } fn take_or_fail <'state, 'source> ( state: &'state Self, iter: &mut TokenIter<'source> ) -> Usually { if let Some(value) = Self::take(state, iter)? { Ok(value) } else { Result::Err("not found".into()) // TODO add info and error type } } } /// Map EDN tokens to parameters of a given type for a given context pub trait Context<'state, U>: Sized { fn get <'source> (&'state self, _iter: &mut TokenIter<'source>) -> Option { None } } impl<'state, T: Context<'state, U>, U> Context<'state, U> for &T { fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { (*self).get(iter) } } impl<'state, T: Context<'state, U>, U> Context<'state, U> for Option { fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { self.as_ref().map(|s|s.get(iter)).flatten() } } pub trait TryFromDsl<'state, T>: Sized { fn try_from_expr <'source: 'state> ( _state: &'state T, _iter: &mut TokenIter<'source> ) -> Option { None } fn try_from_atom <'source: 'state> ( state: &'state T, value: Value<'source> ) -> Option { if let Exp(0, mut iter) = value { return Self::try_from_expr(state, &mut iter) } None } }