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