diff options
author | 2017-09-04 20:37:05 +0200 | |
---|---|---|
committer | 2017-09-04 20:37:05 +0200 | |
commit | fdbe45ec60d628a014a1414b1ea8588ba4f9573c (patch) | |
tree | c70494514b5816f5ff4d5a6459c292e4ab7653ca /askama_shared/src/escaping.rs | |
parent | 23279c3bce4b0b21504f20e76b5cdfa783d4394c (diff) | |
download | askama-fdbe45ec60d628a014a1414b1ea8588ba4f9573c.tar.gz askama-fdbe45ec60d628a014a1414b1ea8588ba4f9573c.tar.bz2 askama-fdbe45ec60d628a014a1414b1ea8588ba4f9573c.zip |
Move escaping algorithm into a separate module
Diffstat (limited to '')
-rw-r--r-- | askama_shared/src/escaping.rs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/askama_shared/src/escaping.rs b/askama_shared/src/escaping.rs new file mode 100644 index 0000000..54f58e4 --- /dev/null +++ b/askama_shared/src/escaping.rs @@ -0,0 +1,50 @@ +fn escapable(b: &u8) -> bool { + *b == b'<' || *b == b'>' || *b == b'&' +} + +pub fn escape(s: String) -> String { + let mut found = Vec::new(); + for (i, b) in s.as_bytes().iter().enumerate() { + if escapable(b) { + found.push(i); + } + } + if found.is_empty() { + return s; + } + + let bytes = s.as_bytes(); + let max_len = bytes.len() + found.len() * 3; + 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"&"); }, + _ => panic!("incorrect indexing"), + } + } + if start < bytes.len() - 1 { + res.extend(&bytes[start..]); + } + + String::from_utf8(res).unwrap() +} + + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_escape() { + assert_eq!(escape("".to_string()), ""); + assert_eq!(escape("<&>".to_string()), "<&>"); + assert_eq!(escape("bla&".to_string()), "bla&"); + assert_eq!(escape("<foo".to_string()), "<foo"); + } +} |