1macro_rules! impl_partial_eq {
2 ($lhs:ty, $rhs:ty) => {
3 impl<'a> 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> 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, 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, 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> 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> PartialEq<$lhs> for $rhs {
53 #[inline]
54 fn eq(&self, other: &$lhs) -> bool {
55 let this: &[u8] = (&**self).as_ref();
56 PartialEq::eq(this, other.as_bytes())
57 }
58 }
59 };
60}
61
62macro_rules! impl_partial_ord {
63 ($lhs:ty, $rhs:ty) => {
64 impl<'a> 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> 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, 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, 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 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 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 '\x01'..='\x7f' => {
529 write!(f, "{}", (ch as u8).escape_ascii())?;
530 }
531 '\u{FFFD}' => {
532 let bytes = self[s..e].as_bytes();
533 if bytes == b"\xEF\xBF\xBD" {
534 write!(f, "{}", ch.escape_debug())?;
535 } else {
536 for &b in self[s..e].as_bytes() {
537 write!(f, "\\x{:02x}", b)?;
538 }
539 }
540 }
541 _ => {
542 write!(f, "{}", ch.escape_debug())?;
543 }
544 }
545 }
546 write!(f, "\"")?;
547 Ok(())
548 }
549 }
550
551 impl ops::Deref for BStr {
552 type Target = [u8];
553
554 #[inline]
555 fn deref(&self) -> &[u8] {
556 &self.bytes
557 }
558 }
559
560 impl ops::DerefMut for BStr {
561 #[inline]
562 fn deref_mut(&mut self) -> &mut [u8] {
563 &mut self.bytes
564 }
565 }
566
567 impl ops::Index<usize> for BStr {
568 type Output = u8;
569
570 #[inline]
571 fn index(&self, idx: usize) -> &u8 {
572 &self.as_bytes()[idx]
573 }
574 }
575
576 impl ops::Index<ops::RangeFull> for BStr {
577 type Output = BStr;
578
579 #[inline]
580 fn index(&self, _: ops::RangeFull) -> &BStr {
581 self
582 }
583 }
584
585 impl ops::Index<ops::Range<usize>> for BStr {
586 type Output = BStr;
587
588 #[inline]
589 fn index(&self, r: ops::Range<usize>) -> &BStr {
590 BStr::new(&self.as_bytes()[r.start..r.end])
591 }
592 }
593
594 impl ops::Index<ops::RangeInclusive<usize>> for BStr {
595 type Output = BStr;
596
597 #[inline]
598 fn index(&self, r: ops::RangeInclusive<usize>) -> &BStr {
599 BStr::new(&self.as_bytes()[*r.start()..=*r.end()])
600 }
601 }
602
603 impl ops::Index<ops::RangeFrom<usize>> for BStr {
604 type Output = BStr;
605
606 #[inline]
607 fn index(&self, r: ops::RangeFrom<usize>) -> &BStr {
608 BStr::new(&self.as_bytes()[r.start..])
609 }
610 }
611
612 impl ops::Index<ops::RangeTo<usize>> for BStr {
613 type Output = BStr;
614
615 #[inline]
616 fn index(&self, r: ops::RangeTo<usize>) -> &BStr {
617 BStr::new(&self.as_bytes()[..r.end])
618 }
619 }
620
621 impl ops::Index<ops::RangeToInclusive<usize>> for BStr {
622 type Output = BStr;
623
624 #[inline]
625 fn index(&self, r: ops::RangeToInclusive<usize>) -> &BStr {
626 BStr::new(&self.as_bytes()[..=r.end])
627 }
628 }
629
630 impl ops::IndexMut<usize> for BStr {
631 #[inline]
632 fn index_mut(&mut self, idx: usize) -> &mut u8 {
633 &mut self.bytes[idx]
634 }
635 }
636
637 impl ops::IndexMut<ops::RangeFull> for BStr {
638 #[inline]
639 fn index_mut(&mut self, _: ops::RangeFull) -> &mut BStr {
640 self
641 }
642 }
643
644 impl ops::IndexMut<ops::Range<usize>> for BStr {
645 #[inline]
646 fn index_mut(&mut self, r: ops::Range<usize>) -> &mut BStr {
647 BStr::from_bytes_mut(&mut self.bytes[r.start..r.end])
648 }
649 }
650
651 impl ops::IndexMut<ops::RangeInclusive<usize>> for BStr {
652 #[inline]
653 fn index_mut(&mut self, r: ops::RangeInclusive<usize>) -> &mut BStr {
654 BStr::from_bytes_mut(&mut self.bytes[*r.start()..=*r.end()])
655 }
656 }
657
658 impl ops::IndexMut<ops::RangeFrom<usize>> for BStr {
659 #[inline]
660 fn index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut BStr {
661 BStr::from_bytes_mut(&mut self.bytes[r.start..])
662 }
663 }
664
665 impl ops::IndexMut<ops::RangeTo<usize>> for BStr {
666 #[inline]
667 fn index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut BStr {
668 BStr::from_bytes_mut(&mut self.bytes[..r.end])
669 }
670 }
671
672 impl ops::IndexMut<ops::RangeToInclusive<usize>> for BStr {
673 #[inline]
674 fn index_mut(&mut self, r: ops::RangeToInclusive<usize>) -> &mut BStr {
675 BStr::from_bytes_mut(&mut self.bytes[..=r.end])
676 }
677 }
678
679 impl AsRef<[u8]> for BStr {
680 #[inline]
681 fn as_ref(&self) -> &[u8] {
682 self.as_bytes()
683 }
684 }
685
686 impl AsRef<BStr> for BStr {
687 #[inline]
688 fn as_ref(&self) -> &BStr {
689 self
690 }
691 }
692
693 impl AsRef<BStr> for [u8] {
694 #[inline]
695 fn as_ref(&self) -> &BStr {
696 BStr::new(self)
697 }
698 }
699
700 impl AsRef<BStr> for str {
701 #[inline]
702 fn as_ref(&self) -> &BStr {
703 BStr::new(self)
704 }
705 }
706
707 impl AsMut<[u8]> for BStr {
708 #[inline]
709 fn as_mut(&mut self) -> &mut [u8] {
710 &mut self.bytes
711 }
712 }
713
714 impl AsMut<BStr> for [u8] {
715 #[inline]
716 fn as_mut(&mut self) -> &mut BStr {
717 BStr::new_mut(self)
718 }
719 }
720
721 impl Borrow<BStr> for [u8] {
722 #[inline]
723 fn borrow(&self) -> &BStr {
724 self.as_bstr()
725 }
726 }
727
728 impl Borrow<BStr> for str {
729 #[inline]
730 fn borrow(&self) -> &BStr {
731 self.as_bytes().as_bstr()
732 }
733 }
734
735 impl Borrow<[u8]> for BStr {
736 #[inline]
737 fn borrow(&self) -> &[u8] {
738 self.as_bytes()
739 }
740 }
741
742 impl BorrowMut<BStr> for [u8] {
743 #[inline]
744 fn borrow_mut(&mut self) -> &mut BStr {
745 BStr::new_mut(self)
746 }
747 }
748
749 impl BorrowMut<[u8]> for BStr {
750 #[inline]
751 fn borrow_mut(&mut self) -> &mut [u8] {
752 self.as_bytes_mut()
753 }
754 }
755
756 impl<'a> Default for &'a BStr {
757 fn default() -> &'a BStr {
758 BStr::from_bytes(b"")
759 }
760 }
761
762 impl<'a> Default for &'a mut BStr {
763 fn default() -> &'a mut BStr {
764 BStr::from_bytes_mut(&mut [])
765 }
766 }
767
768 impl<'a, const N: usize> From<&'a [u8; N]> for &'a BStr {
769 #[inline]
770 fn from(s: &'a [u8; N]) -> &'a BStr {
771 BStr::from_bytes(s)
772 }
773 }
774
775 impl<'a> From<&'a [u8]> for &'a BStr {
776 #[inline]
777 fn from(s: &'a [u8]) -> &'a BStr {
778 BStr::from_bytes(s)
779 }
780 }
781
782 impl<'a> From<&'a BStr> for &'a [u8] {
783 #[inline]
784 fn from(s: &'a BStr) -> &'a [u8] {
785 BStr::as_bytes(s)
786 }
787 }
788
789 impl<'a> From<&'a str> for &'a BStr {
790 #[inline]
791 fn from(s: &'a str) -> &'a BStr {
792 BStr::from_bytes(s.as_bytes())
793 }
794 }
795
796 #[cfg(feature = "alloc")]
797 impl<'a> From<&'a BStr> for Cow<'a, BStr> {
798 #[inline]
799 fn from(s: &'a BStr) -> Cow<'a, BStr> {
800 Cow::Borrowed(s)
801 }
802 }
803
804 #[cfg(feature = "alloc")]
805 impl From<Box<[u8]>> for Box<BStr> {
806 #[inline]
807 fn from(s: Box<[u8]>) -> Box<BStr> {
808 BStr::from_boxed_bytes(s)
809 }
810 }
811
812 #[cfg(feature = "alloc")]
813 impl From<Box<BStr>> for Box<[u8]> {
814 #[inline]
815 fn from(s: Box<BStr>) -> Box<[u8]> {
816 BStr::into_boxed_bytes(s)
817 }
818 }
819
820 impl<'a> TryFrom<&'a BStr> for &'a str {
821 type Error = crate::Utf8Error;
822
823 #[inline]
824 fn try_from(s: &'a BStr) -> Result<&'a str, crate::Utf8Error> {
825 s.as_bytes().to_str()
826 }
827 }
828
829 #[cfg(feature = "alloc")]
830 impl<'a> TryFrom<&'a BStr> for String {
831 type Error = crate::Utf8Error;
832
833 #[inline]
834 fn try_from(s: &'a BStr) -> Result<String, crate::Utf8Error> {
835 Ok(s.as_bytes().to_str()?.into())
836 }
837 }
838
839 #[cfg(feature = "alloc")]
840 impl Clone for Box<BStr> {
841 #[inline]
842 fn clone(&self) -> Self {
843 BStr::from_boxed_bytes(self.as_bytes().into())
844 }
845 }
846
847 impl Eq for BStr {}
848
849 impl PartialEq<BStr> for BStr {
850 #[inline]
851 fn eq(&self, other: &BStr) -> bool {
852 self.as_bytes() == other.as_bytes()
853 }
854 }
855
856 impl_partial_eq!(BStr, [u8]);
857 impl_partial_eq!(BStr, &'a [u8]);
858 impl_partial_eq!(BStr, str);
859 impl_partial_eq!(BStr, &'a str);
860 impl_partial_eq_n!(BStr, [u8; N]);
861 impl_partial_eq_n!(BStr, &'a [u8; N]);
862
863 #[cfg(feature = "alloc")]
864 impl_partial_eq!(BStr, Vec<u8>);
865 #[cfg(feature = "alloc")]
866 impl_partial_eq!(&'a BStr, Vec<u8>);
867 #[cfg(feature = "alloc")]
868 impl_partial_eq!(BStr, String);
869 #[cfg(feature = "alloc")]
870 impl_partial_eq!(&'a BStr, String);
871 #[cfg(feature = "alloc")]
872 impl_partial_eq_cow!(&'a BStr, Cow<'a, BStr>);
873 #[cfg(feature = "alloc")]
874 impl_partial_eq_cow!(&'a BStr, Cow<'a, str>);
875 #[cfg(feature = "alloc")]
876 impl_partial_eq_cow!(&'a BStr, Cow<'a, [u8]>);
877
878 impl hash::Hash for BStr {
879 #[inline]
880 fn hash<H: hash::Hasher>(&self, state: &mut H) {
881 self.as_bytes().hash(state);
882 }
883 }
884
885 impl PartialOrd for BStr {
886 #[inline]
887 fn partial_cmp(&self, other: &BStr) -> Option<Ordering> {
888 PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes())
889 }
890 }
891
892 impl Ord for BStr {
893 #[inline]
894 fn cmp(&self, other: &BStr) -> Ordering {
895 self.partial_cmp(other).unwrap()
896 }
897 }
898
899 impl_partial_ord!(BStr, [u8]);
900 impl_partial_ord!(BStr, &'a [u8]);
901 impl_partial_ord!(BStr, str);
902 impl_partial_ord!(BStr, &'a str);
903 impl_partial_ord_n!(BStr, [u8; N]);
904 impl_partial_ord_n!(BStr, &'a [u8; N]);
905
906 #[cfg(feature = "alloc")]
907 impl_partial_ord!(BStr, Vec<u8>);
908 #[cfg(feature = "alloc")]
909 impl_partial_ord!(&'a BStr, Vec<u8>);
910 #[cfg(feature = "alloc")]
911 impl_partial_ord!(BStr, String);
912 #[cfg(feature = "alloc")]
913 impl_partial_ord!(&'a BStr, String);
914}
915
916#[cfg(feature = "serde")]
917mod bstr_serde {
918 use core::fmt;
919
920 use serde::{
921 de::Error, de::Visitor, Deserialize, Deserializer, Serialize,
922 Serializer,
923 };
924
925 use crate::bstr::BStr;
926
927 impl Serialize for BStr {
928 #[inline]
929 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
930 where
931 S: Serializer,
932 {
933 serializer.serialize_bytes(self.as_bytes())
934 }
935 }
936
937 impl<'a, 'de: 'a> Deserialize<'de> for &'a BStr {
938 #[inline]
939 fn deserialize<D>(deserializer: D) -> Result<&'a BStr, D::Error>
940 where
941 D: Deserializer<'de>,
942 {
943 struct BStrVisitor;
944
945 impl<'de> Visitor<'de> for BStrVisitor {
946 type Value = &'de BStr;
947
948 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
949 f.write_str("a borrowed byte string")
950 }
951
952 #[inline]
953 fn visit_borrowed_bytes<E: Error>(
954 self,
955 value: &'de [u8],
956 ) -> Result<&'de BStr, E> {
957 Ok(BStr::new(value))
958 }
959
960 #[inline]
961 fn visit_borrowed_str<E: Error>(
962 self,
963 value: &'de str,
964 ) -> Result<&'de BStr, E> {
965 Ok(BStr::new(value))
966 }
967 }
968
969 deserializer.deserialize_bytes(BStrVisitor)
970 }
971 }
972}
973
974#[cfg(all(feature = "serde", feature = "alloc"))]
975mod bstring_serde {
976 use core::{cmp, fmt};
977
978 use alloc::{boxed::Box, string::String, vec::Vec};
979
980 use serde::{
981 de::Error, de::SeqAccess, de::Visitor, Deserialize, Deserializer,
982 Serialize, Serializer,
983 };
984
985 use crate::{bstr::BStr, bstring::BString};
986
987 impl Serialize for BString {
988 #[inline]
989 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
990 where
991 S: Serializer,
992 {
993 serializer.serialize_bytes(self.as_bytes())
994 }
995 }
996
997 impl<'de> Deserialize<'de> for BString {
998 #[inline]
999 fn deserialize<D>(deserializer: D) -> Result<BString, D::Error>
1000 where
1001 D: Deserializer<'de>,
1002 {
1003 struct BStringVisitor;
1004
1005 impl<'de> Visitor<'de> for BStringVisitor {
1006 type Value = BString;
1007
1008 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
1009 f.write_str("a byte string")
1010 }
1011
1012 #[inline]
1013 fn visit_seq<V: SeqAccess<'de>>(
1014 self,
1015 mut visitor: V,
1016 ) -> Result<BString, V::Error> {
1017 let len = cmp::min(visitor.size_hint().unwrap_or(0), 256);
1018 let mut bytes = Vec::with_capacity(len);
1019 while let Some(v) = visitor.next_element()? {
1020 bytes.push(v);
1021 }
1022 Ok(BString::from(bytes))
1023 }
1024
1025 #[inline]
1026 fn visit_bytes<E: Error>(
1027 self,
1028 value: &[u8],
1029 ) -> Result<BString, E> {
1030 Ok(BString::from(value))
1031 }
1032
1033 #[inline]
1034 fn visit_byte_buf<E: Error>(
1035 self,
1036 value: Vec<u8>,
1037 ) -> Result<BString, E> {
1038 Ok(BString::from(value))
1039 }
1040
1041 #[inline]
1042 fn visit_str<E: Error>(
1043 self,
1044 value: &str,
1045 ) -> Result<BString, E> {
1046 Ok(BString::from(value))
1047 }
1048
1049 #[inline]
1050 fn visit_string<E: Error>(
1051 self,
1052 value: String,
1053 ) -> Result<BString, E> {
1054 Ok(BString::from(value))
1055 }
1056 }
1057
1058 deserializer.deserialize_byte_buf(BStringVisitor)
1059 }
1060 }
1061
1062 impl<'de> Deserialize<'de> for Box<BStr> {
1063 #[inline]
1064 fn deserialize<D>(deserializer: D) -> Result<Box<BStr>, D::Error>
1065 where
1066 D: Deserializer<'de>,
1067 {
1068 struct BoxedBStrVisitor;
1069
1070 impl<'de> Visitor<'de> for BoxedBStrVisitor {
1071 type Value = Box<BStr>;
1072
1073 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
1074 f.write_str("a boxed byte string")
1075 }
1076
1077 #[inline]
1078 fn visit_seq<V: SeqAccess<'de>>(
1079 self,
1080 mut visitor: V,
1081 ) -> Result<Box<BStr>, V::Error> {
1082 let len = cmp::min(visitor.size_hint().unwrap_or(0), 256);
1083 let mut bytes = Vec::with_capacity(len);
1084 while let Some(v) = visitor.next_element()? {
1085 bytes.push(v);
1086 }
1087 Ok(BStr::from_boxed_bytes(bytes.into_boxed_slice()))
1088 }
1089
1090 #[inline]
1091 fn visit_bytes<E: Error>(
1092 self,
1093 value: &[u8],
1094 ) -> Result<Box<BStr>, E> {
1095 Ok(BStr::from_boxed_bytes(
1096 value.to_vec().into_boxed_slice(),
1097 ))
1098 }
1099
1100 #[inline]
1101 fn visit_byte_buf<E: Error>(
1102 self,
1103 value: Vec<u8>,
1104 ) -> Result<Box<BStr>, E> {
1105 Ok(BStr::from_boxed_bytes(value.into_boxed_slice()))
1106 }
1107
1108 #[inline]
1109 fn visit_str<E: Error>(
1110 self,
1111 value: &str,
1112 ) -> Result<Box<BStr>, E> {
1113 Ok(BStr::from_boxed_bytes(
1114 value.as_bytes().to_vec().into_boxed_slice(),
1115 ))
1116 }
1117
1118 #[inline]
1119 fn visit_string<E: Error>(
1120 self,
1121 value: String,
1122 ) -> Result<Box<BStr>, E> {
1123 Ok(BStr::from_boxed_bytes(
1124 value.into_bytes().into_boxed_slice(),
1125 ))
1126 }
1127 }
1128
1129 deserializer.deserialize_byte_buf(BoxedBStrVisitor)
1130 }
1131 }
1132}
1133
1134#[cfg(all(test, feature = "std"))]
1135mod display {
1136 use alloc::format;
1137
1138 #[cfg(not(miri))]
1139 use crate::bstring::BString;
1140 use crate::ByteSlice;
1141
1142 #[test]
1143 fn clean() {
1144 assert_eq!(&format!("{}", &b"abc".as_bstr()), "abc");
1145 assert_eq!(&format!("{}", &b"\xf0\x28\x8c\xbc".as_bstr()), "�(��");
1146 }
1147
1148 #[test]
1149 fn from_str() {
1150 let s: BString = "abc".parse().unwrap();
1151 assert_eq!(s, BString::new(b"abc".to_vec()));
1152 }
1153
1154 #[test]
1155 fn width_bigger_than_bstr() {
1156 assert_eq!(&format!("{:<7}!", &b"abc".as_bstr()), "abc !");
1157 assert_eq!(&format!("{:>7}!", &b"abc".as_bstr()), " abc!");
1158 assert_eq!(&format!("{:^7}!", &b"abc".as_bstr()), " abc !");
1159 assert_eq!(&format!("{:^6}!", &b"abc".as_bstr()), " abc !");
1160 assert_eq!(&format!("{:-<7}!", &b"abc".as_bstr()), "abc----!");
1161 assert_eq!(&format!("{:->7}!", &b"abc".as_bstr()), "----abc!");
1162 assert_eq!(&format!("{:-^7}!", &b"abc".as_bstr()), "--abc--!");
1163 assert_eq!(&format!("{:-^6}!", &b"abc".as_bstr()), "-abc--!");
1164
1165 assert_eq!(
1166 &format!("{:<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1167 "�(�� !"
1168 );
1169 assert_eq!(
1170 &format!("{:>7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1171 " �(��!"
1172 );
1173 assert_eq!(
1174 &format!("{:^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1175 " �(�� !"
1176 );
1177 assert_eq!(
1178 &format!("{:^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1179 " �(�� !"
1180 );
1181
1182 assert_eq!(
1183 &format!("{:-<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1184 "�(��---!"
1185 );
1186 assert_eq!(
1187 &format!("{:->7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1188 "---�(��!"
1189 );
1190 assert_eq!(
1191 &format!("{:-^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1192 "-�(��--!"
1193 );
1194 assert_eq!(
1195 &format!("{:-^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1196 "-�(��-!"
1197 );
1198 }
1199
1200 #[test]
1201 fn width_lesser_than_bstr() {
1202 assert_eq!(&format!("{:<2}!", &b"abc".as_bstr()), "abc!");
1203 assert_eq!(&format!("{:>2}!", &b"abc".as_bstr()), "abc!");
1204 assert_eq!(&format!("{:^2}!", &b"abc".as_bstr()), "abc!");
1205 assert_eq!(&format!("{:-<2}!", &b"abc".as_bstr()), "abc!");
1206 assert_eq!(&format!("{:->2}!", &b"abc".as_bstr()), "abc!");
1207 assert_eq!(&format!("{:-^2}!", &b"abc".as_bstr()), "abc!");
1208
1209 assert_eq!(
1210 &format!("{:<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1211 "�(��!"
1212 );
1213 assert_eq!(
1214 &format!("{:>3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1215 "�(��!"
1216 );
1217 assert_eq!(
1218 &format!("{:^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1219 "�(��!"
1220 );
1221 assert_eq!(
1222 &format!("{:^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1223 "�(��!"
1224 );
1225
1226 assert_eq!(
1227 &format!("{:-<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1228 "�(��!"
1229 );
1230 assert_eq!(
1231 &format!("{:->3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1232 "�(��!"
1233 );
1234 assert_eq!(
1235 &format!("{:-^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1236 "�(��!"
1237 );
1238 assert_eq!(
1239 &format!("{:-^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
1240 "�(��!"
1241 );
1242 }
1243
1244 #[cfg(not(miri))]
1245 quickcheck::quickcheck! {
1246 fn total_length(bstr: BString) -> bool {
1247 let size = bstr.chars().count();
1248 format!("{:<1$}", bstr.as_bstr(), size).chars().count() >= size
1249 }
1250 }
1251}
1252
1253#[cfg(all(test, feature = "alloc"))]
1254mod bstring_arbitrary {
1255 use alloc::{boxed::Box, vec::Vec};
1256
1257 use crate::bstring::BString;
1258
1259 use quickcheck::{Arbitrary, Gen};
1260
1261 impl Arbitrary for BString {
1262 fn arbitrary(g: &mut Gen) -> BString {
1263 BString::from(Vec::<u8>::arbitrary(g))
1264 }
1265
1266 fn shrink(&self) -> Box<dyn Iterator<Item = BString>> {
1267 Box::new(self.as_vec().shrink().map(BString::from))
1268 }
1269 }
1270}
1271
1272#[test]
1273#[cfg(feature = "std")]
1274fn test_debug() {
1275 use alloc::format;
1276
1277 use crate::{ByteSlice, B};
1278
1279 assert_eq!(
1280 r#""\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp""#,
1281 format!("{:?}", b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp".as_bstr()),
1282 );
1283
1284 assert_eq!(
1288 b"\"\\xff\xef\xbf\xbd\\xff\"".as_bstr(),
1289 B(&format!("{:?}", b"\xff\xef\xbf\xbd\xff".as_bstr())).as_bstr(),
1292 );
1293
1294 assert_eq!(
1296 b"\"\\xed\\xa0\\x80Aa\\x7f\\x0b\"".as_bstr(),
1297 B(&format!("{:?}", b"\xed\xa0\x80Aa\x7f\x0b".as_bstr())).as_bstr(),
1300 );
1301
1302 assert_eq!(
1303 r#""\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff""#,
1304 format!("{:?}", b"\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff".as_bstr()),
1305 );
1306}
1307
1308#[test]
1310#[cfg(feature = "std")]
1311fn test_cows_regression() {
1312 use std::borrow::Cow;
1313
1314 use crate::ByteSlice;
1315
1316 let c1 = Cow::from(b"hello bstr".as_bstr());
1317 let c2 = b"goodbye bstr".as_bstr();
1318 assert_ne!(c1, c2);
1319
1320 let c3 = Cow::from("hello str");
1321 let c4 = "goodbye str";
1322 assert_ne!(c3, c4);
1323}
1324
1325#[test]
1326#[cfg(feature = "alloc")]
1327fn test_eq_ord() {
1328 use core::cmp::Ordering;
1329
1330 use crate::{BStr, BString};
1331
1332 let b = BStr::new("hello");
1333 assert_eq!(b, b"hello");
1334 assert_ne!(b, b"world");
1335 assert_eq!(b.partial_cmp(b"hello"), Some(Ordering::Equal));
1336 assert_eq!(b.partial_cmp(b"world"), Some(Ordering::Less));
1337
1338 let b = BString::from("hello");
1339 assert_eq!(b, b"hello");
1340 assert_ne!(b, b"world");
1341 assert_eq!(b.partial_cmp(b"hello"), Some(Ordering::Equal));
1342 assert_eq!(b.partial_cmp(b"world"), Some(Ordering::Less));
1343}