diff --git a/src/re_bytes.rs b/src/re_bytes.rs index ca01e0ec9..a3d494ad2 100644 --- a/src/re_bytes.rs +++ b/src/re_bytes.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::fmt; +use std::iter::FusedIterator; use std::ops::{Index, Range}; use std::str::FromStr; use std::sync::Arc; @@ -701,6 +702,8 @@ impl<'r, 't> Iterator for Matches<'r, 't> { } } +impl<'r, 't> FusedIterator for Matches<'r, 't> {} + /// An iterator that yields all non-overlapping capture groups matching a /// particular regular expression. /// @@ -724,6 +727,8 @@ impl<'r, 't> Iterator for CaptureMatches<'r, 't> { } } +impl<'r, 't> FusedIterator for CaptureMatches<'r, 't> {} + /// Yields all substrings delimited by a regular expression match. /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the @@ -757,6 +762,8 @@ impl<'r, 't> Iterator for Split<'r, 't> { } } +impl<'r, 't> FusedIterator for Split<'r, 't> {} + /// Yields at most `N` substrings delimited by a regular expression match. /// /// The last substring will be whatever remains after splitting. @@ -790,8 +797,14 @@ impl<'r, 't> Iterator for SplitN<'r, 't> { Some(&text[self.splits.last..]) } } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.n)) + } } +impl<'r, 't> FusedIterator for SplitN<'r, 't> {} + /// An iterator over the names of all possible captures. /// /// `None` indicates an unnamed capture; the first element (capture 0, the @@ -813,8 +826,16 @@ impl<'r> Iterator for CaptureNames<'r> { fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + + fn count(self) -> usize { + self.0.count() + } } +impl<'r> ExactSizeIterator for CaptureNames<'r> {} + +impl<'r> FusedIterator for CaptureNames<'r> {} + /// CaptureLocations is a low level representation of the raw offsets of each /// submatch. /// @@ -1073,6 +1094,8 @@ impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> { } } +impl<'c, 't> FusedIterator for SubCaptureMatches<'c, 't> {} + /// Replacer describes types that can be used to replace matches in a byte /// string. /// diff --git a/src/re_set.rs b/src/re_set.rs index b8954be7f..573b6e8f2 100644 --- a/src/re_set.rs +++ b/src/re_set.rs @@ -352,6 +352,8 @@ impl DoubleEndedIterator for SetMatchesIntoIter { } } +impl iter::FusedIterator for SetMatchesIntoIter {} + /// A borrowed iterator over the set of matches from a regex set. /// /// The lifetime `'a` refers to the lifetime of a `SetMatches` value. @@ -392,6 +394,8 @@ impl<'a> DoubleEndedIterator for SetMatchesIter<'a> { } } +impl<'a> iter::FusedIterator for SetMatchesIter<'a> {} + #[doc(hidden)] impl From for RegexSet { fn from(exec: Exec) -> Self { diff --git a/src/re_trait.rs b/src/re_trait.rs index d14a9f761..7bade9821 100644 --- a/src/re_trait.rs +++ b/src/re_trait.rs @@ -1,3 +1,5 @@ +use std::iter::FusedIterator; + /// Slot is a single saved capture location. Note that there are two slots for /// every capture in a regular expression (one slot each for the start and end /// of the capture). @@ -73,6 +75,8 @@ impl<'c> Iterator for SubCapturesPosIter<'c> { } } +impl<'c> FusedIterator for SubCapturesPosIter<'c> {} + /// `RegularExpression` describes types that can implement regex searching. /// /// This trait is my attempt at reducing code duplication and to standardize @@ -205,6 +209,13 @@ where } } +impl<'t, R> FusedIterator for Matches<'t, R> +where + R: RegularExpression, + R::Text: 't + AsRef<[u8]>, +{ +} + /// An iterator over all non-overlapping successive leftmost-first matches with /// captures. pub struct CaptureMatches<'t, R>(Matches<'t, R>) @@ -260,3 +271,10 @@ where Some(locs) } } + +impl<'t, R> FusedIterator for CaptureMatches<'t, R> +where + R: RegularExpression, + R::Text: 't + AsRef<[u8]>, +{ +} diff --git a/src/re_unicode.rs b/src/re_unicode.rs index ea95c1b6d..5fad4d4fe 100644 --- a/src/re_unicode.rs +++ b/src/re_unicode.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::fmt; +use std::iter::FusedIterator; use std::ops::{Index, Range}; use std::str::FromStr; use std::sync::Arc; @@ -762,8 +763,16 @@ impl<'r> Iterator for CaptureNames<'r> { fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + + fn count(self) -> usize { + self.0.count() + } } +impl<'r> ExactSizeIterator for CaptureNames<'r> {} + +impl<'r> FusedIterator for CaptureNames<'r> {} + /// Yields all substrings delimited by a regular expression match. /// /// `'r` is the lifetime of the compiled regular expression and `'t` is the @@ -797,6 +806,8 @@ impl<'r, 't> Iterator for Split<'r, 't> { } } +impl<'r, 't> FusedIterator for Split<'r, 't> {} + /// Yields at most `N` substrings delimited by a regular expression match. /// /// The last substring will be whatever remains after splitting. @@ -830,8 +841,14 @@ impl<'r, 't> Iterator for SplitN<'r, 't> { Some(&text[self.splits.last..]) } } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.n)) + } } +impl<'r, 't> FusedIterator for SplitN<'r, 't> {} + /// CaptureLocations is a low level representation of the raw offsets of each /// submatch. /// @@ -1075,6 +1092,8 @@ impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> { } } +impl<'c, 't> FusedIterator for SubCaptureMatches<'c, 't> {} + /// An iterator that yields all non-overlapping capture groups matching a /// particular regular expression. /// @@ -1098,6 +1117,8 @@ impl<'r, 't> Iterator for CaptureMatches<'r, 't> { } } +impl<'r, 't> FusedIterator for CaptureMatches<'r, 't> {} + /// An iterator over all non-overlapping matches for a particular string. /// /// The iterator yields a `Match` value. The iterator stops when no more @@ -1116,6 +1137,8 @@ impl<'r, 't> Iterator for Matches<'r, 't> { } } +impl<'r, 't> FusedIterator for Matches<'r, 't> {} + /// Replacer describes types that can be used to replace matches in a string. /// /// In general, users of this crate shouldn't need to implement this trait,