templar 0.5.0

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

pub struct Metadata {
    pub minimum_nodes: u16,
    pub maximum_nodes: Option<u16>,
}

pub(crate) enum Executors {
    Piped(PipedExecutor),
    Conditional(ConditionalExecutor),
    Indeterminate(IndeterminateExecutor),
    Loop(LoopExecutor),
    Filter(FilterExecutor),
    Function(FunctionExecutor),
}

pub(crate) struct IndeterminateExecutor(fn(&ContextWrapper, input: &[Node]) -> Data);

impl IndeterminateExecutor {
    #[inline]
    pub fn new(new_fn: fn(&ContextWrapper, input: &[Node]) -> Data) -> Self {
        Self(new_fn)
    }

    #[inline]
    pub(crate) fn metadata() -> &'static Metadata {
        &Metadata {
            minimum_nodes: 0,
            maximum_nodes: None,
        }
    }
}

pub(crate) struct ConditionalExecutor(
    fn(&ContextWrapper, condition: &Node, positive: &Node, negative: &Node) -> Data,
);

impl ConditionalExecutor {
    #[inline]
    pub fn new(
        new_fn: fn(&ContextWrapper, condition: &Node, positive: &Node, negative: &Node) -> Data,
    ) -> Self {
        Self(new_fn)
    }

    #[inline]
    pub(crate) fn metadata() -> &'static Metadata {
        &Metadata {
            minimum_nodes: 2,
            maximum_nodes: Some(3),
        }
    }
}
pub(crate) struct PipedExecutor(fn(&ContextWrapper, left: &Node, right: &Node) -> Data);

impl PipedExecutor {
    #[inline]
    pub fn new(new_fn: fn(&ContextWrapper, left: &Node, right: &Node) -> Data) -> Self {
        Self(new_fn)
    }

    #[inline]
    pub(crate) fn metadata() -> &'static Metadata {
        &Metadata {
            minimum_nodes: 2,
            maximum_nodes: Some(2),
        }
    }
}

pub(crate) struct LoopExecutor(
    fn(&ContextWrapper, ctx_name: &Node, arr: &Node, to_loop: &Node) -> Data,
);

impl LoopExecutor {
    #[inline]
    pub fn new(
        new_fn: fn(&ContextWrapper, val_name: &Node, val_array: &Node, exec: &Node) -> Data,
    ) -> Self {
        Self(new_fn)
    }

    #[inline]
    pub(crate) fn metadata() -> &'static Metadata {
        &Metadata {
            minimum_nodes: 3,
            maximum_nodes: Some(3),
        }
    }
}

pub(crate) struct FilterExecutor(Arc<dyn Fn(Data, Data) -> Data + Sync + Send>);

impl FilterExecutor {
    #[inline]
    pub fn new(new_fn: Arc<dyn Fn(Data, Data) -> Data + Sync + Send>) -> Self {
        Self(new_fn)
    }
}

pub(crate) struct FunctionExecutor(Arc<dyn Fn(Data) -> Data + Sync + Send>);

impl FunctionExecutor {
    #[inline]
    pub fn new(new_fn: Arc<dyn Fn(Data) -> Data + Sync + Send>) -> Self {
        Self(new_fn)
    }
}

pub(crate) trait Executor {
    fn exec(&self, ctx: &ContextWrapper, nodes: &[Node]) -> Data;
}

impl From<FilterExecutor> for Executors {
    #[inline]
    fn from(t: FilterExecutor) -> Self {
        Self::Filter(t)
    }
}

impl From<PipedExecutor> for Executors {
    #[inline]
    fn from(t: PipedExecutor) -> Self {
        Self::Piped(t)
    }
}

impl From<ConditionalExecutor> for Executors {
    #[inline]
    fn from(t: ConditionalExecutor) -> Self {
        Self::Conditional(t)
    }
}

impl From<IndeterminateExecutor> for Executors {
    #[inline]
    fn from(t: IndeterminateExecutor) -> Self {
        Self::Indeterminate(t)
    }
}

impl From<LoopExecutor> for Executors {
    #[inline]
    fn from(t: LoopExecutor) -> Self {
        Self::Loop(t)
    }
}

impl Executor for Executors {
    #[inline]
    fn exec(&self, ctx: &ContextWrapper, nodes: &[Node]) -> Data {
        match self {
            Self::Piped(ref ex) => ex.exec(ctx, nodes),
            Self::Conditional(ref ex) => ex.exec(ctx, nodes),
            Self::Indeterminate(ref ex) => ex.exec(ctx, nodes),
            Self::Loop(ref ex) => ex.exec(ctx, nodes),
            Self::Filter(ref ex) => ex.exec(ctx, nodes),
            Self::Function(ref ex) => ex.exec(ctx, nodes),
        }
    }
}

impl Executor for IndeterminateExecutor {
    #[inline]
    fn exec(&self, ctx: &ContextWrapper, nodes: &[Node]) -> Data {
        self.0(ctx, &nodes)
    }
}

impl Executor for FilterExecutor {
    #[inline]
    fn exec(&self, ctx: &ContextWrapper, nodes: &[Node]) -> Data {
        self.0(nodes[0].exec(ctx), nodes[1].exec(ctx))
    }
}

impl Executor for FunctionExecutor {
    #[inline]
    fn exec(&self, ctx: &ContextWrapper, nodes: &[Node]) -> Data {
        self.0(nodes[0].exec(ctx))
    }
}

impl Executor for PipedExecutor {
    #[inline]
    fn exec(&self, ctx: &ContextWrapper, nodes: &[Node]) -> Data {
        self.0(ctx, &nodes[0], &nodes[1])
    }
}

impl Executor for ConditionalExecutor {
    #[inline]
    fn exec(&self, ctx: &ContextWrapper, nodes: &[Node]) -> Data {
        self.0(ctx, &nodes[0], &nodes[1], &nodes[2])
    }
}

impl Executor for LoopExecutor {
    #[inline]
    fn exec(&self, ctx: &ContextWrapper, nodes: &[Node]) -> Data {
        self.0(ctx, &nodes[0], &nodes[1], &nodes[2])
    }
}