diff options
author | bott <mhpoin@gmail.com> | 2018-11-03 15:31:53 +0100 |
---|---|---|
committer | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2018-11-05 21:03:31 +0100 |
commit | 2ef8258e8fb9a19c7c9d7b93655e1f6d6432c961 (patch) | |
tree | 5b46fc7691f3d21191b03d50a06169c942edc046 /askama_shared | |
parent | 2721c44a20f3e3af5bb2facdbb77c64652f160a8 (diff) | |
download | askama-2ef8258e8fb9a19c7c9d7b93655e1f6d6432c961.tar.gz askama-2ef8258e8fb9a19c7c9d7b93655e1f6d6432c961.tar.bz2 askama-2ef8258e8fb9a19c7c9d7b93655e1f6d6432c961.zip |
Improve performance of html escape
Diffstat (limited to 'askama_shared')
-rw-r--r-- | askama_shared/src/escaping.rs | 85 |
1 files changed, 39 insertions, 46 deletions
diff --git a/askama_shared/src/escaping.rs b/askama_shared/src/escaping.rs index 93545fd..930dbbe 100644 --- a/askama_shared/src/escaping.rs +++ b/askama_shared/src/escaping.rs @@ -47,60 +47,53 @@ 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; - } - 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] { - b'<' => { - res.extend(b"<"); - } - b'>' => { - res.extend(b">"); - } - b'&' => { - res.extend(b"&"); + if let Some(found) = found { + let bytes = s.as_bytes(); + 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"<"); + } + b'>' => { + res.extend(b">"); + } + b'&' => { + res.extend(b"&"); + } + b'"' => { + res.extend(b"""); + } + b'\'' => { + res.extend(b"'"); + } + b'/' => { + res.extend(b"/"); + } + _ => res.push(*c), } - b'"' => { - res.extend(b"""); - } - b'\'' => { - res.extend(b"'"); - } - b'/' => { - res.extend(b"/"); - } - _ => panic!("incorrect indexing"), } - } - if start < bytes.len() { - res.extend(&bytes[start..]); - } - String::from_utf8(res).unwrap() + String::from_utf8(res).unwrap() + } else { + s + } } #[cfg(test)] |