goodrouter 1.0.12

a bi directional trie router for all your routing needs
Documentation
use regex::{CaptureMatches, Regex};

pub fn parse_template_parts<'r>(template: &'r str, re: &'r Regex) -> TemplateParts<'r> {
    TemplateParts::new(template, re)
}

pub struct TemplateParts<'r> {
    template: &'r str,
    matches: CaptureMatches<'r, 'r>,
    is_finished: bool,
    index: usize,
    part_offset: usize,
    parameter: &'r str,
}

impl<'r> TemplateParts<'r> {
    fn new(template: &'r str, re: &'r Regex) -> Self {
        let matches = re.captures_iter(template);
        let is_finished = false;
        let part_index = 0;
        let part_offset = 0;
        let parameter = "";

        Self {
            template,
            matches,
            is_finished,
            index: part_index,
            part_offset,
            parameter,
        }
    }
}

impl<'r> Iterator for TemplateParts<'r> {
    type Item = &'r str;

    fn next(&mut self) -> Option<Self::Item> {
        if self.is_finished {
            return None;
        }

        let result = if self.index % 2 == 0 {
            let part_offset = self.part_offset;

            if let Some(current_match) = self.matches.next() {
                let first_capture = current_match.get(0).unwrap();
                let current_capture = current_match.get(1).unwrap();

                self.part_offset = first_capture.end();
                self.parameter = current_capture.as_str();

                Some(&self.template[part_offset..first_capture.start()])
            } else {
                self.is_finished = true;

                Some(&self.template[part_offset..])
            }
        } else {
            Some(self.parameter)
        };

        self.index += 1;

        result
    }
}

#[cfg(test)]
mod tests {
    use super::super::TEMPLATE_PLACEHOLDER_REGEX;
    use super::*;

    #[test]
    fn parse_template_parts_test() {
        let parts: Vec<_> =
            parse_template_parts("/a/{b}/{c}", &TEMPLATE_PLACEHOLDER_REGEX).collect();

        assert_eq!(parts, vec!["/a/", "b", "/", "c", ""]);

        let parts: Vec<_> =
            parse_template_parts("/a/{b}/{c}/", &TEMPLATE_PLACEHOLDER_REGEX).collect();

        assert_eq!(parts, vec!["/a/", "b", "/", "c", "/"]);

        let parts: Vec<_> = parse_template_parts("", &TEMPLATE_PLACEHOLDER_REGEX).collect();

        assert_eq!(parts, vec![""])
    }
}