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