aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askama_shared/src/escaping.rs50
-rw-r--r--askama_shared/src/filters/mod.rs46
-rw-r--r--askama_shared/src/lib.rs1
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"&lt;"); },
+ b'>' => { res.extend(b"&gt;"); },
+ b'&' => { res.extend(b"&amp;"); },
+ _ => 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()), "&lt;&amp;&gt;");
+ assert_eq!(escape("bla&".to_string()), "bla&amp;");
+ assert_eq!(escape("<foo".to_string()), "&lt;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"&lt;"); },
- b'>' => { res.extend(b"&gt;"); },
- b'&' => { res.extend(b"&amp;"); },
- _ => 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(), "&lt;&amp;&gt;");
- assert_eq!(escape(&"bla&").unwrap(), "bla&amp;");
- assert_eq!(escape(&"<foo").unwrap(), "&lt;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;