spinoso_regexp/regexp/regex/utf8/
iter.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use core::iter::{Enumerate, FusedIterator};
use core::ops::Range;

use regex::CaptureNames;

#[derive(Debug)]
#[must_use = "this `Captures` is an `Iterator`, which should be consumed if constructed"]
pub struct Captures<'a> {
    captures: regex::Captures<'a>,
    iter: Range<usize>,
}

impl<'a> From<regex::Captures<'a>> for Captures<'a> {
    fn from(captures: regex::Captures<'a>) -> Self {
        let iter = 0..captures.len();
        Self { captures, iter }
    }
}

impl<'a> Iterator for Captures<'a> {
    type Item = Option<&'a [u8]>;

    fn next(&mut self) -> Option<Self::Item> {
        let idx = self.iter.next()?;
        match self.captures.get(idx) {
            Some(capture) => Some(Some(capture.as_str().as_bytes())),
            None => Some(None),
        }
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        let idx = self.iter.nth(n)?;
        match self.captures.get(idx) {
            Some(capture) => Some(Some(capture.as_str().as_bytes())),
            None => Some(None),
        }
    }

    fn count(self) -> usize {
        self.iter.count()
    }
}

impl FusedIterator for Captures<'_> {}

#[derive(Debug)]
#[must_use = "this `CaptureIndices` is an `Iterator`, which should be consumed if constructed"]
pub struct CaptureIndices<'a, 'b> {
    name: &'b [u8],
    capture_names: Enumerate<CaptureNames<'a>>,
}

impl<'a, 'b> CaptureIndices<'a, 'b> {
    pub(crate) fn with_name_and_iter(name: &'b [u8], iter: CaptureNames<'a>) -> Self {
        Self {
            name,
            capture_names: iter.enumerate(),
        }
    }

    /// The name of the capture group this iterator targets.
    pub const fn name(&self) -> &'b [u8] {
        self.name
    }
}

impl Iterator for CaptureIndices<'_, '_> {
    type Item = usize;

    fn next(&mut self) -> Option<Self::Item> {
        for (index, group) in self.capture_names.by_ref() {
            let group = group.map(str::as_bytes);
            if matches!(group, Some(group) if group == self.name) {
                return Some(index);
            }
        }
        None
    }
}

impl FusedIterator for CaptureIndices<'_, '_> {}