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