1use alloc::borrow::Borrow;
7
8use bytes::{Buf, BufMut, Bytes, BytesMut};
9use core::{
10 fmt::{Debug, Display, Formatter, Write},
11 num::NonZeroUsize,
12};
13
14#[cfg(feature = "std")]
15use std::error::Error;
16
17#[derive(Clone, PartialEq, Eq, Hash, Default)]
29pub struct Utf32String(Bytes);
30
31#[derive(Clone, PartialEq, Eq, Hash, Default)]
49pub struct MysteryString(Bytes);
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash)]
54pub struct StringConversionError<T> {
55 pub num_errors: NonZeroUsize,
57 pub first_error: usize,
59 pub lossy: T,
61}
62
63impl<T> Display for StringConversionError<T> {
64 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
65 if usize::from(self.num_errors) > 1 {
66 write!(
67 f,
68 "string conversion encountered {} unrepresentable characters, the first one at index {}.",
69 self.num_errors,
70 self.first_error
71 )
72 } else {
73 write!(
74 f,
75 "string conversion encountered an unrepresentable character at index {}.",
76 self.first_error
77 )
78 }
79 }
80}
81
82#[cfg(feature = "std")]
83impl<T> Error for StringConversionError<T> where T: Debug {}
84
85impl Utf32String {
86 pub fn from_chars<I, C>(chars: I) -> Result<Self, StringConversionError<Self>>
95 where
96 I: IntoIterator<Item = C>,
97 C: Borrow<char>,
98 {
99 let mut num_errors: usize = 0;
100 let mut first_error: usize = usize::MAX;
101
102 let iter = chars.into_iter();
103 let mut bm = BytesMut::with_capacity(4 * iter.size_hint().0);
104
105 for (i, cref) in iter.enumerate() {
106 let c = *cref.borrow();
107 if c == '\0' {
108 bm.put_u32('\u{2400}'.into());
109 num_errors += 1;
110 first_error = first_error.min(i);
111 } else {
112 bm.put_u32(c.into())
113 }
114 }
115
116 if let Some(num_errors) = NonZeroUsize::new(num_errors) {
117 Err(StringConversionError {
118 num_errors,
119 first_error,
120 lossy: Self(bm.freeze()),
121 })
122 } else {
123 Ok(Self(bm.freeze()))
124 }
125 }
126
127 pub fn from_chars_lossy<I, C>(chars: I) -> Self
130 where
131 I: IntoIterator<Item = C>,
132 C: Borrow<char>,
133 {
134 match Self::from_chars(chars) {
135 Ok(s) => s,
136 Err(e) => e.lossy,
137 }
138 }
139
140 pub fn is_empty(&self) -> bool {
142 self.0.is_empty()
143 }
144
145 pub fn char_len(&self) -> usize {
147 self.0.len() / 4
148 }
149
150 pub fn byte_len(&self) -> usize {
153 self.0.len()
154 }
155
156 pub fn byte_len_with_prefix_and_nul(&self) -> usize {
159 self.0.len() + 8
160 }
161
162 pub fn to_bytes(&self) -> Bytes {
164 self.clone().into_bytes()
165 }
166
167 pub fn into_bytes(self) -> Bytes {
169 self.0
170 }
171}
172
173impl Display for Utf32String {
174 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
175 let mut buf = self.0.clone();
176
177 while buf.has_remaining() {
178 let c: char = buf
179 .get_u32()
180 .try_into()
181 .expect("Utf32String should always contain valid characters");
182 f.write_char(c)?
183 }
184
185 Ok(())
186 }
187}
188
189impl Debug for Utf32String {
190 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
191 let s = self.to_string();
192 f.debug_tuple("Utf32String").field(&s).finish()
193 }
194}
195
196impl TryFrom<String> for Utf32String {
197 type Error = StringConversionError<Utf32String>;
198
199 fn try_from(value: String) -> Result<Self, Self::Error> {
200 Utf32String::from_chars(value.chars())
201 }
202}
203
204impl TryFrom<&String> for Utf32String {
205 type Error = StringConversionError<Utf32String>;
206
207 fn try_from(value: &String) -> Result<Self, Self::Error> {
208 Utf32String::from_chars(value.chars())
209 }
210}
211
212impl TryFrom<&str> for Utf32String {
213 type Error = StringConversionError<Utf32String>;
214
215 fn try_from(value: &str) -> Result<Self, Self::Error> {
216 Utf32String::from_chars(value.chars())
217 }
218}
219
220impl TryFrom<&[char]> for Utf32String {
221 type Error = StringConversionError<Utf32String>;
222
223 fn try_from(value: &[char]) -> Result<Self, Self::Error> {
224 Utf32String::from_chars(value)
225 }
226}
227
228impl MysteryString {
229 pub fn from_chars<I, C>(chars: I) -> Result<Self, StringConversionError<Self>>
237 where
238 I: IntoIterator<Item = C>,
239 C: Borrow<char>,
240 {
241 let mut num_errors: usize = 0;
242 let mut first_error: usize = usize::MAX;
243
244 let iter = chars.into_iter();
245 let mut bm = BytesMut::with_capacity(4 * iter.size_hint().0);
246
247 for (i, cref) in iter.enumerate() {
248 match u8::try_from(*cref.borrow()) {
249 Ok(b) if b != 0 => {
250 bm.put_u8(b);
251 }
252 _ => {
253 bm.put_u8(b'?');
254 num_errors += 1;
255 first_error = first_error.min(i);
256 }
257 }
258 }
259
260 if let Some(num_errors) = NonZeroUsize::new(num_errors) {
261 Err(StringConversionError {
262 num_errors,
263 first_error,
264 lossy: Self(bm.freeze()),
265 })
266 } else {
267 Ok(Self(bm.freeze()))
268 }
269 }
270
271 pub fn from_bytes<I, C>(chars: I) -> Result<Self, StringConversionError<Self>>
281 where
282 I: IntoIterator<Item = C>,
283 C: Borrow<u8>,
284 {
285 let mut failed = false;
286 let mut num_errors: usize = 0;
287 let mut first_error: usize = usize::MAX;
288
289 let iter = chars.into_iter();
290 let mut bm = BytesMut::with_capacity(4 * iter.size_hint().0);
291
292 for (i, bref) in iter.enumerate() {
293 let b = *bref.borrow();
294
295 if b != 0 {
296 if !failed {
301 bm.put_u8(b);
302 }
303 } else {
304 failed = true;
305 num_errors += 1;
306 first_error = first_error.min(i);
307 }
308 }
309
310 if let Some(num_errors) = NonZeroUsize::new(num_errors) {
311 Err(StringConversionError {
312 num_errors,
313 first_error,
314 lossy: Self(bm.freeze()),
315 })
316 } else {
317 Ok(Self(bm.freeze()))
318 }
319 }
320
321 pub fn from_chars_lossy<I, C>(chars: I) -> Self
324 where
325 I: IntoIterator<Item = C>,
326 C: Borrow<char>,
327 {
328 match Self::from_chars(chars) {
329 Ok(s) => s,
330 Err(e) => e.lossy,
331 }
332 }
333
334 pub fn from_bytes_lossy<I, C>(chars: I) -> Self
337 where
338 I: IntoIterator<Item = C>,
339 C: Borrow<u8>,
340 {
341 match Self::from_bytes(chars) {
342 Ok(s) => s,
343 Err(e) => e.lossy,
344 }
345 }
346
347 pub fn is_empty(&self) -> bool {
349 self.0.is_empty()
350 }
351
352 pub fn len(&self) -> usize {
354 self.0.len()
355 }
356
357 pub fn len_with_prefix_and_nul(&self) -> usize {
359 self.len() + 2
360 }
361
362 pub fn to_bytes(&self) -> Bytes {
364 self.clone().into_bytes()
365 }
366
367 pub fn into_bytes(self) -> Bytes {
369 self.0
370 }
371}
372
373impl Display for MysteryString {
374 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
375 let mut buf = self.0.clone();
376 while buf.has_remaining() {
377 let byte = buf.get_u8();
378 let c = char::from_u32(byte.into()).unwrap();
379 f.write_char(c)?
380 }
381
382 Ok(())
383 }
384}
385
386impl Debug for MysteryString {
387 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
388 let s = self.to_string();
389 f.debug_tuple("MysteryString").field(&s).finish()
390 }
391}
392
393impl TryFrom<String> for MysteryString {
394 type Error = StringConversionError<MysteryString>;
395
396 fn try_from(value: String) -> Result<Self, Self::Error> {
397 MysteryString::from_chars(value.chars())
398 }
399}
400
401impl TryFrom<&String> for MysteryString {
402 type Error = StringConversionError<MysteryString>;
403
404 fn try_from(value: &String) -> Result<Self, Self::Error> {
405 MysteryString::from_chars(value.chars())
406 }
407}
408
409impl TryFrom<&str> for MysteryString {
410 type Error = StringConversionError<MysteryString>;
411
412 fn try_from(value: &str) -> Result<Self, Self::Error> {
413 MysteryString::from_chars(value.chars())
414 }
415}
416
417impl TryFrom<Vec<u8>> for MysteryString {
418 type Error = StringConversionError<MysteryString>;
419
420 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
421 MysteryString::from_bytes(value)
422 }
423}
424
425impl TryFrom<&Vec<u8>> for MysteryString {
426 type Error = StringConversionError<MysteryString>;
427
428 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
429 MysteryString::from_bytes(value)
430 }
431}
432
433impl TryFrom<&[u8]> for MysteryString {
434 type Error = StringConversionError<MysteryString>;
435
436 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
437 MysteryString::from_bytes(value)
438 }
439}