Skip to content

Commit 99ae17d

Browse files
committed
Avoid copying key when it doesn't need escaping
1 parent d2d5f31 commit 99ae17d

1 file changed

Lines changed: 29 additions & 11 deletions

File tree

extractor/src/extractor.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use node_types::{EntryKind, Field, NodeTypeMap, Storage, TypeName};
2+
use std::borrow::Cow;
23
use std::collections::BTreeMap as Map;
34
use std::collections::BTreeSet as Set;
45
use std::fmt;
@@ -192,20 +193,37 @@ pub fn extract(
192193

193194
/// Escapes a string for use in a TRAP key, by replacing special characters with
194195
/// HTML entities.
195-
fn escape_key(s: &str) -> String {
196-
let mut escaped = String::new();
197-
for c in s.chars() {
196+
fn escape_key<'a, S: Into<Cow<'a, str>>>(key: S) -> Cow<'a, str> {
197+
fn needs_escaping(c: char) -> bool {
198198
match c {
199-
'&' => escaped.push_str("&amp;"),
200-
'{' => escaped.push_str("&lbrace;"),
201-
'}' => escaped.push_str("&rbrace;"),
202-
'"' => escaped.push_str("&quot;"),
203-
'@' => escaped.push_str("&commat;"),
204-
'#' => escaped.push_str("&num;"),
205-
_ => escaped.push(c),
199+
'&' => true,
200+
'{' => true,
201+
'}' => true,
202+
'"' => true,
203+
'@' => true,
204+
'#' => true,
205+
_ => false,
206206
}
207207
}
208-
escaped
208+
209+
let key = key.into();
210+
if key.contains(needs_escaping) {
211+
let mut escaped = String::with_capacity(key.len());
212+
for c in key.chars() {
213+
match c {
214+
'&' => escaped.push_str("&amp;"),
215+
'{' => escaped.push_str("&lbrace;"),
216+
'}' => escaped.push_str("&rbrace;"),
217+
'"' => escaped.push_str("&quot;"),
218+
'@' => escaped.push_str("&commat;"),
219+
'#' => escaped.push_str("&num;"),
220+
_ => escaped.push(c),
221+
}
222+
}
223+
Cow::Owned(escaped)
224+
} else {
225+
key
226+
}
209227
}
210228

211229
/// Normalizes the path according the common CodeQL specification. Assumes that

0 commit comments

Comments
 (0)