use crate::*; use std::marker::PhantomData; use ::tek_layout::{*, tek_engine::{Usually, Content, Render, Engine, Thunk}}; use Item::*; //pub struct EdnContent<'a, E, T: AsRef>(PhantomData, &'a [Item]); //impl<'a, E, T: AsRef> From<&'a [Item]> for EdnContent<'a, E, T> { //fn from (items: &'a [Item]) -> Self { //Self(Default::default(), items) //} //} pub struct EdnView<'a, E: Engine + 'a, T: EdnLayout<'a, E> + 'a>( PhantomData<&'a ()>, BoxBox + Send + Sync> + Send + Sync> ); impl<'a, E: Engine + 'a, T: EdnLayout<'a, E> + 'a> EdnView<'a, E, T> { fn from (source: &'a str) -> Usually { let items: Vec> = Item::read_all(source)?; let layout = T::parse(items.iter().map(|x|x.to_str()).collect::>().as_slice()); Ok(Self(Default::default(), Box::new(move|_|{ let _ = layout; Box::new(()) }))) } } macro_rules! edn_ns { (|$state:ident, $items:ident| { $($match:pat => $handle:expr),* $(,)? }) => { match $items { $($match => |$state|Box::new($handle),)* _ => |$state|Box::new(()) } } } pub trait EdnLayout<'a, E: Engine> where Self: 'a { fn get_bool (&self, _: &Item<&str>) -> bool { false } fn get_unit (&self, _: &Item<&str>) -> E::Unit { 0.into() } fn get_usize (&self, _: &Item<&str>) -> usize { 0 } fn get_content (&self, _: &Item<&str>) -> Box> { Box::new(()) } fn parse (items: &'a [Item<&'a str>]) -> impl Fn(&'a Self)->Box + 'a> + 'a { edn_ns!(|state, items|{ [Key("when"), c, a, ..] => When(state.get_bool(c), state.get_content(a)), [Key("either"), c, a, b, ..] => Either(state.get_bool(c), state.get_content(a), state.get_content(b)), [Key("fill"), a, ..] => Fill::xy(state.get_content(a)), [Key("fill/x"), a, ..] => Fill::x(state.get_content(a)), [Key("fill/y"), a, ..] => Fill::y(state.get_content(a)), [Key("fixed"), x, y, a, ..] => Fixed::xy(state.get_unit(x), state.get_unit(y), state.get_content(a)), [Key("fixed/x"), x, a, ..] => Fixed::x(state.get_unit(x), state.get_content(a)), [Key("fixed/y"), y, a, ..] => Fixed::y(state.get_unit(y), state.get_content(a)), [Key("shrink"), x, y, a, ..] => Shrink::xy(state.get_unit(x), state.get_unit(y), state.get_content(a)), [Key("shrink/x"), x, a, ..] => Shrink::x(state.get_unit(x), state.get_content(a)), [Key("shrink/y"), y, a, ..] => Shrink::y(state.get_unit(y), state.get_content(a)), [Key("expand"), x, y, a, ..] => Expand::xy(state.get_unit(x), state.get_unit(y), state.get_content(a)), [Key("expand/x"), x, a, ..] => Expand::x(state.get_unit(x), state.get_content(a)), [Key("expand/y"), y, a, ..] => Expand::y(state.get_unit(y), state.get_content(a)), [Key("push"), x, y, a, ..] => Push::xy(state.get_unit(x), state.get_unit(y), state.get_content(a)), [Key("push/x"), x, a, ..] => Push::x(state.get_unit(x), state.get_content(a)), [Key("push/y"), y, a, ..] => Push::y(state.get_unit(y), state.get_content(a)), [Key("pull"), x, y, a, ..] => Pull::xy(state.get_unit(x), state.get_unit(y), state.get_content(a)), [Key("pull/x"), x, a, ..] => Pull::x(state.get_unit(x), state.get_content(a)), [Key("pull/y"), y, a, ..] => Pull::y(state.get_unit(y), state.get_content(a)), }) } }