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