1use std::fmt::{self};
2use std::io::Write;
3use std::{slice, str};
4
5use super::reader::BorrowReader;
6use super::{BorrowDecode, Encode, Writer};
7use crate::{DecodeError, EncodeError};
8
9#[repr(transparent)]
13pub struct EscapedSlice([u8]);
14
15impl EscapedSlice {
16 pub unsafe fn from_slice(b: &[u8]) -> &EscapedSlice {
21 unsafe { std::mem::transmute(b) }
23 }
24
25 pub fn as_bytes(&self) -> &[u8] {
28 &self.0
29 }
30
31 pub fn iter(&self) -> EscapedIter<'_> {
33 EscapedIter(self.0[..self.0.len() - 1].iter())
34 }
35}
36
37impl<F> Encode<F> for EscapedSlice {
38 fn encode<W: Write>(&self, w: &mut Writer<W>) -> Result<(), EncodeError> {
39 w.write_escaped_slice(self)
40 }
41}
42
43impl<'de, F> BorrowDecode<'de, F> for &'de EscapedSlice {
44 fn borrow_decode(w: &mut BorrowReader<'de>) -> Result<Self, DecodeError> {
45 w.read_escaped_slice()
46 }
47}
48
49impl fmt::Debug for EscapedSlice {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 let mut escaped = false;
52 let iter = self.0[..self.0.len() - 1].iter().copied().filter(|x| {
53 if escaped {
54 escaped = false;
55 true
56 } else if *x == 1 {
57 escaped = true;
58 false
59 } else {
60 true
61 }
62 });
63
64 f.debug_list().entries(iter).finish()
65 }
66}
67
68impl PartialEq<[u8]> for EscapedSlice {
69 fn eq(&self, other: &[u8]) -> bool {
70 let mut iter = other.iter().copied();
71 for a in self.iter().copied() {
72 let Some(b) = iter.next() else {
73 return false;
74 };
75 if a != b {
76 return false;
77 }
78 }
79 iter.next().is_none()
80 }
81}
82
83impl PartialEq<EscapedSlice> for [u8] {
84 fn eq(&self, other: &EscapedSlice) -> bool {
85 EscapedSlice::eq(other, self)
86 }
87}
88
89impl Eq for EscapedSlice {}
90impl PartialEq for EscapedSlice {
91 fn eq(&self, other: &Self) -> bool {
92 self.0 == other.0
93 }
94}
95
96impl<'a> IntoIterator for &'a EscapedSlice {
97 type Item = &'a u8;
98
99 type IntoIter = EscapedIter<'a>;
100
101 fn into_iter(self) -> Self::IntoIter {
102 self.iter()
103 }
104}
105
106pub struct EscapedIter<'a>(slice::Iter<'a, u8>);
107
108impl<'a> Iterator for EscapedIter<'a> {
109 type Item = &'a u8;
110
111 fn next(&mut self) -> Option<Self::Item> {
112 let c = self.0.next()?;
113 if *c == 1 {
114 self.0.next()
115 } else {
116 Some(c)
117 }
118 }
119}
120
121#[repr(transparent)]
125pub struct EscapedStr(str);
126
127impl EscapedStr {
128 pub unsafe fn from_str(b: &str) -> &EscapedStr {
133 unsafe { std::mem::transmute(b) }
135 }
136
137 pub fn as_bytes(&self) -> &[u8] {
140 self.0.as_bytes()
141 }
142
143 pub fn as_slice(&self) -> &EscapedSlice {
144 unsafe { EscapedSlice::from_slice(self.0.as_bytes()) }
145 }
146
147 pub fn chars(&self) -> EscapedChars<'_> {
149 EscapedChars(self.0[..self.0.len() - 1].chars())
150 }
151}
152
153impl<F> Encode<F> for EscapedStr {
154 fn encode<W: Write>(&self, w: &mut Writer<W>) -> Result<(), EncodeError> {
155 w.write_escaped_slice(self.as_slice())
156 }
157}
158
159impl<'de, F> BorrowDecode<'de, F> for &'de EscapedStr {
160 fn borrow_decode(w: &mut BorrowReader<'de>) -> Result<Self, DecodeError> {
161 w.read_escaped_str()
162 }
163}
164
165impl PartialEq<str> for EscapedStr {
166 fn eq(&self, other: &str) -> bool {
167 let mut iter = other.chars();
168 for a in self.chars() {
169 let Some(b) = iter.next() else {
170 return false;
171 };
172 if a != b {
173 return false;
174 }
175 }
176 iter.next().is_none()
177 }
178}
179
180impl PartialEq<EscapedStr> for str {
181 fn eq(&self, other: &EscapedStr) -> bool {
182 EscapedStr::eq(other, self)
183 }
184}
185
186impl Eq for EscapedStr {}
187impl PartialEq for EscapedStr {
188 fn eq(&self, other: &Self) -> bool {
189 self.0 == other.0
190 }
191}
192
193impl fmt::Debug for EscapedStr {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 use std::fmt::Write;
196 f.write_char('"')?;
197 for c in self.chars() {
198 for c in c.escape_debug() {
199 f.write_char(c)?;
200 }
201 }
202 f.write_char('"')?;
203 Ok(())
204 }
205}
206
207impl fmt::Display for EscapedStr {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 use std::fmt::Write;
210 for c in self.chars() {
211 f.write_char(c)?;
212 }
213 Ok(())
214 }
215}
216
217pub struct EscapedChars<'a>(str::Chars<'a>);
218
219impl<'a> Iterator for EscapedChars<'a> {
220 type Item = char;
221
222 fn next(&mut self) -> Option<Self::Item> {
223 let c = self.0.next()?;
224 if c == '\x01' {
225 self.0.next()
226 } else {
227 Some(c)
228 }
229 }
230}