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 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 '\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 '\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 assert_eq!(
1296 b"\"\\xff\xef\xbf\xbd\\xff\"".as_bstr(),
1297 B(&format!("{:?}", b"\xff\xef\xbf\xbd\xff".as_bstr())).as_bstr(),
1300 );
1301
1302 assert_eq!(
1304 b"\"\\xed\\xa0\\x80Aa\\x7f\\x0b\"".as_bstr(),
1305 B(&format!("{:?}", b"\xed\xa0\x80Aa\x7f\x0b".as_bstr())).as_bstr(),
1308 )
1309}
1310
1311#[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}