trql 0.2.0

Query language for programmatically generating structures from trees.
Documentation
use crate::{
    query::{Operation, Select, Series},
    tree::{Chain, Children, Condition, Descendants, DynNodes, Node, Nodes, Tree},
};

pub trait Command {
    fn execute<'a, T: Tree + 'a, I: Nodes<T> + 'a>(self, iter: I) -> Box<dyn DynNodes<T> + 'a>;
}

impl Command for Select {
    fn execute<'a, T: Tree + 'a, I: Nodes<T> + 'a>(self, iter: I) -> Box<dyn DynNodes<T> + 'a> {
        Box::new(Chain::<T>::new(
            self.into_iter()
                .map(|x| x.execute::<T, I>(iter.clone()))
                .collect(),
        ))
    }
}

impl Command for Series {
    fn execute<'a, T: Tree + 'a, I: Nodes<T> + 'a>(self, iter: I) -> Box<dyn DynNodes<T> + 'a> {
        let mut iter = Box::new(iter) as Box<dyn DynNodes<T> + 'a>;
        for command in self {
            iter = command.execute::<T, Box<dyn DynNodes<T> + 'a>>(iter);
        }
        iter
    }
}

impl Command for Operation {
    fn execute<'a, T: Tree + 'a, I: Nodes<T> + 'a>(self, iter: I) -> Box<dyn DynNodes<T> + 'a> {
        match self {
            Self::Parallel(select) => select.execute(iter),
            Self::Condition(select) => Box::new(Condition::new(iter, move |tree: T| {
                select.clone().execute::<T, T>(tree)
            })),
            Self::Range { from, to, step } => Box::new(
                iter.zip(1..)
                    .filter(move |&(_, i)| (from <= i && i <= to && (i - from) % step == 0))
                    .map(|(node, _)| node),
            ),
            Self::Descendants => Box::new(Descendants::<T, I>::new(iter)),
            Self::Children => Box::new(Children::<T, I>::new(iter)),
            Self::Token(token) => Box::new(iter.filter(move |node| node.name() == token)),
        }
    }
}