write_html/escapes.rs
1/*!
2Provides `StringEscaper` and `HtmlEscaper` to escape strings for use in string literals and HTML elements respectively.
3*/
4
5use std::fmt::Write;
6
7
8
9/// Escapes a string for the inside of a string literal.
10///
11/// # Examples
12/// ```
13/// use std::fmt::Write;
14/// use write_html::escapes::StringEscaper;
15///
16/// let mut s = String::new();
17/// let mut escaper = StringEscaper::new(&mut s);
18/// escaper.write_str("Hello, \"world\"").unwrap();
19/// assert_eq!(s, "Hello, \\\"world\\\"");
20/// ```
21pub struct StringEscaper<'a, W: Write> {
22 w: &'a mut W,
23}
24
25impl<'a, W: Write> StringEscaper<'a, W> {
26 /// Creates a new `StringEscaper` that will write to `w`.
27 ///
28 /// # Arguments
29 /// * `w` - The `Write` to write to.
30 pub fn new(w: &'a mut W) -> Self {
31 Self { w }
32 }
33}
34
35impl<'a, W: Write> Write for StringEscaper<'a, W> {
36 fn write_str(&mut self, s: &str) -> std::fmt::Result {
37 for c in s.chars() {
38 match c {
39 '"' => write!(self.w, "\\\"")?,
40 '\'' => write!(self.w, "\\\'")?,
41 '\\' => write!(self.w, "\\\\")?,
42 '\r' => write!(self.w, "\\r")?,
43 '\n' => write!(self.w, "\\n")?,
44 '\t' => write!(self.w, "\\t")?,
45 // TODO ...
46 _ => write!(self.w, "{}", c)?,
47 };
48 }
49
50 Ok(())
51 }
52}
53
54/// Escapes a string for the inside of an HTML element.
55///
56/// # Examples
57/// ```
58/// use std::fmt::Write;
59/// use write_html::escapes::HtmlEscaper;
60///
61/// let mut s = String::new();
62/// let mut escaper = HtmlEscaper::new(&mut s);
63/// escaper.write_str("<h1>H1</h1>").unwrap();
64/// assert_eq!(s, "<h1>H1</h1>");
65/// ```
66pub struct HtmlEscaper<'a, W: Write> {
67 w: &'a mut W,
68}
69
70impl<'a, W: Write> HtmlEscaper<'a, W> {
71 /// Creates a new `HtmlEscaper` that will write to `w`.
72 ///
73 /// # Arguments
74 /// * `w` - The `Write` to write to.
75 pub fn new(w: &'a mut W) -> Self {
76 Self { w }
77 }
78}
79
80impl<'a, W: Write> Write for HtmlEscaper<'a, W> {
81 fn write_str(&mut self, s: &str) -> std::fmt::Result {
82 for c in s.chars() {
83 match c {
84 '<' => write!(self.w, "<")?,
85 '>' => write!(self.w, ">")?,
86 '&' => write!(self.w, "&")?,
87 '\n' => write!(self.w, "<br>")?,
88 // TODO ...
89 _ => write!(self.w, "{}", c)?,
90 };
91 }
92
93 Ok(())
94 }
95}