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
@@ -394,10 +394,14 @@ impl Regex {
394
394
///
395
395
/// The `0`th capture group is always unnamed, so it must always be
396
396
/// accessed with `at(0)` or `[0]`.
397
- pub fn captures < ' t > ( & self , text : & ' t str ) -> Option < Captures < ' t > > {
398
- let mut caps = self . alloc_captures ( ) ;
399
- if exec ( self , & mut caps, text, 0 ) {
400
- Some ( Captures :: new ( self , text, caps) )
397
+ pub fn captures < ' r , ' t > ( & ' r self , text : & ' t str ) -> Option < Captures < ' r , ' t > > {
398
+ let mut locs = self . alloc_captures ( ) ;
399
+ if exec ( self , & mut locs, text, 0 ) {
400
+ Some ( Captures {
401
+ regex : self ,
402
+ text : text,
403
+ locs : locs,
404
+ } )
401
405
} else {
402
406
None
403
407
}
@@ -815,37 +819,13 @@ impl<'r, 't> Iterator for RegexSplitsN<'r, 't> {
815
819
/// Positions returned from a capture group are always byte indices.
816
820
///
817
821
/// `'t` is the lifetime of the matched text.
818
- pub struct Captures < ' t > {
822
+ pub struct Captures < ' r , ' t > {
823
+ regex : & ' r Regex ,
819
824
text : & ' t str ,
820
825
locs : Vec < Option < usize > > ,
821
- named : Option < HashMap < String , usize > > ,
822
826
}
823
827
824
- impl < ' t > Captures < ' t > {
825
- fn new (
826
- re : & Regex ,
827
- search : & ' t str ,
828
- locs : Vec < Option < usize > > ,
829
- ) -> Captures < ' t > {
830
- let named =
831
- if re. captures_len ( ) == 0 {
832
- None
833
- } else {
834
- let mut named = HashMap :: new ( ) ;
835
- for ( i, name) in re. capture_names ( ) . enumerate ( ) {
836
- if let Some ( name) = name {
837
- named. insert ( name. to_owned ( ) , i) ;
838
- }
839
- }
840
- Some ( named)
841
- } ;
842
- Captures {
843
- text : search,
844
- locs : locs,
845
- named : named,
846
- }
847
- }
848
-
828
+ impl < ' r , ' t > Captures < ' r , ' t > {
849
829
/// Returns the start and end positions of the Nth capture group.
850
830
/// Returns `None` if `i` is not a valid capture group or if the capture
851
831
/// group did not match anything.
@@ -874,37 +854,49 @@ impl<'t> Captures<'t> {
874
854
/// `name` isn't a valid capture group or didn't match anything, then
875
855
/// `None` is returned.
876
856
pub fn name ( & self , name : & str ) -> Option < & ' t str > {
877
- match self . named {
878
- None => None ,
879
- Some ( ref h) => {
880
- match h. get ( name) {
881
- None => None ,
882
- Some ( i) => self . at ( * i) ,
857
+ match * self . regex {
858
+ Regex :: Native ( ExNative { ref groups, .. } ) => {
859
+ match groups. binary_search_by ( |& ( n, _) | n. cmp ( name) ) {
860
+ Ok ( i) => self . at ( groups[ i] . 1 ) ,
861
+ Err ( _) => None
883
862
}
884
- }
863
+ } ,
864
+ Regex :: Dynamic ( Program { ref named_groups, .. } ) => {
865
+ named_groups. get ( name) . and_then ( |i| self . at ( * i) )
866
+ } ,
885
867
}
886
868
}
887
869
888
870
/// Creates an iterator of all the capture groups in order of appearance
889
871
/// in the regular expression.
890
- pub fn iter ( & ' t self ) -> SubCaptures < ' t > {
872
+ pub fn iter < ' c > ( & ' c self ) -> SubCaptures < ' c , ' r , ' t > {
891
873
SubCaptures { idx : 0 , caps : self , }
892
874
}
893
875
894
876
/// Creates an iterator of all the capture group positions in order of
895
877
/// appearance in the regular expression. Positions are byte indices
896
878
/// in terms of the original string matched.
897
- pub fn iter_pos ( & ' t self ) -> SubCapturesPos < ' t > {
879
+ pub fn iter_pos < ' c > ( & ' c self ) -> SubCapturesPos < ' c , ' r , ' t > {
898
880
SubCapturesPos { idx : 0 , caps : self , }
899
881
}
900
882
901
883
/// Creates an iterator of all named groups as an tuple with the group
902
884
/// name and the value. The iterator returns these values in arbitrary
903
885
/// order.
904
- pub fn iter_named ( & ' t self ) -> SubCapturesNamed < ' t > {
886
+ pub fn iter_named < ' c > ( & ' c self ) -> SubCapturesNamed < ' c , ' r , ' t > {
887
+ let iter = match * self . regex {
888
+ Regex :: Native ( ExNative { ref groups, .. } ) => {
889
+ Box :: new ( groups. iter ( ) . map ( |& v| v) )
890
+ as Box < Iterator < Item =( & ' r str , usize ) > + ' r >
891
+ } ,
892
+ Regex :: Dynamic ( Program { ref named_groups, .. } ) => {
893
+ Box :: new ( named_groups. iter ( ) . map ( |( s, i) | ( & s[ ..] , * i) ) )
894
+ as Box < Iterator < Item =( & ' r str , usize ) > + ' r >
895
+ } ,
896
+ } ;
905
897
SubCapturesNamed {
906
898
caps : self ,
907
- inner : self . named . as_ref ( ) . map ( |n| n . iter ( ) ) ,
899
+ inner : iter
908
900
}
909
901
}
910
902
@@ -948,7 +940,7 @@ impl<'t> Captures<'t> {
948
940
///
949
941
/// # Panics
950
942
/// If there is no group at the given index.
951
- impl < ' t > Index < usize > for Captures < ' t > {
943
+ impl < ' r , ' t > Index < usize > for Captures < ' r , ' t > {
952
944
953
945
type Output = str ;
954
946
@@ -962,7 +954,7 @@ impl<'t> Index<usize> for Captures<'t> {
962
954
///
963
955
/// # Panics
964
956
/// If there is no group named by the given value.
965
- impl < ' t > Index < & ' t str > for Captures < ' t > {
957
+ impl < ' r , ' t > Index < & ' t str > for Captures < ' r , ' t > {
966
958
967
959
type Output = str ;
968
960
@@ -979,12 +971,12 @@ impl<'t> Index<&'t str> for Captures<'t> {
979
971
/// expression.
980
972
///
981
973
/// `'t` is the lifetime of the matched text.
982
- pub struct SubCaptures < ' t > {
974
+ pub struct SubCaptures < ' c , ' r : ' c , ' t : ' c > {
983
975
idx : usize ,
984
- caps : & ' t Captures < ' t > ,
976
+ caps : & ' c Captures < ' r , ' t > ,
985
977
}
986
978
987
- impl < ' t > Iterator for SubCaptures < ' t > {
979
+ impl < ' c , ' r , ' t > Iterator for SubCaptures < ' c , ' r , ' t > {
988
980
type Item = Option < & ' t str > ;
989
981
990
982
fn next ( & mut self ) -> Option < Option < & ' t str > > {
@@ -1003,12 +995,12 @@ impl<'t> Iterator for SubCaptures<'t> {
1003
995
/// Positions are byte indices in terms of the original string matched.
1004
996
///
1005
997
/// `'t` is the lifetime of the matched text.
1006
- pub struct SubCapturesPos < ' t > {
998
+ pub struct SubCapturesPos < ' c , ' r : ' c , ' t : ' c > {
1007
999
idx : usize ,
1008
- caps : & ' t Captures < ' t > ,
1000
+ caps : & ' c Captures < ' r , ' t > ,
1009
1001
}
1010
1002
1011
- impl < ' t > Iterator for SubCapturesPos < ' t > {
1003
+ impl < ' c , ' r , ' t > Iterator for SubCapturesPos < ' c , ' r , ' t > {
1012
1004
type Item = Option < ( usize , usize ) > ;
1013
1005
1014
1006
fn next ( & mut self ) -> Option < Option < ( usize , usize ) > > {
@@ -1025,17 +1017,17 @@ impl<'t> Iterator for SubCapturesPos<'t> {
1025
1017
/// name and the value.
1026
1018
///
1027
1019
/// `'t` is the lifetime of the matched text.
1028
- pub struct SubCapturesNamed < ' t > {
1029
- caps : & ' t Captures < ' t > ,
1030
- inner : Option < Iter < ' t , String , usize > > ,
1020
+ pub struct SubCapturesNamed < ' c , ' r : ' c , ' t : ' c > {
1021
+ caps : & ' c Captures < ' r , ' t > ,
1022
+ inner : Box < Iterator < Item = ( & ' r str , usize ) > + ' r > ,
1031
1023
}
1032
1024
1033
- impl < ' t > Iterator for SubCapturesNamed < ' t > {
1034
- type Item = ( & ' t str , Option < & ' t str > ) ;
1025
+ impl < ' c , ' r , ' t > Iterator for SubCapturesNamed < ' c , ' r , ' t > {
1026
+ type Item = ( & ' r str , Option < & ' t str > ) ;
1035
1027
1036
- fn next ( & mut self ) -> Option < ( & ' t str , Option < & ' t str > ) > {
1037
- match self . inner . as_mut ( ) . map_or ( None , |it| it . next ( ) ) {
1038
- Some ( ( name, pos) ) => Some ( ( name, self . caps . at ( * pos) ) ) ,
1028
+ fn next ( & mut self ) -> Option < ( & ' r str , Option < & ' t str > ) > {
1029
+ match self . inner . next ( ) {
1030
+ Some ( ( name, pos) ) => Some ( ( name, self . caps . at ( pos) ) ) ,
1039
1031
None => None
1040
1032
}
1041
1033
}
@@ -1056,9 +1048,9 @@ pub struct FindCaptures<'r, 't> {
1056
1048
}
1057
1049
1058
1050
impl < ' r , ' t > Iterator for FindCaptures < ' r , ' t > {
1059
- type Item = Captures < ' t > ;
1051
+ type Item = Captures < ' r , ' t > ;
1060
1052
1061
- fn next ( & mut self ) -> Option < Captures < ' t > > {
1053
+ fn next ( & mut self ) -> Option < Captures < ' r , ' t > > {
1062
1054
if self . last_end > self . search . len ( ) {
1063
1055
return None
1064
1056
}
0 commit comments