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