1use std::{fmt, ops::Range};
2
3#[derive(Clone, Default)]
7pub struct UnescapedRoute {
8 inner: Vec<u8>,
10 escaped: Vec<usize>,
11}
12
13impl UnescapedRoute {
14 pub fn new(mut inner: Vec<u8>) -> UnescapedRoute {
16 let mut escaped = Vec::new();
17 let mut i = 0;
18
19 while let Some(&c) = inner.get(i) {
20 if (c == b'{' && inner.get(i + 1) == Some(&b'{'))
21 || (c == b'}' && inner.get(i + 1) == Some(&b'}'))
22 {
23 inner.remove(i);
24 escaped.push(i);
25 }
26
27 i += 1;
28 }
29
30 UnescapedRoute { inner, escaped }
31 }
32
33 pub fn is_escaped(&self, i: usize) -> bool {
35 self.escaped.contains(&i)
36 }
37
38 pub fn splice(
40 &mut self,
41 range: Range<usize>,
42 replace: Vec<u8>,
43 ) -> impl Iterator<Item = u8> + '_ {
44 self.escaped.retain(|x| !range.contains(x));
46
47 let offset = (replace.len() as isize) - (range.len() as isize);
49 for i in &mut self.escaped {
50 if *i > range.end {
51 *i = i.checked_add_signed(offset).unwrap();
52 }
53 }
54
55 self.inner.splice(range, replace)
56 }
57
58 pub fn append(&mut self, other: &UnescapedRoute) {
60 for i in &other.escaped {
61 self.escaped.push(self.inner.len() + i);
62 }
63
64 self.inner.extend_from_slice(&other.inner);
65 }
66
67 pub fn truncate(&mut self, to: usize) {
69 self.escaped.retain(|&x| x < to);
70 self.inner.truncate(to);
71 }
72
73 pub fn as_ref(&self) -> UnescapedRef<'_> {
75 UnescapedRef {
76 inner: &self.inner,
77 escaped: &self.escaped,
78 offset: 0,
79 }
80 }
81
82 pub fn unescaped(&self) -> &[u8] {
84 &self.inner
85 }
86
87 pub fn into_unescaped(self) -> Vec<u8> {
89 self.inner
90 }
91}
92
93impl std::ops::Deref for UnescapedRoute {
94 type Target = [u8];
95
96 fn deref(&self) -> &Self::Target {
97 &self.inner
98 }
99}
100
101impl fmt::Debug for UnescapedRoute {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 fmt::Debug::fmt(std::str::from_utf8(&self.inner).unwrap(), f)
104 }
105}
106
107#[derive(Copy, Clone)]
109pub struct UnescapedRef<'a> {
110 pub inner: &'a [u8],
111 escaped: &'a [usize],
112 offset: isize,
114}
115
116impl<'a> UnescapedRef<'a> {
117 pub fn to_owned(self) -> UnescapedRoute {
119 let mut escaped = Vec::new();
120 for &i in self.escaped {
121 let i = i.checked_add_signed(self.offset);
122
123 match i {
124 Some(i) if i < self.inner.len() => escaped.push(i),
125 _ => {}
126 }
127 }
128
129 UnescapedRoute {
130 escaped,
131 inner: self.inner.to_owned(),
132 }
133 }
134
135 pub fn is_escaped(&self, i: usize) -> bool {
137 if let Some(i) = i.checked_add_signed(-self.offset) {
138 return self.escaped.contains(&i);
139 }
140
141 false
142 }
143
144 pub fn slice_off(&self, start: usize) -> UnescapedRef<'a> {
146 UnescapedRef {
147 inner: &self.inner[start..],
148 escaped: self.escaped,
149 offset: self.offset - (start as isize),
150 }
151 }
152
153 pub fn slice_until(&self, end: usize) -> UnescapedRef<'a> {
155 UnescapedRef {
156 inner: &self.inner[..end],
157 escaped: self.escaped,
158 offset: self.offset,
159 }
160 }
161
162 pub fn unescaped(&self) -> &[u8] {
164 self.inner
165 }
166}
167
168impl<'a> std::ops::Deref for UnescapedRef<'a> {
169 type Target = &'a [u8];
170
171 fn deref(&self) -> &Self::Target {
172 &self.inner
173 }
174}
175
176impl<'a> fmt::Debug for UnescapedRef<'a> {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 f.debug_struct("UnescapedRef")
179 .field("inner", &std::str::from_utf8(self.inner))
180 .field("escaped", &self.escaped)
181 .field("offset", &self.offset)
182 .finish()
183 }
184}