aboutsummaryrefslogtreecommitdiffstats
path: root/askama_shared
diff options
context:
space:
mode:
authorLibravatar bott <mhpoin@gmail.com>2018-11-03 15:31:53 +0100
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2018-11-05 21:03:31 +0100
commit2ef8258e8fb9a19c7c9d7b93655e1f6d6432c961 (patch)
tree5b46fc7691f3d21191b03d50a06169c942edc046 /askama_shared
parent2721c44a20f3e3af5bb2facdbb77c64652f160a8 (diff)
downloadaskama-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.rs85
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"&lt;");
- }
- b'>' => {
- res.extend(b"&gt;");
- }
- b'&' => {
- res.extend(b"&amp;");
+ 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"&lt;");
+ }
+ b'>' => {
+ res.extend(b"&gt;");
+ }
+ b'&' => {
+ res.extend(b"&amp;");
+ }
+ b'"' => {
+ res.extend(b"&quot;");
+ }
+ b'\'' => {
+ res.extend(b"&#x27;");
+ }
+ b'/' => {
+ res.extend(b"&#x2f;");
+ }
+ _ => res.push(*c),
}
- b'"' => {
- res.extend(b"&quot;");
- }
- b'\'' => {
- res.extend(b"&#x27;");
- }
- b'/' => {
- res.extend(b"&#x2f;");
- }
- _ => 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)]