diff options
Diffstat (limited to '')
-rw-r--r-- | askama_shared/src/escaping.rs | 52 |
1 files changed, 20 insertions, 32 deletions
diff --git a/askama_shared/src/escaping.rs b/askama_shared/src/escaping.rs index 8bb8f0b..6390f0c 100644 --- a/askama_shared/src/escaping.rs +++ b/askama_shared/src/escaping.rs @@ -55,46 +55,34 @@ pub struct Escaped<'a> { bytes: &'a [u8], } -enum State { - Empty, - Unescaped(usize), +macro_rules! escaping_body { + ($state:ident, $i:ident, $fmt:ident, $_self:ident, $quote:expr) => {{ + if $state < $i { + $fmt.write_str(unsafe { str::from_utf8_unchecked(&$_self.bytes[$state..$i]) })?; + } + $fmt.write_str($quote)?; + $state = $i + 1; + }}; } impl<'a> ::std::fmt::Display for Escaped<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - use self::State::*; - let mut state = Empty; + let mut state = 0; for (i, b) in self.bytes.iter().enumerate() { - let next = if b.wrapping_sub(b'"') <= FLAG { + if b.wrapping_sub(b'"') <= FLAG { match *b { - b'<' => Some("<"), - b'>' => Some(">"), - b'&' => Some("&"), - b'"' => Some("""), - b'\'' => Some("'"), - b'/' => Some("/"), - _ => None, - } - } else { - None - }; - state = match (state, next) { - (Empty, None) => Unescaped(i), - (s @ Unescaped(_), None) => s, - (Empty, Some(escaped)) => { - fmt.write_str(escaped)?; - Empty - } - (Unescaped(start), Some(escaped)) => { - fmt.write_str(unsafe { str::from_utf8_unchecked(&self.bytes[start..i]) })?; - fmt.write_str(escaped)?; - Empty + b'<' => escaping_body!(state, i, fmt, self, "<"), + b'>' => escaping_body!(state, i, fmt, self, ">"), + b'&' => escaping_body!(state, i, fmt, self, "&"), + b'"' => escaping_body!(state, i, fmt, self, """), + b'\'' => escaping_body!(state, i, fmt, self, "'"), + b'/' => escaping_body!(state, i, fmt, self, "/"), + _ => (), } - }; - } - if let Unescaped(start) = state { - fmt.write_str(unsafe { str::from_utf8_unchecked(&self.bytes[start..]) })?; + } } + + fmt.write_str(unsafe { str::from_utf8_unchecked(&self.bytes[state..]) })?; Ok(()) } } |