misc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.alexwennerberg.com/misc
Log | Files | Refs | README | LICENSE

commit f69895c6f93dbc692ce82e51c338a84bd4725ee3
parent fef0790fa2f8b20b554c7e18e9b74952dd2529ae
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Sat, 24 Jul 2021 19:13:34 -0700

Add html escape file

Diffstat:
Ahtmlescape.rs | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+), 0 deletions(-)

diff --git a/htmlescape.rs b/htmlescape.rs @@ -0,0 +1,59 @@ +use std::fmt; +use std::io; +use std::io::Write; + +// Derived from https://github.com/raphlinus/pulldown-cmark/blob/master/src/escape.rs +// Don't use single quotes (') in any of your attributes + +const fn create_html_escape_table() -> [u8; 256] { + let mut table = [0; 256]; + table[b'"' as usize] = 1; + table[b'&' as usize] = 2; + table[b'<' as usize] = 3; + table[b'>' as usize] = 4; + table +} + +static HTML_ESCAPE_TABLE: [u8; 256] = create_html_escape_table(); + +static HTML_ESCAPES: [&str; 5] = ["", "&quot;", "&amp;", "&lt;", "&gt;"]; + +fn main() { + println!( + "<marquee>{name}'s cool webpage</marquee> + <b id=\"1\">I love to hack: {junk}</b>", + name = EscapedHTML("alex"), + junk = EscapedHTML("<script src=\"hackme.js&1\"></script>") + ) +} + +pub struct EscapedHTML<'a>(pub &'a str); + +impl fmt::Display for EscapedHTML<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = self.0; + let bytes = s.as_bytes(); + let mut mark = 0; + let mut i = 0; + while i < s.len() { + match bytes[i..] + .iter() + .position(|&c| HTML_ESCAPE_TABLE[c as usize] != 0) + { + Some(pos) => { + i += pos; + } + None => break, + } + let c = bytes[i]; + let escape = HTML_ESCAPE_TABLE[c as usize]; + let escape_seq = HTML_ESCAPES[escape as usize]; + f.write_str(&s[mark..i])?; + f.write_str(escape_seq)?; + i += 1; + mark = i; // all escaped characters are ASCII + } + f.write_str(&s[mark..])?; + Ok(()) + } +}