bstr/
impls.rs

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            /// Write the given bstr (lossily) to the given formatter.
405            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            /// Write 'num' fill characters to the given formatter.
419            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                    // ASCII control characters except \0, \n, \r, \t
481                    '\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    // Tests that if the underlying bytes contain the UTF-8 encoding of the
1221    // replacement codepoint, then we emit the codepoint just like other
1222    // non-printable Unicode characters.
1223    assert_eq!(
1224        b"\"\\xFF\xEF\xBF\xBD\\xFF\"".as_bstr(),
1225        // Before fixing #72, the output here would be:
1226        //   \\xFF\\xEF\\xBF\\xBD\\xFF
1227        B(&format!("{:?}", b"\xFF\xEF\xBF\xBD\xFF".as_bstr())).as_bstr(),
1228    );
1229}
1230
1231// See: https://github.com/BurntSushi/bstr/issues/82
1232#[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}