// Taken from: https://github.com/rust-lang/regex/issues/330#issuecomment-274058261 use regex::{CaptureMatches, Captures, Regex}; pub struct SplitCaptures<'r, 't> { finder: CaptureMatches<'r, 't>, text: &'t str, last: usize, caps: Option>, } impl<'r, 't> SplitCaptures<'r, 't> { pub fn new(re: &'r Regex, text: &'t str) -> SplitCaptures<'r, 't> { SplitCaptures { finder: re.captures_iter(text), text, last: 0, caps: None, } } } #[derive(Debug)] pub enum SplitState<'t> { Unmatched(&'t str), Captured(Captures<'t>), } impl<'r, 't> Iterator for SplitCaptures<'r, 't> { type Item = SplitState<'t>; fn next(&mut self) -> Option> { if let Some(caps) = self.caps.take() { return Some(SplitState::Captured(caps)); } match self.finder.next() { None => { if self.last >= self.text.len() { None } else { let s = &self.text[self.last..]; self.last = self.text.len(); Some(SplitState::Unmatched(s)) } } Some(caps) => { let m = caps.get(0).unwrap(); let unmatched = &self.text[self.last..m.start()]; self.last = m.end(); self.caps = Some(caps); Some(SplitState::Unmatched(unmatched)) } } } }