diff options
Diffstat (limited to '')
| -rw-r--r-- | askama_shared/src/escaping.rs | 50 | ||||
| -rw-r--r-- | askama_shared/src/filters/mod.rs | 46 | ||||
| -rw-r--r-- | askama_shared/src/lib.rs | 1 | 
3 files changed, 54 insertions, 43 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"); +    } +} diff --git a/askama_shared/src/filters/mod.rs b/askama_shared/src/filters/mod.rs index 1f5fa42..e6a5858 100644 --- a/askama_shared/src/filters/mod.rs +++ b/askama_shared/src/filters/mod.rs @@ -13,6 +13,7 @@ pub use self::json::json;  use std::fmt; +use escaping;  use super::Result; @@ -33,44 +34,10 @@ pub const BUILT_IN_FILTERS: [&str; 9] = [  ]; -fn escapable(b: &u8) -> bool { -    *b == b'<' || *b == b'>' || *b == b'&' -} -  /// Escapes `&`, `<` and `>` in strings  pub fn escape(s: &fmt::Display) -> Result<String> {      let s = format!("{}", s); -    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 Ok(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..]); -    } - -    Ok(String::from_utf8(res).unwrap()) +    Ok(escaping::escape(s))  }  /// Alias for the `escape()` filter @@ -135,18 +102,11 @@ pub fn join<T, I, S>(input: I, separator: S) -> Result<String>      Ok(rv)  } +  #[cfg(test)]  mod tests {      use super::*;      #[test] -    fn test_escape() { -        assert_eq!(escape(&"").unwrap(), ""); -        assert_eq!(escape(&"<&>").unwrap(), "<&>"); -        assert_eq!(escape(&"bla&").unwrap(), "bla&"); -        assert_eq!(escape(&"<foo").unwrap(), "<foo"); -    } - -    #[test]      fn test_lower() {          assert_eq!(lower(&"Foo").unwrap(), "foo");          assert_eq!(lower(&"FOO").unwrap(), "foo"); diff --git a/askama_shared/src/lib.rs b/askama_shared/src/lib.rs index 301ca13..35e779c 100644 --- a/askama_shared/src/lib.rs +++ b/askama_shared/src/lib.rs @@ -16,6 +16,7 @@ pub mod path;  pub use parser::parse;  pub use generator::generate; +mod escaping;  mod generator;  mod parser; | 
