@@ -211,6 +211,25 @@ pub trait ParallelString {
211
211
fn par_matches < P : Pattern > ( & self , pattern : P ) -> Matches < P > {
212
212
Matches { chars : self . as_parallel_string ( ) , pattern }
213
213
}
214
+
215
+ /// Returns a parallel iterator over substrings that match a given character
216
+ /// or predicate, with their positions, similar to `str::match_indices`.
217
+ ///
218
+ /// Note: the `Pattern` trait is private, for use only by Rayon itself.
219
+ /// It is implemented for `char` and any `F: Fn(char) -> bool + Sync + Send`.
220
+ ///
221
+ /// # Examples
222
+ ///
223
+ /// ```
224
+ /// use rayon::prelude::*;
225
+ /// let digits: Vec<_> = "1, 2, buckle, 3, 4, door"
226
+ /// .par_match_indices(char::is_numeric)
227
+ /// .collect();
228
+ /// assert_eq!(digits, vec![(0, "1"), (3, "2"), (14, "3"), (17, "4")]);
229
+ /// ```
230
+ fn par_match_indices < P : Pattern > ( & self , pattern : P ) -> MatchIndices < P > {
231
+ MatchIndices { chars : self . as_parallel_string ( ) , pattern }
232
+ }
214
233
}
215
234
216
235
impl ParallelString for str {
@@ -243,6 +262,8 @@ mod private {
243
262
where F : Folder < & ' ch str > ;
244
263
fn fold_matches < ' ch , F > ( & self , & ' ch str , folder : F ) -> F
245
264
where F : Folder < & ' ch str > ;
265
+ fn fold_match_indices < ' ch , F > ( & self , & ' ch str , folder : F , base : usize ) -> F
266
+ where F : Folder < ( usize , & ' ch str ) > ;
246
267
}
247
268
}
248
269
use self :: private:: Pattern ;
@@ -280,6 +301,12 @@ impl Pattern for char {
280
301
{
281
302
folder. consume_iter ( chars. matches ( * self ) )
282
303
}
304
+
305
+ fn fold_match_indices < ' ch , F > ( & self , chars : & ' ch str , folder : F , base : usize ) -> F
306
+ where F : Folder < ( usize , & ' ch str ) >
307
+ {
308
+ folder. consume_iter ( chars. match_indices ( * self ) . map ( move |( i, s) | ( base + i, s) ) )
309
+ }
283
310
}
284
311
285
312
impl < FN : Sync + Send + Fn ( char ) -> bool > Pattern for FN {
@@ -312,6 +339,12 @@ impl<FN: Sync + Send + Fn(char) -> bool> Pattern for FN {
312
339
{
313
340
folder. consume_iter ( chars. matches ( self ) )
314
341
}
342
+
343
+ fn fold_match_indices < ' ch , F > ( & self , chars : & ' ch str , folder : F , base : usize ) -> F
344
+ where F : Folder < ( usize , & ' ch str ) >
345
+ {
346
+ folder. consume_iter ( chars. match_indices ( self ) . map ( move |( i, s) | ( base + i, s) ) )
347
+ }
315
348
}
316
349
317
350
@@ -686,3 +719,53 @@ impl<'ch, 'pat, P: Pattern> UnindexedProducer for MatchesProducer<'ch, 'pat, P>
686
719
self . pattern . fold_matches ( self . chars , folder)
687
720
}
688
721
}
722
+
723
+
724
+ // /////////////////////////////////////////////////////////////////////////
725
+
726
+ /// Parallel iterator over substrings that match a pattern, with their positions
727
+ #[ derive( Debug , Clone ) ]
728
+ pub struct MatchIndices < ' ch , P : Pattern > {
729
+ chars : & ' ch str ,
730
+ pattern : P ,
731
+ }
732
+
733
+ struct MatchIndicesProducer < ' ch , ' pat , P : Pattern + ' pat > {
734
+ index : usize ,
735
+ chars : & ' ch str ,
736
+ pattern : & ' pat P ,
737
+ }
738
+
739
+ impl < ' ch , P : Pattern > ParallelIterator for MatchIndices < ' ch , P > {
740
+ type Item = ( usize , & ' ch str ) ;
741
+
742
+ fn drive_unindexed < C > ( self , consumer : C ) -> C :: Result
743
+ where C : UnindexedConsumer < Self :: Item >
744
+ {
745
+ let producer = MatchIndicesProducer { index : 0 , chars : self . chars , pattern : & self . pattern } ;
746
+ bridge_unindexed ( producer, consumer)
747
+ }
748
+ }
749
+
750
+ impl < ' ch , ' pat , P : Pattern > UnindexedProducer for MatchIndicesProducer < ' ch , ' pat , P > {
751
+ type Item = ( usize , & ' ch str ) ;
752
+
753
+ fn split ( mut self ) -> ( Self , Option < Self > ) {
754
+ let index = find_char_midpoint ( self . chars ) ;
755
+ if index > 0 {
756
+ let ( left, right) = self . chars . split_at ( index) ;
757
+ let right_index = self . index + index;
758
+ let pattern = self . pattern ;
759
+ self . chars = left;
760
+ ( self , Some ( MatchIndicesProducer { index : right_index, chars : right, pattern } ) )
761
+ } else {
762
+ ( self , None )
763
+ }
764
+ }
765
+
766
+ fn fold_with < F > ( self , folder : F ) -> F
767
+ where F : Folder < Self :: Item >
768
+ {
769
+ self . pattern . fold_match_indices ( self . chars , folder, self . index )
770
+ }
771
+ }
0 commit comments