upon 0.10.0

A simple, powerful template engine with minimal dependencies and configurable delimiters
Documentation
use crate::types::delimiter::Delimiter;
use crate::types::syntax::Syntax;
use aho_corasick::{AhoCorasick, AhoCorasickBuilder, Anchored, Input, MatchKind, StartKind};

#[cfg_attr(internal_debug, derive(Debug))]
pub struct AhoCorasickSearcher {
    imp: AhoCorasick,
    delimiters: Vec<Delimiter>,
}

impl AhoCorasickSearcher {
    pub fn new(syntax: Syntax) -> Self {
        let imp = AhoCorasickBuilder::new()
            .start_kind(StartKind::Both)
            .match_kind(MatchKind::LeftmostLongest)
            .build(syntax.patterns)
            .expect("failed to build AhoCorasick");
        Self {
            imp,
            delimiters: syntax.delimiters,
        }
    }

    #[inline]
    pub fn find_at(&self, source: &str, at: usize) -> Option<(Delimiter, usize, usize)> {
        self.imp.find(Input::new(source).range(at..)).map(|m| {
            let delimiter = self.delimiters[m.pattern()];
            (delimiter, m.start(), m.end())
        })
    }

    #[inline]
    pub fn starts_with(&self, source: &str, at: usize) -> Option<(Delimiter, usize)> {
        self.imp
            .find(Input::new(source).range(at..).anchored(Anchored::Yes))
            .map(|m| {
                let delimiter = self.delimiters[m.pattern()];
                (delimiter, m.end())
            })
    }
}