1 | macro_rules! impl_partial_eq { |
2 | ($lhs:ty, $rhs:ty) => { |
3 | impl<'a, 'b> PartialEq<$rhs> for $lhs { |
4 | #[inline] |
5 | fn eq(&self, other: &$rhs) -> bool { |
6 | let other: &[u8] = other.as_ref(); |
7 | PartialEq::eq(self.as_bytes(), other) |
8 | } |
9 | } |
10 | |
11 | impl<'a, 'b> PartialEq<$lhs> for $rhs { |
12 | #[inline] |
13 | fn eq(&self, other: &$lhs) -> bool { |
14 | let this: &[u8] = self.as_ref(); |
15 | PartialEq::eq(this, other.as_bytes()) |
16 | } |
17 | } |
18 | }; |
19 | } |
20 | |
21 | #[cfg (feature = "alloc" )] |
22 | macro_rules! impl_partial_eq_cow { |
23 | ($lhs:ty, $rhs:ty) => { |
24 | impl<'a, 'b> PartialEq<$rhs> for $lhs { |
25 | #[inline] |
26 | fn eq(&self, other: &$rhs) -> bool { |
27 | let other: &[u8] = (&**other).as_ref(); |
28 | PartialEq::eq(self.as_bytes(), other) |
29 | } |
30 | } |
31 | |
32 | impl<'a, 'b> PartialEq<$lhs> for $rhs { |
33 | #[inline] |
34 | fn eq(&self, other: &$lhs) -> bool { |
35 | let this: &[u8] = (&**other).as_ref(); |
36 | PartialEq::eq(this, self.as_bytes()) |
37 | } |
38 | } |
39 | }; |
40 | } |
41 | |
42 | macro_rules! impl_partial_ord { |
43 | ($lhs:ty, $rhs:ty) => { |
44 | impl<'a, 'b> PartialOrd<$rhs> for $lhs { |
45 | #[inline] |
46 | fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> { |
47 | let other: &[u8] = other.as_ref(); |
48 | PartialOrd::partial_cmp(self.as_bytes(), other) |
49 | } |
50 | } |
51 | |
52 | impl<'a, 'b> PartialOrd<$lhs> for $rhs { |
53 | #[inline] |
54 | fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> { |
55 | let this: &[u8] = self.as_ref(); |
56 | PartialOrd::partial_cmp(this, other.as_bytes()) |
57 | } |
58 | } |
59 | }; |
60 | } |
61 | |
62 | #[cfg (feature = "alloc" )] |
63 | mod bstring { |
64 | use core::{ |
65 | cmp::Ordering, convert::TryFrom, fmt, iter::FromIterator, ops, |
66 | }; |
67 | |
68 | use alloc::{ |
69 | borrow::{Borrow, BorrowMut, Cow, ToOwned}, |
70 | string::String, |
71 | vec, |
72 | vec::Vec, |
73 | }; |
74 | |
75 | use crate::{ |
76 | bstr::BStr, bstring::BString, ext_slice::ByteSlice, ext_vec::ByteVec, |
77 | }; |
78 | |
79 | impl fmt::Display for BString { |
80 | #[inline ] |
81 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
82 | fmt::Display::fmt(self.as_bstr(), f) |
83 | } |
84 | } |
85 | |
86 | impl fmt::Debug for BString { |
87 | #[inline ] |
88 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
89 | fmt::Debug::fmt(self.as_bstr(), f) |
90 | } |
91 | } |
92 | |
93 | impl ops::Deref for BString { |
94 | type Target = Vec<u8>; |
95 | |
96 | #[inline ] |
97 | fn deref(&self) -> &Vec<u8> { |
98 | self.as_vec() |
99 | } |
100 | } |
101 | |
102 | impl ops::DerefMut for BString { |
103 | #[inline ] |
104 | fn deref_mut(&mut self) -> &mut Vec<u8> { |
105 | self.as_vec_mut() |
106 | } |
107 | } |
108 | |
109 | impl AsRef<[u8]> for BString { |
110 | #[inline ] |
111 | fn as_ref(&self) -> &[u8] { |
112 | self.as_bytes() |
113 | } |
114 | } |
115 | |
116 | impl AsRef<BStr> for BString { |
117 | #[inline ] |
118 | fn as_ref(&self) -> &BStr { |
119 | self.as_bstr() |
120 | } |
121 | } |
122 | |
123 | impl AsMut<[u8]> for BString { |
124 | #[inline ] |
125 | fn as_mut(&mut self) -> &mut [u8] { |
126 | self.as_bytes_mut() |
127 | } |
128 | } |
129 | |
130 | impl AsMut<BStr> for BString { |
131 | #[inline ] |
132 | fn as_mut(&mut self) -> &mut BStr { |
133 | self.as_mut_bstr() |
134 | } |
135 | } |
136 | |
137 | impl Borrow<[u8]> for BString { |
138 | #[inline ] |
139 | fn borrow(&self) -> &[u8] { |
140 | self.as_bytes() |
141 | } |
142 | } |
143 | |
144 | impl Borrow<BStr> for BString { |
145 | #[inline ] |
146 | fn borrow(&self) -> &BStr { |
147 | self.as_bstr() |
148 | } |
149 | } |
150 | |
151 | impl Borrow<BStr> for Vec<u8> { |
152 | #[inline ] |
153 | fn borrow(&self) -> &BStr { |
154 | self.as_slice().as_bstr() |
155 | } |
156 | } |
157 | |
158 | impl Borrow<BStr> for String { |
159 | #[inline ] |
160 | fn borrow(&self) -> &BStr { |
161 | self.as_bytes().as_bstr() |
162 | } |
163 | } |
164 | |
165 | impl BorrowMut<[u8]> for BString { |
166 | #[inline ] |
167 | fn borrow_mut(&mut self) -> &mut [u8] { |
168 | self.as_bytes_mut() |
169 | } |
170 | } |
171 | |
172 | impl BorrowMut<BStr> for BString { |
173 | #[inline ] |
174 | fn borrow_mut(&mut self) -> &mut BStr { |
175 | self.as_mut_bstr() |
176 | } |
177 | } |
178 | |
179 | impl BorrowMut<BStr> for Vec<u8> { |
180 | #[inline ] |
181 | fn borrow_mut(&mut self) -> &mut BStr { |
182 | BStr::new_mut(self.as_mut_slice()) |
183 | } |
184 | } |
185 | |
186 | impl ToOwned for BStr { |
187 | type Owned = BString; |
188 | |
189 | #[inline ] |
190 | fn to_owned(&self) -> BString { |
191 | BString::from(self) |
192 | } |
193 | } |
194 | |
195 | impl Default for BString { |
196 | fn default() -> BString { |
197 | BString::from(vec![]) |
198 | } |
199 | } |
200 | |
201 | impl<'a, const N: usize> From<&'a [u8; N]> for BString { |
202 | #[inline ] |
203 | fn from(s: &'a [u8; N]) -> BString { |
204 | BString::from(&s[..]) |
205 | } |
206 | } |
207 | |
208 | impl<const N: usize> From<[u8; N]> for BString { |
209 | #[inline ] |
210 | fn from(s: [u8; N]) -> BString { |
211 | BString::from(&s[..]) |
212 | } |
213 | } |
214 | |
215 | impl<'a> From<&'a [u8]> for BString { |
216 | #[inline ] |
217 | fn from(s: &'a [u8]) -> BString { |
218 | BString::from(s.to_vec()) |
219 | } |
220 | } |
221 | |
222 | impl From<Vec<u8>> for BString { |
223 | #[inline ] |
224 | fn from(s: Vec<u8>) -> BString { |
225 | BString::new(s) |
226 | } |
227 | } |
228 | |
229 | impl From<BString> for Vec<u8> { |
230 | #[inline ] |
231 | fn from(s: BString) -> Vec<u8> { |
232 | s.into_vec() |
233 | } |
234 | } |
235 | |
236 | impl<'a> From<&'a str> for BString { |
237 | #[inline ] |
238 | fn from(s: &'a str) -> BString { |
239 | BString::from(s.as_bytes().to_vec()) |
240 | } |
241 | } |
242 | |
243 | impl From<String> for BString { |
244 | #[inline ] |
245 | fn from(s: String) -> BString { |
246 | BString::from(s.into_bytes()) |
247 | } |
248 | } |
249 | |
250 | impl<'a> From<&'a BStr> for BString { |
251 | #[inline ] |
252 | fn from(s: &'a BStr) -> BString { |
253 | BString::from(s.bytes.to_vec()) |
254 | } |
255 | } |
256 | |
257 | impl<'a> From<BString> for Cow<'a, BStr> { |
258 | #[inline ] |
259 | fn from(s: BString) -> Cow<'a, BStr> { |
260 | Cow::Owned(s) |
261 | } |
262 | } |
263 | |
264 | impl TryFrom<BString> for String { |
265 | type Error = crate::FromUtf8Error; |
266 | |
267 | #[inline ] |
268 | fn try_from(s: BString) -> Result<String, crate::FromUtf8Error> { |
269 | s.into_vec().into_string() |
270 | } |
271 | } |
272 | |
273 | impl<'a> TryFrom<&'a BString> for &'a str { |
274 | type Error = crate::Utf8Error; |
275 | |
276 | #[inline ] |
277 | fn try_from(s: &'a BString) -> Result<&'a str, crate::Utf8Error> { |
278 | s.as_bytes().to_str() |
279 | } |
280 | } |
281 | |
282 | impl FromIterator<char> for BString { |
283 | #[inline ] |
284 | fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> BString { |
285 | BString::from(iter.into_iter().collect::<String>()) |
286 | } |
287 | } |
288 | |
289 | impl FromIterator<u8> for BString { |
290 | #[inline ] |
291 | fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> BString { |
292 | BString::from(iter.into_iter().collect::<Vec<u8>>()) |
293 | } |
294 | } |
295 | |
296 | impl<'a> FromIterator<&'a str> for BString { |
297 | #[inline ] |
298 | fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> BString { |
299 | let mut buf = vec![]; |
300 | for b in iter { |
301 | buf.push_str(b); |
302 | } |
303 | BString::from(buf) |
304 | } |
305 | } |
306 | |
307 | impl<'a> FromIterator<&'a [u8]> for BString { |
308 | #[inline ] |
309 | fn from_iter<T: IntoIterator<Item = &'a [u8]>>(iter: T) -> BString { |
310 | let mut buf = vec![]; |
311 | for b in iter { |
312 | buf.push_str(b); |
313 | } |
314 | BString::from(buf) |
315 | } |
316 | } |
317 | |
318 | impl<'a> FromIterator<&'a BStr> for BString { |
319 | #[inline ] |
320 | fn from_iter<T: IntoIterator<Item = &'a BStr>>(iter: T) -> BString { |
321 | let mut buf = vec![]; |
322 | for b in iter { |
323 | buf.push_str(b); |
324 | } |
325 | BString::from(buf) |
326 | } |
327 | } |
328 | |
329 | impl FromIterator<BString> for BString { |
330 | #[inline ] |
331 | fn from_iter<T: IntoIterator<Item = BString>>(iter: T) -> BString { |
332 | let mut buf = vec![]; |
333 | for b in iter { |
334 | buf.push_str(b); |
335 | } |
336 | BString::from(buf) |
337 | } |
338 | } |
339 | |
340 | impl Eq for BString {} |
341 | |
342 | impl PartialEq for BString { |
343 | #[inline ] |
344 | fn eq(&self, other: &BString) -> bool { |
345 | &self[..] == &other[..] |
346 | } |
347 | } |
348 | |
349 | impl_partial_eq!(BString, Vec<u8>); |
350 | impl_partial_eq!(BString, [u8]); |
351 | impl_partial_eq!(BString, &'a [u8]); |
352 | impl_partial_eq!(BString, String); |
353 | impl_partial_eq!(BString, str); |
354 | impl_partial_eq!(BString, &'a str); |
355 | impl_partial_eq!(BString, BStr); |
356 | impl_partial_eq!(BString, &'a BStr); |
357 | |
358 | impl PartialOrd for BString { |
359 | #[inline ] |
360 | fn partial_cmp(&self, other: &BString) -> Option<Ordering> { |
361 | PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes()) |
362 | } |
363 | } |
364 | |
365 | impl Ord for BString { |
366 | #[inline ] |
367 | fn cmp(&self, other: &BString) -> Ordering { |
368 | self.partial_cmp(other).unwrap() |
369 | } |
370 | } |
371 | |
372 | impl_partial_ord!(BString, Vec<u8>); |
373 | impl_partial_ord!(BString, [u8]); |
374 | impl_partial_ord!(BString, &'a [u8]); |
375 | impl_partial_ord!(BString, String); |
376 | impl_partial_ord!(BString, str); |
377 | impl_partial_ord!(BString, &'a str); |
378 | impl_partial_ord!(BString, BStr); |
379 | impl_partial_ord!(BString, &'a BStr); |
380 | } |
381 | |
382 | mod bstr { |
383 | use core::{ |
384 | borrow::{Borrow, BorrowMut}, |
385 | cmp::Ordering, |
386 | convert::TryFrom, |
387 | fmt, ops, |
388 | }; |
389 | |
390 | #[cfg (feature = "alloc" )] |
391 | use alloc::{borrow::Cow, boxed::Box, string::String, vec::Vec}; |
392 | |
393 | use crate::{bstr::BStr, ext_slice::ByteSlice}; |
394 | |
395 | impl fmt::Display for BStr { |
396 | #[inline ] |
397 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
398 | /// Write the given bstr (lossily) to the given formatter. |
399 | fn write_bstr( |
400 | f: &mut fmt::Formatter<'_>, |
401 | bstr: &BStr, |
402 | ) -> Result<(), fmt::Error> { |
403 | for chunk in bstr.utf8_chunks() { |
404 | f.write_str(chunk.valid())?; |
405 | if !chunk.invalid().is_empty() { |
406 | f.write_str(" \u{FFFD}" )?; |
407 | } |
408 | } |
409 | Ok(()) |
410 | } |
411 | |
412 | /// Write 'num' fill characters to the given formatter. |
413 | fn write_pads( |
414 | f: &mut fmt::Formatter<'_>, |
415 | num: usize, |
416 | ) -> fmt::Result { |
417 | let fill = f.fill(); |
418 | for _ in 0..num { |
419 | f.write_fmt(format_args!(" {}" , fill))?; |
420 | } |
421 | Ok(()) |
422 | } |
423 | |
424 | if let Some(align) = f.align() { |
425 | let width = f.width().unwrap_or(0); |
426 | let nchars = self.chars().count(); |
427 | let remaining_pads = width.saturating_sub(nchars); |
428 | match align { |
429 | fmt::Alignment::Left => { |
430 | write_bstr(f, self)?; |
431 | write_pads(f, remaining_pads)?; |
432 | } |
433 | fmt::Alignment::Right => { |
434 | write_pads(f, remaining_pads)?; |
435 | write_bstr(f, self)?; |
436 | } |
437 | fmt::Alignment::Center => { |
438 | let half = remaining_pads / 2; |
439 | let second_half = if remaining_pads % 2 == 0 { |
440 | half |
441 | } else { |
442 | half + 1 |
443 | }; |
444 | write_pads(f, half)?; |
445 | write_bstr(f, self)?; |
446 | write_pads(f, second_half)?; |
447 | } |
448 | } |
449 | Ok(()) |
450 | } else { |
451 | write_bstr(f, self)?; |
452 | Ok(()) |
453 | } |
454 | } |
455 | } |
456 | |
457 | impl fmt::Debug for BStr { |
458 | #[inline ] |
459 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
460 | write!(f, " \"" )?; |
461 | for (s, e, ch) in self.char_indices() { |
462 | match ch { |
463 | ' \0' => write!(f, " \\0" )?, |
464 | ' \u{FFFD}' => { |
465 | let bytes = self[s..e].as_bytes(); |
466 | if bytes == b" \xEF\xBF\xBD" { |
467 | write!(f, " {}" , ch.escape_debug())?; |
468 | } else { |
469 | for &b in self[s..e].as_bytes() { |
470 | write!(f, r"\x{:02X}" , b)?; |
471 | } |
472 | } |
473 | } |
474 | // ASCII control characters except \0, \n, \r, \t |
475 | ' \x01' ..=' \x08' |
476 | | ' \x0b' |
477 | | ' \x0c' |
478 | | ' \x0e' ..=' \x19' |
479 | | ' \x7f' => { |
480 | write!(f, " \\x {:02x}" , ch as u32)?; |
481 | } |
482 | ' \n' | ' \r' | ' \t' | _ => { |
483 | write!(f, " {}" , ch.escape_debug())?; |
484 | } |
485 | } |
486 | } |
487 | write!(f, " \"" )?; |
488 | Ok(()) |
489 | } |
490 | } |
491 | |
492 | impl ops::Deref for BStr { |
493 | type Target = [u8]; |
494 | |
495 | #[inline ] |
496 | fn deref(&self) -> &[u8] { |
497 | &self.bytes |
498 | } |
499 | } |
500 | |
501 | impl ops::DerefMut for BStr { |
502 | #[inline ] |
503 | fn deref_mut(&mut self) -> &mut [u8] { |
504 | &mut self.bytes |
505 | } |
506 | } |
507 | |
508 | impl ops::Index<usize> for BStr { |
509 | type Output = u8; |
510 | |
511 | #[inline ] |
512 | fn index(&self, idx: usize) -> &u8 { |
513 | &self.as_bytes()[idx] |
514 | } |
515 | } |
516 | |
517 | impl ops::Index<ops::RangeFull> for BStr { |
518 | type Output = BStr; |
519 | |
520 | #[inline ] |
521 | fn index(&self, _: ops::RangeFull) -> &BStr { |
522 | self |
523 | } |
524 | } |
525 | |
526 | impl ops::Index<ops::Range<usize>> for BStr { |
527 | type Output = BStr; |
528 | |
529 | #[inline ] |
530 | fn index(&self, r: ops::Range<usize>) -> &BStr { |
531 | BStr::new(&self.as_bytes()[r.start..r.end]) |
532 | } |
533 | } |
534 | |
535 | impl ops::Index<ops::RangeInclusive<usize>> for BStr { |
536 | type Output = BStr; |
537 | |
538 | #[inline ] |
539 | fn index(&self, r: ops::RangeInclusive<usize>) -> &BStr { |
540 | BStr::new(&self.as_bytes()[*r.start()..=*r.end()]) |
541 | } |
542 | } |
543 | |
544 | impl ops::Index<ops::RangeFrom<usize>> for BStr { |
545 | type Output = BStr; |
546 | |
547 | #[inline ] |
548 | fn index(&self, r: ops::RangeFrom<usize>) -> &BStr { |
549 | BStr::new(&self.as_bytes()[r.start..]) |
550 | } |
551 | } |
552 | |
553 | impl ops::Index<ops::RangeTo<usize>> for BStr { |
554 | type Output = BStr; |
555 | |
556 | #[inline ] |
557 | fn index(&self, r: ops::RangeTo<usize>) -> &BStr { |
558 | BStr::new(&self.as_bytes()[..r.end]) |
559 | } |
560 | } |
561 | |
562 | impl ops::Index<ops::RangeToInclusive<usize>> for BStr { |
563 | type Output = BStr; |
564 | |
565 | #[inline ] |
566 | fn index(&self, r: ops::RangeToInclusive<usize>) -> &BStr { |
567 | BStr::new(&self.as_bytes()[..=r.end]) |
568 | } |
569 | } |
570 | |
571 | impl ops::IndexMut<usize> for BStr { |
572 | #[inline ] |
573 | fn index_mut(&mut self, idx: usize) -> &mut u8 { |
574 | &mut self.bytes[idx] |
575 | } |
576 | } |
577 | |
578 | impl ops::IndexMut<ops::RangeFull> for BStr { |
579 | #[inline ] |
580 | fn index_mut(&mut self, _: ops::RangeFull) -> &mut BStr { |
581 | self |
582 | } |
583 | } |
584 | |
585 | impl ops::IndexMut<ops::Range<usize>> for BStr { |
586 | #[inline ] |
587 | fn index_mut(&mut self, r: ops::Range<usize>) -> &mut BStr { |
588 | BStr::from_bytes_mut(&mut self.bytes[r.start..r.end]) |
589 | } |
590 | } |
591 | |
592 | impl ops::IndexMut<ops::RangeInclusive<usize>> for BStr { |
593 | #[inline ] |
594 | fn index_mut(&mut self, r: ops::RangeInclusive<usize>) -> &mut BStr { |
595 | BStr::from_bytes_mut(&mut self.bytes[*r.start()..=*r.end()]) |
596 | } |
597 | } |
598 | |
599 | impl ops::IndexMut<ops::RangeFrom<usize>> for BStr { |
600 | #[inline ] |
601 | fn index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut BStr { |
602 | BStr::from_bytes_mut(&mut self.bytes[r.start..]) |
603 | } |
604 | } |
605 | |
606 | impl ops::IndexMut<ops::RangeTo<usize>> for BStr { |
607 | #[inline ] |
608 | fn index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut BStr { |
609 | BStr::from_bytes_mut(&mut self.bytes[..r.end]) |
610 | } |
611 | } |
612 | |
613 | impl ops::IndexMut<ops::RangeToInclusive<usize>> for BStr { |
614 | #[inline ] |
615 | fn index_mut(&mut self, r: ops::RangeToInclusive<usize>) -> &mut BStr { |
616 | BStr::from_bytes_mut(&mut self.bytes[..=r.end]) |
617 | } |
618 | } |
619 | |
620 | impl AsRef<[u8]> for BStr { |
621 | #[inline ] |
622 | fn as_ref(&self) -> &[u8] { |
623 | self.as_bytes() |
624 | } |
625 | } |
626 | |
627 | impl AsRef<BStr> for BStr { |
628 | #[inline ] |
629 | fn as_ref(&self) -> &BStr { |
630 | self |
631 | } |
632 | } |
633 | |
634 | impl AsRef<BStr> for [u8] { |
635 | #[inline ] |
636 | fn as_ref(&self) -> &BStr { |
637 | BStr::new(self) |
638 | } |
639 | } |
640 | |
641 | impl AsRef<BStr> for str { |
642 | #[inline ] |
643 | fn as_ref(&self) -> &BStr { |
644 | BStr::new(self) |
645 | } |
646 | } |
647 | |
648 | impl AsMut<[u8]> for BStr { |
649 | #[inline ] |
650 | fn as_mut(&mut self) -> &mut [u8] { |
651 | &mut self.bytes |
652 | } |
653 | } |
654 | |
655 | impl AsMut<BStr> for [u8] { |
656 | #[inline ] |
657 | fn as_mut(&mut self) -> &mut BStr { |
658 | BStr::new_mut(self) |
659 | } |
660 | } |
661 | |
662 | impl Borrow<BStr> for [u8] { |
663 | #[inline ] |
664 | fn borrow(&self) -> &BStr { |
665 | self.as_bstr() |
666 | } |
667 | } |
668 | |
669 | impl Borrow<BStr> for str { |
670 | #[inline ] |
671 | fn borrow(&self) -> &BStr { |
672 | self.as_bytes().as_bstr() |
673 | } |
674 | } |
675 | |
676 | impl Borrow<[u8]> for BStr { |
677 | #[inline ] |
678 | fn borrow(&self) -> &[u8] { |
679 | self.as_bytes() |
680 | } |
681 | } |
682 | |
683 | impl BorrowMut<BStr> for [u8] { |
684 | #[inline ] |
685 | fn borrow_mut(&mut self) -> &mut BStr { |
686 | BStr::new_mut(self) |
687 | } |
688 | } |
689 | |
690 | impl BorrowMut<[u8]> for BStr { |
691 | #[inline ] |
692 | fn borrow_mut(&mut self) -> &mut [u8] { |
693 | self.as_bytes_mut() |
694 | } |
695 | } |
696 | |
697 | impl<'a> Default for &'a BStr { |
698 | fn default() -> &'a BStr { |
699 | BStr::from_bytes(b"" ) |
700 | } |
701 | } |
702 | |
703 | impl<'a> Default for &'a mut BStr { |
704 | fn default() -> &'a mut BStr { |
705 | BStr::from_bytes_mut(&mut []) |
706 | } |
707 | } |
708 | |
709 | impl<'a, const N: usize> From<&'a [u8; N]> for &'a BStr { |
710 | #[inline ] |
711 | fn from(s: &'a [u8; N]) -> &'a BStr { |
712 | BStr::from_bytes(s) |
713 | } |
714 | } |
715 | |
716 | impl<'a> From<&'a [u8]> for &'a BStr { |
717 | #[inline ] |
718 | fn from(s: &'a [u8]) -> &'a BStr { |
719 | BStr::from_bytes(s) |
720 | } |
721 | } |
722 | |
723 | impl<'a> From<&'a BStr> for &'a [u8] { |
724 | #[inline ] |
725 | fn from(s: &'a BStr) -> &'a [u8] { |
726 | BStr::as_bytes(s) |
727 | } |
728 | } |
729 | |
730 | impl<'a> From<&'a str> for &'a BStr { |
731 | #[inline ] |
732 | fn from(s: &'a str) -> &'a BStr { |
733 | BStr::from_bytes(s.as_bytes()) |
734 | } |
735 | } |
736 | |
737 | #[cfg (feature = "alloc" )] |
738 | impl<'a> From<&'a BStr> for Cow<'a, BStr> { |
739 | #[inline ] |
740 | fn from(s: &'a BStr) -> Cow<'a, BStr> { |
741 | Cow::Borrowed(s) |
742 | } |
743 | } |
744 | |
745 | #[cfg (feature = "alloc" )] |
746 | impl From<Box<[u8]>> for Box<BStr> { |
747 | #[inline ] |
748 | fn from(s: Box<[u8]>) -> Box<BStr> { |
749 | BStr::from_boxed_bytes(s) |
750 | } |
751 | } |
752 | |
753 | #[cfg (feature = "alloc" )] |
754 | impl From<Box<BStr>> for Box<[u8]> { |
755 | #[inline ] |
756 | fn from(s: Box<BStr>) -> Box<[u8]> { |
757 | BStr::into_boxed_bytes(s) |
758 | } |
759 | } |
760 | |
761 | impl<'a> TryFrom<&'a BStr> for &'a str { |
762 | type Error = crate::Utf8Error; |
763 | |
764 | #[inline ] |
765 | fn try_from(s: &'a BStr) -> Result<&'a str, crate::Utf8Error> { |
766 | s.as_bytes().to_str() |
767 | } |
768 | } |
769 | |
770 | #[cfg (feature = "alloc" )] |
771 | impl<'a> TryFrom<&'a BStr> for String { |
772 | type Error = crate::Utf8Error; |
773 | |
774 | #[inline ] |
775 | fn try_from(s: &'a BStr) -> Result<String, crate::Utf8Error> { |
776 | Ok(s.as_bytes().to_str()?.into()) |
777 | } |
778 | } |
779 | |
780 | #[cfg (feature = "alloc" )] |
781 | impl Clone for Box<BStr> { |
782 | #[inline ] |
783 | fn clone(&self) -> Self { |
784 | BStr::from_boxed_bytes(self.as_bytes().into()) |
785 | } |
786 | } |
787 | |
788 | impl Eq for BStr {} |
789 | |
790 | impl PartialEq<BStr> for BStr { |
791 | #[inline ] |
792 | fn eq(&self, other: &BStr) -> bool { |
793 | self.as_bytes() == other.as_bytes() |
794 | } |
795 | } |
796 | |
797 | impl_partial_eq!(BStr, [u8]); |
798 | impl_partial_eq!(BStr, &'a [u8]); |
799 | impl_partial_eq!(BStr, str); |
800 | impl_partial_eq!(BStr, &'a str); |
801 | |
802 | #[cfg (feature = "alloc" )] |
803 | impl_partial_eq!(BStr, Vec<u8>); |
804 | #[cfg (feature = "alloc" )] |
805 | impl_partial_eq!(&'a BStr, Vec<u8>); |
806 | #[cfg (feature = "alloc" )] |
807 | impl_partial_eq!(BStr, String); |
808 | #[cfg (feature = "alloc" )] |
809 | impl_partial_eq!(&'a BStr, String); |
810 | #[cfg (feature = "alloc" )] |
811 | impl_partial_eq_cow!(&'a BStr, Cow<'a, BStr>); |
812 | #[cfg (feature = "alloc" )] |
813 | impl_partial_eq_cow!(&'a BStr, Cow<'a, str>); |
814 | #[cfg (feature = "alloc" )] |
815 | impl_partial_eq_cow!(&'a BStr, Cow<'a, [u8]>); |
816 | |
817 | impl PartialOrd for BStr { |
818 | #[inline ] |
819 | fn partial_cmp(&self, other: &BStr) -> Option<Ordering> { |
820 | PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes()) |
821 | } |
822 | } |
823 | |
824 | impl Ord for BStr { |
825 | #[inline ] |
826 | fn cmp(&self, other: &BStr) -> Ordering { |
827 | self.partial_cmp(other).unwrap() |
828 | } |
829 | } |
830 | |
831 | impl_partial_ord!(BStr, [u8]); |
832 | impl_partial_ord!(BStr, &'a [u8]); |
833 | impl_partial_ord!(BStr, str); |
834 | impl_partial_ord!(BStr, &'a str); |
835 | |
836 | #[cfg (feature = "alloc" )] |
837 | impl_partial_ord!(BStr, Vec<u8>); |
838 | #[cfg (feature = "alloc" )] |
839 | impl_partial_ord!(&'a BStr, Vec<u8>); |
840 | #[cfg (feature = "alloc" )] |
841 | impl_partial_ord!(BStr, String); |
842 | #[cfg (feature = "alloc" )] |
843 | impl_partial_ord!(&'a BStr, String); |
844 | } |
845 | |
846 | #[cfg (feature = "serde" )] |
847 | mod bstr_serde { |
848 | use core::fmt; |
849 | |
850 | use serde::{ |
851 | de::Error, de::Visitor, Deserialize, Deserializer, Serialize, |
852 | Serializer, |
853 | }; |
854 | |
855 | use crate::bstr::BStr; |
856 | |
857 | impl Serialize for BStr { |
858 | #[inline ] |
859 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
860 | where |
861 | S: Serializer, |
862 | { |
863 | serializer.serialize_bytes(self.as_bytes()) |
864 | } |
865 | } |
866 | |
867 | impl<'a, 'de: 'a> Deserialize<'de> for &'a BStr { |
868 | #[inline ] |
869 | fn deserialize<D>(deserializer: D) -> Result<&'a BStr, D::Error> |
870 | where |
871 | D: Deserializer<'de>, |
872 | { |
873 | struct BStrVisitor; |
874 | |
875 | impl<'de> Visitor<'de> for BStrVisitor { |
876 | type Value = &'de BStr; |
877 | |
878 | fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { |
879 | f.write_str("a borrowed byte string" ) |
880 | } |
881 | |
882 | #[inline ] |
883 | fn visit_borrowed_bytes<E: Error>( |
884 | self, |
885 | value: &'de [u8], |
886 | ) -> Result<&'de BStr, E> { |
887 | Ok(BStr::new(value)) |
888 | } |
889 | |
890 | #[inline ] |
891 | fn visit_borrowed_str<E: Error>( |
892 | self, |
893 | value: &'de str, |
894 | ) -> Result<&'de BStr, E> { |
895 | Ok(BStr::new(value)) |
896 | } |
897 | } |
898 | |
899 | deserializer.deserialize_bytes(BStrVisitor) |
900 | } |
901 | } |
902 | } |
903 | |
904 | #[cfg (all(feature = "serde" , feature = "alloc" ))] |
905 | mod bstring_serde { |
906 | use core::{cmp, fmt}; |
907 | |
908 | use alloc::{boxed::Box, string::String, vec::Vec}; |
909 | |
910 | use serde::{ |
911 | de::Error, de::SeqAccess, de::Visitor, Deserialize, Deserializer, |
912 | Serialize, Serializer, |
913 | }; |
914 | |
915 | use crate::{bstr::BStr, bstring::BString}; |
916 | |
917 | impl Serialize for BString { |
918 | #[inline ] |
919 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
920 | where |
921 | S: Serializer, |
922 | { |
923 | serializer.serialize_bytes(self.as_bytes()) |
924 | } |
925 | } |
926 | |
927 | impl<'de> Deserialize<'de> for BString { |
928 | #[inline ] |
929 | fn deserialize<D>(deserializer: D) -> Result<BString, D::Error> |
930 | where |
931 | D: Deserializer<'de>, |
932 | { |
933 | struct BStringVisitor; |
934 | |
935 | impl<'de> Visitor<'de> for BStringVisitor { |
936 | type Value = BString; |
937 | |
938 | fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { |
939 | f.write_str("a byte string" ) |
940 | } |
941 | |
942 | #[inline ] |
943 | fn visit_seq<V: SeqAccess<'de>>( |
944 | self, |
945 | mut visitor: V, |
946 | ) -> Result<BString, V::Error> { |
947 | let len = cmp::min(visitor.size_hint().unwrap_or(0), 256); |
948 | let mut bytes = Vec::with_capacity(len); |
949 | while let Some(v) = visitor.next_element()? { |
950 | bytes.push(v); |
951 | } |
952 | Ok(BString::from(bytes)) |
953 | } |
954 | |
955 | #[inline ] |
956 | fn visit_bytes<E: Error>( |
957 | self, |
958 | value: &[u8], |
959 | ) -> Result<BString, E> { |
960 | Ok(BString::from(value)) |
961 | } |
962 | |
963 | #[inline ] |
964 | fn visit_byte_buf<E: Error>( |
965 | self, |
966 | value: Vec<u8>, |
967 | ) -> Result<BString, E> { |
968 | Ok(BString::from(value)) |
969 | } |
970 | |
971 | #[inline ] |
972 | fn visit_str<E: Error>( |
973 | self, |
974 | value: &str, |
975 | ) -> Result<BString, E> { |
976 | Ok(BString::from(value)) |
977 | } |
978 | |
979 | #[inline ] |
980 | fn visit_string<E: Error>( |
981 | self, |
982 | value: String, |
983 | ) -> Result<BString, E> { |
984 | Ok(BString::from(value)) |
985 | } |
986 | } |
987 | |
988 | deserializer.deserialize_byte_buf(BStringVisitor) |
989 | } |
990 | } |
991 | |
992 | impl<'de> Deserialize<'de> for Box<BStr> { |
993 | #[inline ] |
994 | fn deserialize<D>(deserializer: D) -> Result<Box<BStr>, D::Error> |
995 | where |
996 | D: Deserializer<'de>, |
997 | { |
998 | struct BoxedBStrVisitor; |
999 | |
1000 | impl<'de> Visitor<'de> for BoxedBStrVisitor { |
1001 | type Value = Box<BStr>; |
1002 | |
1003 | fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1004 | f.write_str("a boxed byte string" ) |
1005 | } |
1006 | |
1007 | #[inline ] |
1008 | fn visit_seq<V: SeqAccess<'de>>( |
1009 | self, |
1010 | mut visitor: V, |
1011 | ) -> Result<Box<BStr>, V::Error> { |
1012 | let len = cmp::min(visitor.size_hint().unwrap_or(0), 256); |
1013 | let mut bytes = Vec::with_capacity(len); |
1014 | while let Some(v) = visitor.next_element()? { |
1015 | bytes.push(v); |
1016 | } |
1017 | Ok(BStr::from_boxed_bytes(bytes.into_boxed_slice())) |
1018 | } |
1019 | |
1020 | #[inline ] |
1021 | fn visit_bytes<E: Error>( |
1022 | self, |
1023 | value: &[u8], |
1024 | ) -> Result<Box<BStr>, E> { |
1025 | Ok(BStr::from_boxed_bytes( |
1026 | value.to_vec().into_boxed_slice(), |
1027 | )) |
1028 | } |
1029 | |
1030 | #[inline ] |
1031 | fn visit_byte_buf<E: Error>( |
1032 | self, |
1033 | value: Vec<u8>, |
1034 | ) -> Result<Box<BStr>, E> { |
1035 | Ok(BStr::from_boxed_bytes(value.into_boxed_slice())) |
1036 | } |
1037 | |
1038 | #[inline ] |
1039 | fn visit_str<E: Error>( |
1040 | self, |
1041 | value: &str, |
1042 | ) -> Result<Box<BStr>, E> { |
1043 | Ok(BStr::from_boxed_bytes( |
1044 | value.as_bytes().to_vec().into_boxed_slice(), |
1045 | )) |
1046 | } |
1047 | |
1048 | #[inline ] |
1049 | fn visit_string<E: Error>( |
1050 | self, |
1051 | value: String, |
1052 | ) -> Result<Box<BStr>, E> { |
1053 | Ok(BStr::from_boxed_bytes( |
1054 | value.into_bytes().into_boxed_slice(), |
1055 | )) |
1056 | } |
1057 | } |
1058 | |
1059 | deserializer.deserialize_byte_buf(BoxedBStrVisitor) |
1060 | } |
1061 | } |
1062 | } |
1063 | |
1064 | #[cfg (all(test, feature = "std" ))] |
1065 | mod display { |
1066 | #[cfg (not(miri))] |
1067 | use crate::bstring::BString; |
1068 | use crate::ByteSlice; |
1069 | |
1070 | #[test ] |
1071 | fn clean() { |
1072 | assert_eq!(&format!(" {}" , &b"abc" .as_bstr()), "abc" ); |
1073 | assert_eq!(&format!(" {}" , &b" \xf0\x28\x8c\xbc" .as_bstr()), "�(��" ); |
1074 | } |
1075 | |
1076 | #[test ] |
1077 | fn width_bigger_than_bstr() { |
1078 | assert_eq!(&format!(" {:<7}!" , &b"abc" .as_bstr()), "abc !" ); |
1079 | assert_eq!(&format!(" {:>7}!" , &b"abc" .as_bstr()), " abc!" ); |
1080 | assert_eq!(&format!(" {:^7}!" , &b"abc" .as_bstr()), " abc !" ); |
1081 | assert_eq!(&format!(" {:^6}!" , &b"abc" .as_bstr()), " abc !" ); |
1082 | assert_eq!(&format!(" {:-<7}!" , &b"abc" .as_bstr()), "abc----!" ); |
1083 | assert_eq!(&format!(" {:->7}!" , &b"abc" .as_bstr()), "----abc!" ); |
1084 | assert_eq!(&format!(" {:-^7}!" , &b"abc" .as_bstr()), "--abc--!" ); |
1085 | assert_eq!(&format!(" {:-^6}!" , &b"abc" .as_bstr()), "-abc--!" ); |
1086 | |
1087 | assert_eq!( |
1088 | &format!(" {:<7}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1089 | "�(�� !" |
1090 | ); |
1091 | assert_eq!( |
1092 | &format!(" {:>7}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1093 | " �(��!" |
1094 | ); |
1095 | assert_eq!( |
1096 | &format!(" {:^7}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1097 | " �(�� !" |
1098 | ); |
1099 | assert_eq!( |
1100 | &format!(" {:^6}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1101 | " �(�� !" |
1102 | ); |
1103 | |
1104 | assert_eq!( |
1105 | &format!(" {:-<7}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1106 | "�(��---!" |
1107 | ); |
1108 | assert_eq!( |
1109 | &format!(" {:->7}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1110 | "---�(��!" |
1111 | ); |
1112 | assert_eq!( |
1113 | &format!(" {:-^7}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1114 | "-�(��--!" |
1115 | ); |
1116 | assert_eq!( |
1117 | &format!(" {:-^6}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1118 | "-�(��-!" |
1119 | ); |
1120 | } |
1121 | |
1122 | #[test ] |
1123 | fn width_lesser_than_bstr() { |
1124 | assert_eq!(&format!(" {:<2}!" , &b"abc" .as_bstr()), "abc!" ); |
1125 | assert_eq!(&format!(" {:>2}!" , &b"abc" .as_bstr()), "abc!" ); |
1126 | assert_eq!(&format!(" {:^2}!" , &b"abc" .as_bstr()), "abc!" ); |
1127 | assert_eq!(&format!(" {:-<2}!" , &b"abc" .as_bstr()), "abc!" ); |
1128 | assert_eq!(&format!(" {:->2}!" , &b"abc" .as_bstr()), "abc!" ); |
1129 | assert_eq!(&format!(" {:-^2}!" , &b"abc" .as_bstr()), "abc!" ); |
1130 | |
1131 | assert_eq!( |
1132 | &format!(" {:<3}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1133 | "�(��!" |
1134 | ); |
1135 | assert_eq!( |
1136 | &format!(" {:>3}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1137 | "�(��!" |
1138 | ); |
1139 | assert_eq!( |
1140 | &format!(" {:^3}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1141 | "�(��!" |
1142 | ); |
1143 | assert_eq!( |
1144 | &format!(" {:^2}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1145 | "�(��!" |
1146 | ); |
1147 | |
1148 | assert_eq!( |
1149 | &format!(" {:-<3}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1150 | "�(��!" |
1151 | ); |
1152 | assert_eq!( |
1153 | &format!(" {:->3}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1154 | "�(��!" |
1155 | ); |
1156 | assert_eq!( |
1157 | &format!(" {:-^3}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1158 | "�(��!" |
1159 | ); |
1160 | assert_eq!( |
1161 | &format!(" {:-^2}!" , &b" \xf0\x28\x8c\xbc" .as_bstr()), |
1162 | "�(��!" |
1163 | ); |
1164 | } |
1165 | |
1166 | #[cfg (not(miri))] |
1167 | quickcheck::quickcheck! { |
1168 | fn total_length(bstr: BString) -> bool { |
1169 | let size = bstr.chars().count(); |
1170 | format!("{:<1$}" , bstr.as_bstr(), size).chars().count() >= size |
1171 | } |
1172 | } |
1173 | } |
1174 | |
1175 | #[cfg (all(test, feature = "alloc" ))] |
1176 | mod bstring_arbitrary { |
1177 | use crate::bstring::BString; |
1178 | |
1179 | use quickcheck::{Arbitrary, Gen}; |
1180 | |
1181 | impl Arbitrary for BString { |
1182 | fn arbitrary(g: &mut Gen) -> BString { |
1183 | BString::from(Vec::<u8>::arbitrary(g)) |
1184 | } |
1185 | |
1186 | fn shrink(&self) -> Box<dyn Iterator<Item = BString>> { |
1187 | Box::new(self.as_vec().shrink().map(BString::from)) |
1188 | } |
1189 | } |
1190 | } |
1191 | |
1192 | #[test ] |
1193 | #[cfg (feature = "std" )] |
1194 | fn test_debug() { |
1195 | use crate::{ByteSlice, B}; |
1196 | |
1197 | assert_eq!( |
1198 | r#""\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp""# , |
1199 | format!(" {:?}" , b" \0\0\0 ftypisom \0\0\x02\0isomiso2avc1mp" .as_bstr()), |
1200 | ); |
1201 | |
1202 | // Tests that if the underlying bytes contain the UTF-8 encoding of the |
1203 | // replacement codepoint, then we emit the codepoint just like other |
1204 | // non-printable Unicode characters. |
1205 | assert_eq!( |
1206 | b" \"\\xFF \xEF\xBF\xBD\\xFF \"" .as_bstr(), |
1207 | // Before fixing #72, the output here would be: |
1208 | // \\xFF\\xEF\\xBF\\xBD\\xFF |
1209 | B(&format!(" {:?}" , b" \xFF\xEF\xBF\xBD\xFF" .as_bstr())).as_bstr(), |
1210 | ); |
1211 | } |
1212 | |
1213 | // See: https://github.com/BurntSushi/bstr/issues/82 |
1214 | #[test ] |
1215 | #[cfg (feature = "std" )] |
1216 | fn test_cows_regression() { |
1217 | use std::borrow::Cow; |
1218 | |
1219 | use crate::ByteSlice; |
1220 | |
1221 | let c1: Cow<'_, BStr> = Cow::from(b"hello bstr" .as_bstr()); |
1222 | let c2: &BStr = b"goodbye bstr" .as_bstr(); |
1223 | assert_ne!(c1, c2); |
1224 | |
1225 | let c3: Cow<'_, str> = Cow::from("hello str" ); |
1226 | let c4: &str = "goodbye str" ; |
1227 | assert_ne!(c3, c4); |
1228 | } |
1229 | |