Applies the direct-extraction fast path when it preserves the result of `Regex::replacen`; otherwise falls back to the full regex replacement.
(
&mut self,
val: &'a str,
limit: usize,
replacement: &str,
)
| 242 | /// Applies the direct-extraction fast path when it preserves the result of |
| 243 | /// `Regex::replacen`; otherwise falls back to the full regex replacement. |
| 244 | fn replacen<'a>( |
| 245 | &mut self, |
| 246 | val: &'a str, |
| 247 | limit: usize, |
| 248 | replacement: &str, |
| 249 | ) -> Cow<'a, str> { |
| 250 | // If this pattern is not eligible for direct extraction, use the full regex. |
| 251 | let Some(ShortRegex { short_re, locs }) = self.short_re.as_mut() else { |
| 252 | return self.re.replacen(val, limit, replacement); |
| 253 | }; |
| 254 | |
| 255 | // If the shortened regex does not match, the original anchored regex would |
| 256 | // also leave the input unchanged. |
| 257 | if short_re.captures_read(locs, val).is_none() { |
| 258 | return Cow::Borrowed(val); |
| 259 | }; |
| 260 | |
| 261 | // `captures_read` succeeded, so the overall shortened match is present. |
| 262 | let match_end = locs.get(0).unwrap().1; |
| 263 | if memchr(b'\n', &val.as_bytes()[match_end..]).is_some() { |
| 264 | // If there is a newline after the match, we can't use the short |
| 265 | // regex since it won't match across lines. Fall back to the full |
| 266 | // regex replacement. |
| 267 | return self.re.replacen(val, limit, replacement); |
| 268 | }; |
| 269 | // The fast path only applies to `${1}` replacements, so the result is |
| 270 | // either capture group 1 or the empty string if that group did not match. |
| 271 | if let Some((start, end)) = locs.get(1) { |
| 272 | Cow::Borrowed(&val[start..end]) |
| 273 | } else { |
| 274 | Cow::Borrowed("") |
| 275 | } |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | /// For anchored patterns like `^...(capture)....*$` where the replacement |
no test coverage detected