privatus_analytics/
html.rs1use std::fmt;
2
3#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
10pub struct SafeHtml(String);
11
12impl SafeHtml {
13 pub fn from_trusted(html: impl Into<String>) -> Self {
15 SafeHtml(html.into())
16 }
17
18 pub fn as_str(&self) -> &str {
20 &self.0
21 }
22
23 pub fn into_string(self) -> String {
25 self.0
26 }
27
28 pub fn is_empty(&self) -> bool {
30 self.0.is_empty()
31 }
32}
33
34impl fmt::Display for SafeHtml {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 f.write_str(&self.0)
37 }
38}
39
40impl AsRef<str> for SafeHtml {
41 fn as_ref(&self) -> &str {
42 &self.0
43 }
44}
45
46impl From<SafeHtml> for String {
47 fn from(html: SafeHtml) -> String {
48 html.0
49 }
50}
51
52pub fn escape_html(text: &str) -> String {
56 let mut out = String::with_capacity(text.len());
57 for ch in text.chars() {
58 match ch {
59 '&' => out.push_str("&"),
60 '<' => out.push_str("<"),
61 '>' => out.push_str(">"),
62 '"' => out.push_str("""),
63 '\'' => out.push_str("'"),
64 _ => out.push(ch),
65 }
66 }
67 out
68}
69
70pub(crate) fn truncate_chars(text: &str, max: usize) -> &str {
72 match text.char_indices().nth(max) {
73 Some((index, _)) => &text[..index],
74 None => text,
75 }
76}