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