1use std::fmt::Display;
2
3pub struct Escaper<C, const N: usize>(pub [(C, &'static str); N]);
4impl<const N: usize> Escaper<char, N> {
5 pub fn escape<'a, D: Display>(&'a self, display: &'a D) -> impl Display + 'a {
6 EscaperI {
7 display,
8 replacements: &self.0,
9 }
10 }
11}
12impl<const N: usize> Escaper<u8, N> {
13 pub fn escape<'a, D: Display>(&'a self, display: &'a D) -> impl Display + 'a {
14 EscaperI {
15 display,
16 replacements: &self.0,
17 }
18 }
19 pub fn unescape<'a, D: Display>(&'a self, display: &'a D) -> impl Display + 'a {
20 UnEscaperI {
21 display,
22 replacements: &self.0,
23 }
24 }
25}
26
27struct EscaperI<'a, D: Display, C, const N: usize> {
28 display: &'a D,
29 replacements: &'a [(C, &'static str); N],
30}
31impl<D: Display, const N: usize> Display for EscaperI<'_, D, char, N> {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 let mut r = Replacer {
34 writer: f,
35 replacements: self.replacements,
36 };
37 std::fmt::Write::write_fmt(&mut r, format_args!("{}", self.display))
38 }
39}
40impl<D: Display, const N: usize> Display for EscaperI<'_, D, u8, N> {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 let mut r = Replacer {
43 writer: f,
44 replacements: self.replacements,
45 };
46 std::fmt::Write::write_fmt(&mut r, format_args!("{}", self.display))
47 }
48}
49
50struct UnEscaperI<'a, D: Display, C, const N: usize> {
51 display: &'a D,
52 replacements: &'a [(C, &'static str); N],
53}
54impl<D: Display, const N: usize> Display for UnEscaperI<'_, D, u8, N> {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 let mut r = RevReplacer {
57 writer: f,
58 replacements: self.replacements,
59 };
60 std::fmt::Write::write_fmt(&mut r, format_args!("{}", self.display))
61 }
62}
63
64struct Replacer<'a, W: std::fmt::Write, C, const N: usize> {
65 writer: W,
66 replacements: &'a [(C, &'static str); N],
67}
68impl<W: std::fmt::Write, const N: usize> std::fmt::Write for Replacer<'_, W, char, N> {
69 fn write_str(&mut self, s: &str) -> std::fmt::Result {
70 for c in s.chars() {
71 self.write_char(c)?;
72 }
73 Ok(())
74 }
75 fn write_char(&mut self, c: char) -> std::fmt::Result {
76 for (r, s) in self.replacements {
77 if c == *r {
78 return self.writer.write_str(s);
79 }
80 }
81 self.writer.write_char(c)
82 }
83}
84impl<W: std::fmt::Write, const N: usize> std::fmt::Write for Replacer<'_, W, u8, N> {
85 fn write_str(&mut self, s: &str) -> std::fmt::Result {
86 for c in s.as_bytes() {
87 self.write_char(*c as char)?;
88 }
89 Ok(())
90 }
91 fn write_char(&mut self, c: char) -> std::fmt::Result {
92 for (r, s) in self.replacements {
93 if c == *r as char {
94 return self.writer.write_str(s);
95 }
96 }
97 self.writer.write_char(c)
98 }
99}
100
101struct RevReplacer<'a, W: std::fmt::Write, C, const N: usize> {
102 writer: W,
103 replacements: &'a [(C, &'static str); N],
104}
105
106impl<W: std::fmt::Write, const N: usize> std::fmt::Write for RevReplacer<'_, W, u8, N> {
107 fn write_str(&mut self, s: &str) -> std::fmt::Result {
108 let bytes = self.replacements.map(|(a,b)| (a,b.as_bytes()));
109 let mut s = s.as_bytes();
110 'outer: loop {
111 let mut i = 0;
112 while i < s.len() {
113 if let Some((a,b)) = bytes.iter().find_map(|(b,needle)|
114 s.strip_prefix(*needle).map(|r| (*b,r) )
115 ) {
116 self.writer.write_str(std::str::from_utf8(&s[..i]).map_err(|_|std::fmt::Error)?)?;
117 self.writer.write_char(a as char)?;
118 s = b;
119 continue 'outer
120 }
121 i += 1;
122 }
123 return self.writer.write_str(std::str::from_utf8(s).map_err(|_| std::fmt::Error)?);
124 }
125 }
126 fn write_char(&mut self, c: char) -> std::fmt::Result {
127 self.writer.write_char(c)
128 }
129}
130
131pub static IRI_ESCAPE: Escaper<u8, 5> = Escaper([
132 (b' ', "%20"),
133 (b'\\', "%5C"),
134 (b'^', "%5E"),
135 (b'[', "%5B"),
136 (b']', "%5D"),
137]);