|
1 |
| -use aho_corasick::AhoCorasickBuilder; |
| 1 | +use aho_corasick::{AhoCorasick, AhoCorasickBuilder}; |
2 | 2 | use core::fmt::{self, Display};
|
3 | 3 | use core::str::FromStr;
|
4 | 4 | use std::env;
|
@@ -344,33 +344,46 @@ pub fn update_text_region_fn(
|
344 | 344 | move |path, src, dst| update_text_region(path, start, end, src, dst, &mut insert)
|
345 | 345 | }
|
346 | 346 |
|
347 |
| -/// Replace substrings if they aren't bordered by identifier characters. Returns `None` if there |
348 |
| -/// were no replacements. |
349 | 347 | #[must_use]
|
350 |
| -pub fn replace_ident_like(replacements: &[(&str, &str)], src: &str, dst: &mut String) -> UpdateStatus { |
351 |
| - fn is_ident_char(c: u8) -> bool { |
352 |
| - matches!(c, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_') |
353 |
| - } |
| 348 | +pub fn is_ident_char(c: u8) -> bool { |
| 349 | + matches!(c, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_') |
| 350 | +} |
354 | 351 |
|
355 |
| - let searcher = AhoCorasickBuilder::new() |
356 |
| - .match_kind(aho_corasick::MatchKind::LeftmostLongest) |
357 |
| - .build(replacements.iter().map(|&(x, _)| x.as_bytes())) |
358 |
| - .unwrap(); |
| 352 | +pub struct StringReplacer<'a> { |
| 353 | + searcher: AhoCorasick, |
| 354 | + replacements: &'a [(&'a str, &'a str)], |
| 355 | +} |
| 356 | +impl<'a> StringReplacer<'a> { |
| 357 | + #[must_use] |
| 358 | + pub fn new(replacements: &'a [(&'a str, &'a str)]) -> Self { |
| 359 | + Self { |
| 360 | + searcher: AhoCorasickBuilder::new() |
| 361 | + .match_kind(aho_corasick::MatchKind::LeftmostLongest) |
| 362 | + .build(replacements.iter().map(|&(x, _)| x)) |
| 363 | + .unwrap(), |
| 364 | + replacements, |
| 365 | + } |
| 366 | + } |
359 | 367 |
|
360 |
| - let mut pos = 0; |
361 |
| - let mut changed = false; |
362 |
| - for m in searcher.find_iter(src) { |
363 |
| - if !is_ident_char(src.as_bytes().get(m.start().wrapping_sub(1)).copied().unwrap_or(0)) |
364 |
| - && !is_ident_char(src.as_bytes().get(m.end()).copied().unwrap_or(0)) |
365 |
| - { |
366 |
| - dst.push_str(&src[pos..m.start()]); |
367 |
| - dst.push_str(replacements[m.pattern()].1); |
368 |
| - pos = m.end(); |
369 |
| - changed = true; |
| 368 | + /// Replace substrings if they aren't bordered by identifier characters. |
| 369 | + pub fn replace_ident_fn(&self) -> impl Fn(&Path, &str, &mut String) -> UpdateStatus { |
| 370 | + move |_, src, dst| { |
| 371 | + let mut pos = 0; |
| 372 | + let mut changed = false; |
| 373 | + for m in self.searcher.find_iter(src) { |
| 374 | + if !is_ident_char(src.as_bytes().get(m.start().wrapping_sub(1)).copied().unwrap_or(0)) |
| 375 | + && !is_ident_char(src.as_bytes().get(m.end()).copied().unwrap_or(0)) |
| 376 | + { |
| 377 | + changed = true; |
| 378 | + dst.push_str(&src[pos..m.start()]); |
| 379 | + dst.push_str(self.replacements[m.pattern()].1); |
| 380 | + pos = m.end(); |
| 381 | + } |
| 382 | + } |
| 383 | + dst.push_str(&src[pos..]); |
| 384 | + UpdateStatus::from_changed(changed) |
370 | 385 | }
|
371 | 386 | }
|
372 |
| - dst.push_str(&src[pos..]); |
373 |
| - UpdateStatus::from_changed(changed) |
374 | 387 | }
|
375 | 388 |
|
376 | 389 | #[expect(clippy::must_use_candidate)]
|
|
0 commit comments