diff --git a/src/re_bytes.rs b/src/re_bytes.rs index 0e3fc777b7..e42ae30437 100644 --- a/src/re_bytes.rs +++ b/src/re_bytes.rs @@ -682,21 +682,21 @@ impl<'t> Captures<'t> { /// Creates an iterator of all the capture groups in order of appearance /// in the regular expression. - pub fn iter<'a>(&'a self) -> SubCaptures<'a, 't> { + pub fn iter<'c>(&'c self) -> SubCaptures<'c, 't> { SubCaptures { idx: 0, caps: self } } /// Creates an iterator of all the capture group positions in order of /// appearance in the regular expression. Positions are byte indices /// in terms of the original string matched. - pub fn iter_pos(&'t self) -> SubCapturesPos<'t> { + pub fn iter_pos<'c>(&'c self) -> SubCapturesPos<'c> { SubCapturesPos { idx: 0, slots: &self.slots } } /// Creates an iterator of all named groups as an tuple with the group /// name and the value. The iterator returns these values in arbitrary /// order. - pub fn iter_named<'a>(&'a self) -> SubCapturesNamed<'a, 't> { + pub fn iter_named<'c>(&'c self) -> SubCapturesNamed<'c, 't> { SubCapturesNamed { caps: self, names: self.named_groups.iter() diff --git a/src/re_unicode.rs b/src/re_unicode.rs index 4653ee3430..8f671633b3 100644 --- a/src/re_unicode.rs +++ b/src/re_unicode.rs @@ -874,21 +874,21 @@ impl<'t> Captures<'t> { /// Creates an iterator of all the capture groups in order of appearance /// in the regular expression. - pub fn iter(&'t self) -> SubCaptures<'t> { + pub fn iter<'c>(&'c self) -> SubCaptures<'c, 't> { SubCaptures { idx: 0, caps: self, } } /// Creates an iterator of all the capture group positions in order of /// appearance in the regular expression. Positions are byte indices /// in terms of the original string matched. - pub fn iter_pos(&'t self) -> SubCapturesPos<'t> { + pub fn iter_pos<'c>(&'c self) -> SubCapturesPos<'c> { SubCapturesPos { idx: 0, slots: &self.slots } } /// Creates an iterator of all named groups as an tuple with the group /// name and the value. The iterator returns these values in arbitrary /// order. - pub fn iter_named(&'t self) -> SubCapturesNamed<'t> { + pub fn iter_named<'c>(&'c self) -> SubCapturesNamed<'c, 't> { SubCapturesNamed { caps: self, names: self.named_groups.iter() @@ -1013,16 +1013,17 @@ impl<'t, 'i> Index<&'i str> for Captures<'t> { /// An iterator over capture groups for a particular match of a regular /// expression. /// -/// `'c` is the lifetime of the captures. -pub struct SubCaptures<'c> { +/// `'c` is the lifetime of the captures and `'t` is the lifetime of the +/// matched text. +pub struct SubCaptures<'c, 't: 'c> { idx: usize, - caps: &'c Captures<'c>, + caps: &'c Captures<'t>, } -impl<'c> Iterator for SubCaptures<'c> { - type Item = Option<&'c str>; +impl<'c, 't> Iterator for SubCaptures<'c, 't> { + type Item = Option<&'t str>; - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { if self.idx < self.caps.len() { self.idx += 1; Some(self.caps.at(self.idx - 1)) @@ -1063,16 +1064,17 @@ impl<'c> Iterator for SubCapturesPos<'c> { /// An Iterator over named capture groups as a tuple with the group /// name and the value. /// -/// `'c` is the lifetime of the captures. -pub struct SubCapturesNamed<'c> { - caps: &'c Captures<'c>, +/// `'c` is the lifetime of the captures and `'t` is the lifetime of the +/// matched text. +pub struct SubCapturesNamed<'c, 't: 'c> { + caps: &'c Captures<'t>, names: NamedGroupsIter<'c>, } -impl<'c> Iterator for SubCapturesNamed<'c> { - type Item = (&'c str, Option<&'c str>); +impl<'c, 't> Iterator for SubCapturesNamed<'c, 't> { + type Item = (&'c str, Option<&'t str>); - fn next(&mut self) -> Option<(&'c str, Option<&'c str>)> { + fn next(&mut self) -> Option<(&'c str, Option<&'t str>)> { self.names.next().map(|(name, pos)| (name, self.caps.at(pos))) } } diff --git a/tests/api.rs b/tests/api.rs index e6c3a27a8d..dbf3ed20fe 100644 --- a/tests/api.rs +++ b/tests/api.rs @@ -168,12 +168,13 @@ fn capture_iter_missing() { #[test] fn capture_iter_pos() { let re = regex!(r"(.)(?P.)(.)(?P.)"); - let cap = re.captures(t!("abcd")).unwrap(); - let expected = vec![ (0, 4), (0, 1), (1, 2), (2, 3), (3, 4), ].into_iter().map(Some).collect::>(); - let got = cap.iter_pos().collect::>(); + let got = { + let cap = re.captures(t!("abcd")).unwrap(); + cap.iter_pos().collect::>() + }; assert_eq!(expected, got); } @@ -192,15 +193,21 @@ fn capture_iter_pos_missing() { #[test] fn capture_iter_named() { let re = regex!(r"(.)(?P.)(.)(?P.)"); - let cap = re.captures(t!("abcd")).unwrap(); - let expected1 = vec![ - ("a", Some(t!("b"))), ("b", Some(t!("d"))), + (String::from("a"), Some(t!("b"))), (String::from("b"), Some(t!("d"))), ]; let expected2 = vec![ - ("b", Some(t!("d"))), ("a", Some(t!("b"))), + (String::from("b"), Some(t!("d"))), (String::from("a"), Some(t!("b"))), ]; - let got = cap.iter_named().collect::>(); + let got = { + let cap = re.captures(t!("abcd")).unwrap(); + // The names live as long as the captures object, so we clone them. + // The texts, on the other hand, must have the lifetime of the matched + // text (in this case, 'static). + cap.iter_named() + .map(|(name, text)| (name.to_owned(), text)) + .collect::>() + }; assert!(got == expected1 || got == expected2); }