templar 0.5.0

Lightweight, fast, and powerful templating engine
Documentation
use super::*;

pub struct ContextWalk<'a> {
    inner: std::cell::RefCell<ContextWalkValue<'a>>,
}

impl<'a> ContextWalk<'a> {
    pub fn exec(&self, ctx: &impl Context) -> Data {
        let val = &*self.inner.borrow();
        match val {
            ContextWalkValue::None => Data::empty(),
            ContextWalkValue::Owned(v) => v.exec(ctx),
            ContextWalkValue::Ref(v) => v.exec(ctx),
        }
    }

    pub fn walk(&'a self, ctx: &impl Context, key: &InnerData) {
        let val = self.inner.borrow();
        let mut new_walk = None;
        let mut res = None;
        match &*val {
            ContextWalkValue::Ref(ContextMapValue::Map(m)) => new_walk = Some(m.get(key).into()),
            ContextWalkValue::Ref(val) => res = Some(val.exec(ctx)),
            ContextWalkValue::Owned(val) => res = Some(val.exec(ctx)),
            _ => return,
        };
        drop(val);
        if let Some(res) = res {
            new_walk = Some(if res.is_failed() || res.is_empty() {
                res.into()
            } else {
                match res.into_inner() {
                    InnerData::Map(m) => m.get(key).cloned().into(),
                    InnerData::Err(e) => e.into(),
                    other => other.into(),
                }
            })
        }
        let inner_mut: &mut ContextWalkValue<'a> = &mut self.inner.borrow_mut();
        drop(replace(inner_mut, new_walk.unwrap()));
    }
}

impl<'a> From<ContextWalkValue<'a>> for ContextWalk<'a> {
    fn from(val: ContextWalkValue<'a>) -> Self {
        ContextWalk {
            inner: std::cell::RefCell::new(val),
        }
    }
}

impl<'a> From<Option<&'a ContextMapValue>> for ContextWalk<'a> {
    fn from(val: Option<&'a ContextMapValue>) -> Self {
        match val {
            Some(v) => ContextWalkValue::Ref(v).into(),
            None => ContextWalkValue::from(Data::empty()).into(),
        }
    }
}

enum ContextWalkValue<'a> {
    Ref(&'a ContextMapValue),
    Owned(ContextMapValue),
    None,
}

impl<'a> From<Option<&'a ContextMapValue>> for ContextWalkValue<'a> {
    fn from(val: Option<&'a ContextMapValue>) -> Self {
        match val {
            Some(v) => Self::Ref(v),
            None => Self::None,
        }
    }
}

impl<'a> From<InnerData> for ContextWalkValue<'a> {
    fn from(val: InnerData) -> Self {
        Self::Owned(Data::from(val).into())
    }
}

impl<'a> From<TemplarError> for ContextWalkValue<'a> {
    fn from(val: TemplarError) -> Self {
        Self::Owned(Data::from(val).into())
    }
}

impl<'a> From<Option<InnerData>> for ContextWalkValue<'a> {
    fn from(val: Option<InnerData>) -> Self {
        match val {
            Some(v) => v.into(),
            None => Self::None,
        }
    }
}

impl<'a> From<Data> for ContextWalkValue<'a> {
    fn from(val: Data) -> Self {
        Self::Owned(val.into())
    }
}