another_html_builder/
content.rs1const CONTENT_ESCAPE: [char; 6] = ['&', '<', '>', '"', '\'', '/'];
4
5pub struct EscapedContent<'a>(pub &'a str);
15
16impl std::fmt::Display for EscapedContent<'_> {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 if self.0.is_empty() {
19 return Ok(());
20 }
21 let mut start: usize = 0;
22 while let Some(index) = self.0[start..].find(CONTENT_ESCAPE) {
23 if index > 0 {
24 f.write_str(&self.0[start..(start + index)])?;
25 }
26 let begin = start + index;
27 debug_assert!(start <= begin);
28 let end = begin + 1;
29 debug_assert!(begin < self.0.len());
30 debug_assert!(begin < end);
31 debug_assert!(end <= self.0.len());
32 match &self.0[begin..end] {
33 "&" => f.write_str("&")?,
34 "<" => f.write_str("<")?,
35 ">" => f.write_str(">")?,
36 "\"" => f.write_str(""")?,
37 "'" => f.write_str("'")?,
38 "/" => f.write_str("/")?,
39 other => f.write_str(other)?,
40 };
41 start = end;
42 debug_assert!(start <= self.0.len());
43 }
44 f.write_str(&self.0[start..])?;
45 Ok(())
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 #[test_case::test_case("hello world", "hello world"; "without character to escape")]
52 #[test_case::test_case("a\"b", "a"b"; "with special in the middle")]
53 #[test_case::test_case("\"a", ""a"; "with special at the beginning")]
54 #[test_case::test_case("a\"", "a""; "with special at the end")]
55 fn escaping_content(input: &str, expected: &str) {
56 assert_eq!(format!("{}", super::EscapedContent(input)), expected);
57 }
58}