Improve performance of html escape
@@ -47,34 +47,27 @@ where
}
}
-fn escapable(b: u8) -> bool {
- match b {
- b'<' | b'>' | b'&' | b'"' | b'\'' | b'/' => true,
- _ => false,
- }
-}
-
+const FLAG: u8 = b'>' - b'"';
pub fn escape(s: String) -> String {
- let mut found = Vec::new();
+ let mut found = None;
for (i, b) in s.as_bytes().iter().enumerate() {
- if escapable(*b) {
- found.push(i);
+ if b.wrapping_sub(b'"') <= FLAG {
+ match *b {
+ b'<' | b'>' | b'&' | b'"' | b'\'' | b'/' => {
+ found = Some(i);
+ break;
}
+ _ => (),
+ };
}
- if found.is_empty() {
- return s;
}
+ if let Some(found) = found {
let bytes = s.as_bytes();
- let max_len = bytes.len() + found.len() * 5;
- let mut res = Vec::<u8>::with_capacity(max_len);
- let mut start = 0;
- for idx in &found {
- if start < *idx {
- res.extend(&bytes[start..*idx]);
- }
- start = *idx + 1;
- match bytes[*idx] {
+ let mut res = Vec::with_capacity(s.len() + 6);
+ res.extend(&bytes[0..found]);
+ for c in bytes[found..].iter() {
+ match *c {
b'<' => {
res.extend(b"&lt;");
}
@@ -93,14 +86,14 @@ pub fn escape(s: String) -> String {
b'/' => {
res.extend(b"&#x2f;");
}
- _ => panic!("incorrect indexing"),
+ _ => res.push(*c),
}
}
- if start < bytes.len() {
- res.extend(&bytes[start..]);
- }
String::from_utf8(res).unwrap()
+ } else {
+ s
+ }
}
#[cfg(test)]
