@@ -845,6 +845,14 @@ impl ReverseAnchored {
845
845
) ;
846
846
return Err ( core) ;
847
847
}
848
+ // Note that the caller can still request an anchored search even when
849
+ // the regex isn't anchored at the start. We detect that case in the
850
+ // search routines below and just fallback to the core engine. This
851
+ // is fine because both searches are anchored. It's just a matter of
852
+ // picking one. Falling back to the core engine is a little simpler,
853
+ // since if we used the reverse anchored approach, we'd have to add an
854
+ // extra check to ensure the match reported starts at the place where
855
+ // the caller requested the search to start.
848
856
if core. info . is_always_anchored_start ( ) {
849
857
debug ! (
850
858
"skipping reverse anchored optimization because \
@@ -930,6 +938,9 @@ impl Strategy for ReverseAnchored {
930
938
931
939
#[ cfg_attr( feature = "perf-inline" , inline( always) ) ]
932
940
fn search ( & self , cache : & mut Cache , input : & Input < ' _ > ) -> Option < Match > {
941
+ if input. get_anchored ( ) . is_anchored ( ) {
942
+ return self . core . search ( cache, input) ;
943
+ }
933
944
match self . try_search_half_anchored_rev ( cache, input) {
934
945
Err ( _err) => {
935
946
trace ! ( "fast reverse anchored search failed: {}" , _err) ;
@@ -948,6 +959,9 @@ impl Strategy for ReverseAnchored {
948
959
cache : & mut Cache ,
949
960
input : & Input < ' _ > ,
950
961
) -> Option < HalfMatch > {
962
+ if input. get_anchored ( ) . is_anchored ( ) {
963
+ return self . core . search_half ( cache, input) ;
964
+ }
951
965
match self . try_search_half_anchored_rev ( cache, input) {
952
966
Err ( _err) => {
953
967
trace ! ( "fast reverse anchored search failed: {}" , _err) ;
@@ -973,6 +987,9 @@ impl Strategy for ReverseAnchored {
973
987
input : & Input < ' _ > ,
974
988
slots : & mut [ Option < NonMaxUsize > ] ,
975
989
) -> Option < PatternID > {
990
+ if input. get_anchored ( ) . is_anchored ( ) {
991
+ return self . core . search_slots ( cache, input, slots) ;
992
+ }
976
993
match self . try_search_half_anchored_rev ( cache, input) {
977
994
Err ( _err) => {
978
995
trace ! ( "fast reverse anchored search failed: {}" , _err) ;
@@ -1034,6 +1051,13 @@ impl ReverseSuffix {
1034
1051
// requires a reverse scan after a literal match to confirm or reject
1035
1052
// the match. (Although, in the case of confirmation, it then needs to
1036
1053
// do another forward scan to find the end position.)
1054
+ //
1055
+ // Note that the caller can still request an anchored search even
1056
+ // when the regex isn't anchored. We detect that case in the search
1057
+ // routines below and just fallback to the core engine. Currently this
1058
+ // optimization assumes all searches are unanchored, so if we do want
1059
+ // to enable this optimization for anchored searches, it will need a
1060
+ // little work to support it.
1037
1061
if core. info . is_always_anchored_start ( ) {
1038
1062
debug ! (
1039
1063
"skipping reverse suffix optimization because \
@@ -1211,6 +1235,9 @@ impl Strategy for ReverseSuffix {
1211
1235
1212
1236
#[ cfg_attr( feature = "perf-inline" , inline( always) ) ]
1213
1237
fn search ( & self , cache : & mut Cache , input : & Input < ' _ > ) -> Option < Match > {
1238
+ if input. get_anchored ( ) . is_anchored ( ) {
1239
+ return self . core . search ( cache, input) ;
1240
+ }
1214
1241
match self . try_search_half_start ( cache, input) {
1215
1242
Err ( RetryError :: Quadratic ( _err) ) => {
1216
1243
trace ! ( "reverse suffix optimization failed: {}" , _err) ;
@@ -1255,6 +1282,9 @@ impl Strategy for ReverseSuffix {
1255
1282
cache : & mut Cache ,
1256
1283
input : & Input < ' _ > ,
1257
1284
) -> Option < HalfMatch > {
1285
+ if input. get_anchored ( ) . is_anchored ( ) {
1286
+ return self . core . search_half ( cache, input) ;
1287
+ }
1258
1288
match self . try_search_half_start ( cache, input) {
1259
1289
Err ( RetryError :: Quadratic ( _err) ) => {
1260
1290
trace ! ( "reverse suffix half optimization failed: {}" , _err) ;
@@ -1309,6 +1339,9 @@ impl Strategy for ReverseSuffix {
1309
1339
input : & Input < ' _ > ,
1310
1340
slots : & mut [ Option < NonMaxUsize > ] ,
1311
1341
) -> Option < PatternID > {
1342
+ if input. get_anchored ( ) . is_anchored ( ) {
1343
+ return self . core . search_slots ( cache, input, slots) ;
1344
+ }
1312
1345
if !self . core . is_capture_search_needed ( slots. len ( ) ) {
1313
1346
trace ! ( "asked for slots unnecessarily, trying fast path" ) ;
1314
1347
let m = self . search ( cache, input) ?;
@@ -1396,6 +1429,13 @@ impl ReverseInner {
1396
1429
// or when the literal scan matches. If it matches, then confirming the
1397
1430
// match requires a reverse scan followed by a forward scan to confirm
1398
1431
// or reject, which is a fair bit of work.
1432
+ //
1433
+ // Note that the caller can still request an anchored search even
1434
+ // when the regex isn't anchored. We detect that case in the search
1435
+ // routines below and just fallback to the core engine. Currently this
1436
+ // optimization assumes all searches are unanchored, so if we do want
1437
+ // to enable this optimization for anchored searches, it will need a
1438
+ // little work to support it.
1399
1439
if core. info . is_always_anchored_start ( ) {
1400
1440
debug ! (
1401
1441
"skipping reverse inner optimization because \
@@ -1635,6 +1675,9 @@ impl Strategy for ReverseInner {
1635
1675
1636
1676
#[ cfg_attr( feature = "perf-inline" , inline( always) ) ]
1637
1677
fn search ( & self , cache : & mut Cache , input : & Input < ' _ > ) -> Option < Match > {
1678
+ if input. get_anchored ( ) . is_anchored ( ) {
1679
+ return self . core . search ( cache, input) ;
1680
+ }
1638
1681
match self . try_search_full ( cache, input) {
1639
1682
Err ( RetryError :: Quadratic ( _err) ) => {
1640
1683
trace ! ( "reverse inner optimization failed: {}" , _err) ;
@@ -1654,6 +1697,9 @@ impl Strategy for ReverseInner {
1654
1697
cache : & mut Cache ,
1655
1698
input : & Input < ' _ > ,
1656
1699
) -> Option < HalfMatch > {
1700
+ if input. get_anchored ( ) . is_anchored ( ) {
1701
+ return self . core . search_half ( cache, input) ;
1702
+ }
1657
1703
match self . try_search_full ( cache, input) {
1658
1704
Err ( RetryError :: Quadratic ( _err) ) => {
1659
1705
trace ! ( "reverse inner half optimization failed: {}" , _err) ;
@@ -1675,6 +1721,9 @@ impl Strategy for ReverseInner {
1675
1721
input : & Input < ' _ > ,
1676
1722
slots : & mut [ Option < NonMaxUsize > ] ,
1677
1723
) -> Option < PatternID > {
1724
+ if input. get_anchored ( ) . is_anchored ( ) {
1725
+ return self . core . search_slots ( cache, input, slots) ;
1726
+ }
1678
1727
if !self . core . is_capture_search_needed ( slots. len ( ) ) {
1679
1728
trace ! ( "asked for slots unnecessarily, trying fast path" ) ;
1680
1729
let m = self . search ( cache, input) ?;
0 commit comments