1use std::fmt::Write;
4
5use unicode_segmentation::UnicodeSegmentation as _;
6
7pub trait CollectEscaped {
8 fn collect_pango_escaped_into<T: Write>(self, out: &mut T);
10
11 #[inline]
13 fn collect_pango_escaped<T: Write + Default>(self) -> T
14 where
15 Self: Sized,
16 {
17 let mut out = T::default();
18 self.collect_pango_escaped_into(&mut out);
19 out
20 }
21}
22
23impl<I, R> CollectEscaped for I
24where
25 I: Iterator<Item = R>,
26 R: AsRef<str>,
27{
28 fn collect_pango_escaped_into<T: Write>(self, out: &mut T) {
29 for c in self {
30 let _ = match c.as_ref() {
31 "&" => out.write_str("&"),
32 "<" => out.write_str("<"),
33 ">" => out.write_str(">"),
34 "'" => out.write_str("'"),
35 x => out.write_str(x),
36 };
37 }
38 }
39}
40
41pub trait Escaped {
42 fn pango_escaped_into<T: Write>(self, out: &mut T);
44
45 #[inline]
47 fn pango_escaped<T: Write + Default>(self) -> T
48 where
49 Self: Sized,
50 {
51 let mut out = T::default();
52 self.pango_escaped_into(&mut out);
53 out
54 }
55}
56
57impl<R: AsRef<str>> Escaped for R {
58 fn pango_escaped_into<T: Write>(self, out: &mut T) {
59 self.as_ref()
60 .split_word_bounds()
61 .collect_pango_escaped_into(out);
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn collect_pango() {
71 let orig = "&my 'text' <a̐>";
72 let escaped: String = orig.graphemes(true).collect_pango_escaped();
73 assert_eq!(escaped, "&my 'text' <a̐>");
74 }
75 #[test]
76 fn pango() {
77 let orig = "&my 'text' <a̐>";
78 let escaped: String = orig.pango_escaped();
79 assert_eq!(escaped, "&my 'text' <a̐>");
80 }
81}