Skip to content

Commit 730a624

Browse files
perf: avoid allocating new strings when no characters need to be escaped or removed
- Added fast-path check in `escape_chars` to detect early if escaping is needed. - Added fast-path `contains` check in `replacements` to prevent regex deep cloning and unprintable chars removal when not needed.
1 parent 212b453 commit 730a624

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

src/template.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -407,13 +407,19 @@ impl<'a> Template<'a> {
407407
}
408408

409409
fn replacements(&mut self) {
410-
lazy_static::lazy_static! {
411-
static ref RE: Regex = Regex::new(&format!(r"\s*{}", BACKSPACE)).expect("Failed to create regex with constant pattern");
410+
if self.out.contains(BACKSPACE) {
411+
lazy_static::lazy_static! {
412+
static ref RE: Regex = Regex::new(&format!(r"\s*{}", BACKSPACE)).expect("Failed to create regex with constant pattern");
413+
}
414+
if let std::borrow::Cow::Owned(s) = RE.replace_all(&self.out, "") {
415+
self.out = s;
416+
}
412417
}
413-
self.out = RE.replace_all(&self.out, "").to_string();
414418

415419
// UNPRINTABLE should be substituted after BACKSPACE
416-
self.out = self.out.replace(UNPRINTABLE, "");
420+
if self.out.contains(UNPRINTABLE) {
421+
self.out = self.out.replace(UNPRINTABLE, "");
422+
}
417423
}
418424

419425
/// Retrieves the status code.

src/utils.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,16 @@ pub fn find_tag_position(text: &str, tag: &str) -> Option<usize> {
596596
/// assert_eq!(escaped, r#"Hello, &lt;world&gt; &amp; &quot;friends&quot;! &#123;example&#125;"#);
597597
/// ```
598598
pub fn escape_chars(input: &str, escape_braces: bool) -> String {
599+
let needs_escape = input.chars().any(|c| match c {
600+
'&' | '<' | '>' | '"' | '\'' | '/' => true,
601+
'{' | '}' if escape_braces => true,
602+
_ => false,
603+
});
604+
605+
if !needs_escape {
606+
return input.to_string();
607+
}
608+
599609
let mut result = String::with_capacity(input.len() * 2);
600610

601611
for c in input.chars() {

0 commit comments

Comments
 (0)