9
9
// except according to those terms.
10
10
11
11
use std:: borrow:: Cow ;
12
- use std:: collections:: HashMap ;
13
- use std:: collections:: hash_map:: Iter ;
14
12
use std:: fmt;
15
13
use std:: ops:: Index ;
16
14
#[ cfg( feature = "pattern" ) ]
@@ -186,6 +184,8 @@ pub struct ExNative {
186
184
#[ doc( hidden) ]
187
185
pub names : & ' static & ' static [ Option < & ' static str > ] ,
188
186
#[ doc( hidden) ]
187
+ pub groups : & ' static & ' static [ ( & ' static str , usize ) ] ,
188
+ #[ doc( hidden) ]
189
189
pub prog : fn ( & mut CaptureIdxs , & str , usize ) -> bool ,
190
190
}
191
191
@@ -416,10 +416,14 @@ impl Regex {
416
416
///
417
417
/// The `0`th capture group is always unnamed, so it must always be
418
418
/// accessed with `at(0)` or `[0]`.
419
- pub fn captures < ' t > ( & self , text : & ' t str ) -> Option < Captures < ' t > > {
420
- let mut caps = self . alloc_captures ( ) ;
421
- if exec ( self , & mut caps, text, 0 ) {
422
- Some ( Captures :: new ( self , text, caps) )
419
+ pub fn captures < ' r , ' t > ( & ' r self , text : & ' t str ) -> Option < Captures < ' r , ' t > > {
420
+ let mut locs = self . alloc_captures ( ) ;
421
+ if exec ( self , & mut locs, text, 0 ) {
422
+ Some ( Captures {
423
+ regex : self ,
424
+ text : text,
425
+ locs : locs,
426
+ } )
423
427
} else {
424
428
None
425
429
}
@@ -823,37 +827,13 @@ impl<'r, 't> Iterator for RegexSplitsN<'r, 't> {
823
827
/// Positions returned from a capture group are always byte indices.
824
828
///
825
829
/// `'t` is the lifetime of the matched text.
826
- pub struct Captures < ' t > {
830
+ pub struct Captures < ' r , ' t > {
831
+ regex : & ' r Regex ,
827
832
text : & ' t str ,
828
833
locs : Vec < Option < usize > > ,
829
- named : Option < HashMap < String , usize > > ,
830
834
}
831
835
832
- impl < ' t > Captures < ' t > {
833
- fn new (
834
- re : & Regex ,
835
- search : & ' t str ,
836
- locs : Vec < Option < usize > > ,
837
- ) -> Captures < ' t > {
838
- let named =
839
- if re. captures_len ( ) == 0 {
840
- None
841
- } else {
842
- let mut named = HashMap :: new ( ) ;
843
- for ( i, name) in re. capture_names ( ) . enumerate ( ) {
844
- if let Some ( name) = name {
845
- named. insert ( name. to_owned ( ) , i) ;
846
- }
847
- }
848
- Some ( named)
849
- } ;
850
- Captures {
851
- text : search,
852
- locs : locs,
853
- named : named,
854
- }
855
- }
856
-
836
+ impl < ' r , ' t > Captures < ' r , ' t > {
857
837
/// Returns the start and end positions of the Nth capture group.
858
838
/// Returns `None` if `i` is not a valid capture group or if the capture
859
839
/// group did not match anything.
@@ -882,35 +862,50 @@ impl<'t> Captures<'t> {
882
862
/// `name` isn't a valid capture group or didn't match anything, then
883
863
/// `None` is returned.
884
864
pub fn name ( & self , name : & str ) -> Option < & ' t str > {
885
- match self . named {
886
- None => None ,
887
- Some ( ref h) => {
888
- match h. get ( name) {
889
- None => None ,
890
- Some ( i) => self . at ( * i) ,
865
+ match * self . regex {
866
+ Regex :: Native ( ExNative { ref groups, .. } ) => {
867
+ match groups. binary_search_by ( |& ( n, _) | n. cmp ( name) ) {
868
+ Ok ( i) => self . at ( groups[ i] . 1 ) ,
869
+ Err ( _) => None
891
870
}
892
- }
871
+ } ,
872
+ Regex :: Dynamic ( Program { ref named_groups, .. } ) => {
873
+ named_groups. get ( name) . and_then ( |i| self . at ( * i) )
874
+ } ,
893
875
}
894
876
}
895
877
896
878
/// Creates an iterator of all the capture groups in order of appearance
897
879
/// in the regular expression.
898
- pub fn iter ( & ' t self ) -> SubCaptures < ' t > {
880
+ pub fn iter < ' c > ( & ' c self ) -> SubCaptures < ' c , ' r , ' t > {
899
881
SubCaptures { idx : 0 , caps : self , }
900
882
}
901
883
902
884
/// Creates an iterator of all the capture group positions in order of
903
885
/// appearance in the regular expression. Positions are byte indices
904
886
/// in terms of the original string matched.
905
- pub fn iter_pos ( & ' t self ) -> SubCapturesPos < ' t > {
887
+ pub fn iter_pos < ' c > ( & ' c self ) -> SubCapturesPos < ' c , ' r , ' t > {
906
888
SubCapturesPos { idx : 0 , caps : self , }
907
889
}
908
890
909
891
/// Creates an iterator of all named groups as an tuple with the group
910
892
/// name and the value. The iterator returns these values in arbitrary
911
893
/// order.
912
- pub fn iter_named ( & ' t self ) -> SubCapturesNamed < ' t > {
913
- SubCapturesNamed { caps : self , inner : self . named . as_ref ( ) . map ( |n| n. iter ( ) ) }
894
+ pub fn iter_named < ' c > ( & ' c self ) -> SubCapturesNamed < ' c , ' r , ' t > {
895
+ let iter = match * self . regex {
896
+ Regex :: Native ( ExNative { ref groups, .. } ) => {
897
+ Box :: new ( groups. iter ( ) . map ( |& v| v) )
898
+ as Box < Iterator < Item =( & ' r str , usize ) > + ' r >
899
+ } ,
900
+ Regex :: Dynamic ( Program { ref named_groups, .. } ) => {
901
+ Box :: new ( named_groups. iter ( ) . map ( |( s, i) | ( & s[ ..] , * i) ) )
902
+ as Box < Iterator < Item =( & ' r str , usize ) > + ' r >
903
+ } ,
904
+ } ;
905
+ SubCapturesNamed {
906
+ caps : self ,
907
+ inner : iter
908
+ }
914
909
}
915
910
916
911
/// Expands all instances of `$name` in `text` to the corresponding capture
@@ -953,7 +948,7 @@ impl<'t> Captures<'t> {
953
948
///
954
949
/// # Panics
955
950
/// If there is no group at the given index.
956
- impl < ' t > Index < usize > for Captures < ' t > {
951
+ impl < ' r , ' t > Index < usize > for Captures < ' r , ' t > {
957
952
958
953
type Output = str ;
959
954
@@ -967,7 +962,7 @@ impl<'t> Index<usize> for Captures<'t> {
967
962
///
968
963
/// # Panics
969
964
/// If there is no group named by the given value.
970
- impl < ' t > Index < & ' t str > for Captures < ' t > {
965
+ impl < ' r , ' t > Index < & ' t str > for Captures < ' r , ' t > {
971
966
972
967
type Output = str ;
973
968
@@ -984,12 +979,12 @@ impl<'t> Index<&'t str> for Captures<'t> {
984
979
/// expression.
985
980
///
986
981
/// `'t` is the lifetime of the matched text.
987
- pub struct SubCaptures < ' t > {
982
+ pub struct SubCaptures < ' c , ' r : ' c , ' t : ' c > {
988
983
idx : usize ,
989
- caps : & ' t Captures < ' t > ,
984
+ caps : & ' c Captures < ' r , ' t > ,
990
985
}
991
986
992
- impl < ' t > Iterator for SubCaptures < ' t > {
987
+ impl < ' c , ' r , ' t > Iterator for SubCaptures < ' c , ' r , ' t > {
993
988
type Item = Option < & ' t str > ;
994
989
995
990
fn next ( & mut self ) -> Option < Option < & ' t str > > {
@@ -1008,12 +1003,12 @@ impl<'t> Iterator for SubCaptures<'t> {
1008
1003
/// Positions are byte indices in terms of the original string matched.
1009
1004
///
1010
1005
/// `'t` is the lifetime of the matched text.
1011
- pub struct SubCapturesPos < ' t > {
1006
+ pub struct SubCapturesPos < ' c , ' r : ' c , ' t : ' c > {
1012
1007
idx : usize ,
1013
- caps : & ' t Captures < ' t > ,
1008
+ caps : & ' c Captures < ' r , ' t > ,
1014
1009
}
1015
1010
1016
- impl < ' t > Iterator for SubCapturesPos < ' t > {
1011
+ impl < ' c , ' r , ' t > Iterator for SubCapturesPos < ' c , ' r , ' t > {
1017
1012
type Item = Option < ( usize , usize ) > ;
1018
1013
1019
1014
fn next ( & mut self ) -> Option < Option < ( usize , usize ) > > {
@@ -1030,17 +1025,17 @@ impl<'t> Iterator for SubCapturesPos<'t> {
1030
1025
/// name and the value.
1031
1026
///
1032
1027
/// `'t` is the lifetime of the matched text.
1033
- pub struct SubCapturesNamed < ' t > {
1034
- caps : & ' t Captures < ' t > ,
1035
- inner : Option < Iter < ' t , String , usize > > ,
1028
+ pub struct SubCapturesNamed < ' c , ' r : ' c , ' t : ' c > {
1029
+ caps : & ' c Captures < ' r , ' t > ,
1030
+ inner : Box < Iterator < Item = ( & ' r str , usize ) > + ' r > ,
1036
1031
}
1037
1032
1038
- impl < ' t > Iterator for SubCapturesNamed < ' t > {
1039
- type Item = ( & ' t str , Option < & ' t str > ) ;
1033
+ impl < ' c , ' r , ' t > Iterator for SubCapturesNamed < ' c , ' r , ' t > {
1034
+ type Item = ( & ' r str , Option < & ' t str > ) ;
1040
1035
1041
- fn next ( & mut self ) -> Option < ( & ' t str , Option < & ' t str > ) > {
1042
- match self . inner . as_mut ( ) . map_or ( None , |it| it . next ( ) ) {
1043
- Some ( ( name, pos) ) => Some ( ( name, self . caps . at ( * pos) ) ) ,
1036
+ fn next ( & mut self ) -> Option < ( & ' r str , Option < & ' t str > ) > {
1037
+ match self . inner . next ( ) {
1038
+ Some ( ( name, pos) ) => Some ( ( name, self . caps . at ( pos) ) ) ,
1044
1039
None => None
1045
1040
}
1046
1041
}
@@ -1061,9 +1056,9 @@ pub struct FindCaptures<'r, 't> {
1061
1056
}
1062
1057
1063
1058
impl < ' r , ' t > Iterator for FindCaptures < ' r , ' t > {
1064
- type Item = Captures < ' t > ;
1059
+ type Item = Captures < ' r , ' t > ;
1065
1060
1066
- fn next ( & mut self ) -> Option < Captures < ' t > > {
1061
+ fn next ( & mut self ) -> Option < Captures < ' r , ' t > > {
1067
1062
if self . last_end > self . search . len ( ) {
1068
1063
return None
1069
1064
}
@@ -1087,7 +1082,11 @@ impl<'r, 't> Iterator for FindCaptures<'r, 't> {
1087
1082
self . last_end = e;
1088
1083
self . skip_next_empty = true ;
1089
1084
}
1090
- Some ( Captures :: new ( self . re , self . search , caps) )
1085
+ Some ( Captures {
1086
+ regex : self . re ,
1087
+ text : self . search ,
1088
+ locs : caps
1089
+ } )
1091
1090
}
1092
1091
}
1093
1092
0 commit comments