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 = "std")]
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 = "std")]
63 mod bstring {
64 use std::borrow::{Borrow, Cow, ToOwned};
65 use std::cmp::Ordering;
66 use std::fmt;
67 use std::iter::FromIterator;
68 use std::ops;
69
70 use bstr::BStr;
71 use bstring::BString;
72 use ext_vec::ByteVec;
73
74 impl fmt::Display for BString {
75 #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 fmt::Display::fmt(self.as_bstr(), f)
78 }
79 }
80
81 impl fmt::Debug for BString {
82 #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result83 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84 fmt::Debug::fmt(self.as_bstr(), f)
85 }
86 }
87
88 impl ops::Deref for BString {
89 type Target = Vec<u8>;
90
91 #[inline]
deref(&self) -> &Vec<u8>92 fn deref(&self) -> &Vec<u8> {
93 &self.bytes
94 }
95 }
96
97 impl ops::DerefMut for BString {
98 #[inline]
deref_mut(&mut self) -> &mut Vec<u8>99 fn deref_mut(&mut self) -> &mut Vec<u8> {
100 &mut self.bytes
101 }
102 }
103
104 impl AsRef<[u8]> for BString {
105 #[inline]
as_ref(&self) -> &[u8]106 fn as_ref(&self) -> &[u8] {
107 &self.bytes
108 }
109 }
110
111 impl AsRef<BStr> for BString {
112 #[inline]
as_ref(&self) -> &BStr113 fn as_ref(&self) -> &BStr {
114 self.as_bstr()
115 }
116 }
117
118 impl AsMut<[u8]> for BString {
119 #[inline]
as_mut(&mut self) -> &mut [u8]120 fn as_mut(&mut self) -> &mut [u8] {
121 &mut self.bytes
122 }
123 }
124
125 impl AsMut<BStr> for BString {
126 #[inline]
as_mut(&mut self) -> &mut BStr127 fn as_mut(&mut self) -> &mut BStr {
128 self.as_mut_bstr()
129 }
130 }
131
132 impl Borrow<BStr> for BString {
133 #[inline]
borrow(&self) -> &BStr134 fn borrow(&self) -> &BStr {
135 self.as_bstr()
136 }
137 }
138
139 impl ToOwned for BStr {
140 type Owned = BString;
141
142 #[inline]
to_owned(&self) -> BString143 fn to_owned(&self) -> BString {
144 BString::from(self)
145 }
146 }
147
148 impl Default for BString {
default() -> BString149 fn default() -> BString {
150 BString::from(vec![])
151 }
152 }
153
154 impl<'a> From<&'a [u8]> for BString {
155 #[inline]
from(s: &'a [u8]) -> BString156 fn from(s: &'a [u8]) -> BString {
157 BString::from(s.to_vec())
158 }
159 }
160
161 impl From<Vec<u8>> for BString {
162 #[inline]
from(s: Vec<u8>) -> BString163 fn from(s: Vec<u8>) -> BString {
164 BString { bytes: s }
165 }
166 }
167
168 impl From<BString> for Vec<u8> {
169 #[inline]
from(s: BString) -> Vec<u8>170 fn from(s: BString) -> Vec<u8> {
171 s.bytes
172 }
173 }
174
175 impl<'a> From<&'a str> for BString {
176 #[inline]
from(s: &'a str) -> BString177 fn from(s: &'a str) -> BString {
178 BString::from(s.as_bytes().to_vec())
179 }
180 }
181
182 impl From<String> for BString {
183 #[inline]
from(s: String) -> BString184 fn from(s: String) -> BString {
185 BString::from(s.into_bytes())
186 }
187 }
188
189 impl<'a> From<&'a BStr> for BString {
190 #[inline]
from(s: &'a BStr) -> BString191 fn from(s: &'a BStr) -> BString {
192 BString::from(s.bytes.to_vec())
193 }
194 }
195
196 impl<'a> From<BString> for Cow<'a, BStr> {
197 #[inline]
from(s: BString) -> Cow<'a, BStr>198 fn from(s: BString) -> Cow<'a, BStr> {
199 Cow::Owned(s)
200 }
201 }
202
203 impl FromIterator<char> for BString {
204 #[inline]
from_iter<T: IntoIterator<Item = char>>(iter: T) -> BString205 fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> BString {
206 BString::from(iter.into_iter().collect::<String>())
207 }
208 }
209
210 impl FromIterator<u8> for BString {
211 #[inline]
from_iter<T: IntoIterator<Item = u8>>(iter: T) -> BString212 fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> BString {
213 BString::from(iter.into_iter().collect::<Vec<u8>>())
214 }
215 }
216
217 impl<'a> FromIterator<&'a str> for BString {
218 #[inline]
from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> BString219 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> BString {
220 let mut buf = vec![];
221 for b in iter {
222 buf.push_str(b);
223 }
224 BString::from(buf)
225 }
226 }
227
228 impl<'a> FromIterator<&'a [u8]> for BString {
229 #[inline]
from_iter<T: IntoIterator<Item = &'a [u8]>>(iter: T) -> BString230 fn from_iter<T: IntoIterator<Item = &'a [u8]>>(iter: T) -> BString {
231 let mut buf = vec![];
232 for b in iter {
233 buf.push_str(b);
234 }
235 BString::from(buf)
236 }
237 }
238
239 impl<'a> FromIterator<&'a BStr> for BString {
240 #[inline]
from_iter<T: IntoIterator<Item = &'a BStr>>(iter: T) -> BString241 fn from_iter<T: IntoIterator<Item = &'a BStr>>(iter: T) -> BString {
242 let mut buf = vec![];
243 for b in iter {
244 buf.push_str(b);
245 }
246 BString::from(buf)
247 }
248 }
249
250 impl FromIterator<BString> for BString {
251 #[inline]
from_iter<T: IntoIterator<Item = BString>>(iter: T) -> BString252 fn from_iter<T: IntoIterator<Item = BString>>(iter: T) -> BString {
253 let mut buf = vec![];
254 for b in iter {
255 buf.push_str(b);
256 }
257 BString::from(buf)
258 }
259 }
260
261 impl Eq for BString {}
262
263 impl PartialEq for BString {
264 #[inline]
eq(&self, other: &BString) -> bool265 fn eq(&self, other: &BString) -> bool {
266 &self[..] == &other[..]
267 }
268 }
269
270 impl_partial_eq!(BString, Vec<u8>);
271 impl_partial_eq!(BString, [u8]);
272 impl_partial_eq!(BString, &'a [u8]);
273 impl_partial_eq!(BString, String);
274 impl_partial_eq!(BString, str);
275 impl_partial_eq!(BString, &'a str);
276 impl_partial_eq!(BString, BStr);
277 impl_partial_eq!(BString, &'a BStr);
278
279 impl PartialOrd for BString {
280 #[inline]
partial_cmp(&self, other: &BString) -> Option<Ordering>281 fn partial_cmp(&self, other: &BString) -> Option<Ordering> {
282 PartialOrd::partial_cmp(&self.bytes, &other.bytes)
283 }
284 }
285
286 impl Ord for BString {
287 #[inline]
cmp(&self, other: &BString) -> Ordering288 fn cmp(&self, other: &BString) -> Ordering {
289 self.partial_cmp(other).unwrap()
290 }
291 }
292
293 impl_partial_ord!(BString, Vec<u8>);
294 impl_partial_ord!(BString, [u8]);
295 impl_partial_ord!(BString, &'a [u8]);
296 impl_partial_ord!(BString, String);
297 impl_partial_ord!(BString, str);
298 impl_partial_ord!(BString, &'a str);
299 impl_partial_ord!(BString, BStr);
300 impl_partial_ord!(BString, &'a BStr);
301 }
302
303 mod bstr {
304 #[cfg(feature = "std")]
305 use std::borrow::Cow;
306
307 use core::cmp::Ordering;
308 use core::fmt;
309 use core::ops;
310
311 use bstr::BStr;
312 use ext_slice::ByteSlice;
313
314 impl fmt::Display for BStr {
315 #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result316 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
317 /// Write the given bstr (lossily) to the given formatter.
318 fn write_bstr(
319 f: &mut fmt::Formatter,
320 bstr: &BStr,
321 ) -> Result<(), fmt::Error> {
322 for chunk in bstr.utf8_chunks() {
323 f.write_str(chunk.valid())?;
324 if !chunk.invalid().is_empty() {
325 f.write_str("\u{FFFD}")?;
326 }
327 }
328 Ok(())
329 }
330
331 /// Write 'num' fill characters to the given formatter.
332 fn write_pads(f: &mut fmt::Formatter, num: usize) -> fmt::Result {
333 let fill = f.fill();
334 for _ in 0..num {
335 f.write_fmt(format_args!("{}", fill))?;
336 }
337 Ok(())
338 }
339
340 if let Some(align) = f.align() {
341 let width = f.width().unwrap_or(0);
342 let nchars = self.chars().count();
343 let remaining_pads = width.saturating_sub(nchars);
344 match align {
345 fmt::Alignment::Left => {
346 write_bstr(f, self)?;
347 write_pads(f, remaining_pads)?;
348 }
349 fmt::Alignment::Right => {
350 write_pads(f, remaining_pads)?;
351 write_bstr(f, self)?;
352 }
353 fmt::Alignment::Center => {
354 let half = remaining_pads / 2;
355 let second_half = if remaining_pads % 2 == 0 {
356 half
357 } else {
358 half + 1
359 };
360 write_pads(f, half)?;
361 write_bstr(f, self)?;
362 write_pads(f, second_half)?;
363 }
364 }
365 Ok(())
366 } else {
367 write_bstr(f, self)?;
368 Ok(())
369 }
370 }
371 }
372
373 impl fmt::Debug for BStr {
374 #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result375 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
376 write!(f, "\"")?;
377 for (s, e, ch) in self.char_indices() {
378 match ch {
379 '\0' => write!(f, "\\0")?,
380 '\u{FFFD}' => {
381 let bytes = self[s..e].as_bytes();
382 if bytes == b"\xEF\xBF\xBD" {
383 write!(f, "{}", ch.escape_debug())?;
384 } else {
385 for &b in self[s..e].as_bytes() {
386 write!(f, r"\x{:02X}", b)?;
387 }
388 }
389 }
390 // ASCII control characters except \0, \n, \r, \t
391 '\x01'..='\x08'
392 | '\x0b'
393 | '\x0c'
394 | '\x0e'..='\x19'
395 | '\x7f' => {
396 write!(f, "\\x{:02x}", ch as u32)?;
397 }
398 '\n' | '\r' | '\t' | _ => {
399 write!(f, "{}", ch.escape_debug())?;
400 }
401 }
402 }
403 write!(f, "\"")?;
404 Ok(())
405 }
406 }
407
408 impl ops::Deref for BStr {
409 type Target = [u8];
410
411 #[inline]
deref(&self) -> &[u8]412 fn deref(&self) -> &[u8] {
413 &self.bytes
414 }
415 }
416
417 impl ops::DerefMut for BStr {
418 #[inline]
deref_mut(&mut self) -> &mut [u8]419 fn deref_mut(&mut self) -> &mut [u8] {
420 &mut self.bytes
421 }
422 }
423
424 impl ops::Index<usize> for BStr {
425 type Output = u8;
426
427 #[inline]
index(&self, idx: usize) -> &u8428 fn index(&self, idx: usize) -> &u8 {
429 &self.as_bytes()[idx]
430 }
431 }
432
433 impl ops::Index<ops::RangeFull> for BStr {
434 type Output = BStr;
435
436 #[inline]
index(&self, _: ops::RangeFull) -> &BStr437 fn index(&self, _: ops::RangeFull) -> &BStr {
438 self
439 }
440 }
441
442 impl ops::Index<ops::Range<usize>> for BStr {
443 type Output = BStr;
444
445 #[inline]
index(&self, r: ops::Range<usize>) -> &BStr446 fn index(&self, r: ops::Range<usize>) -> &BStr {
447 BStr::new(&self.as_bytes()[r.start..r.end])
448 }
449 }
450
451 impl ops::Index<ops::RangeInclusive<usize>> for BStr {
452 type Output = BStr;
453
454 #[inline]
index(&self, r: ops::RangeInclusive<usize>) -> &BStr455 fn index(&self, r: ops::RangeInclusive<usize>) -> &BStr {
456 BStr::new(&self.as_bytes()[*r.start()..=*r.end()])
457 }
458 }
459
460 impl ops::Index<ops::RangeFrom<usize>> for BStr {
461 type Output = BStr;
462
463 #[inline]
index(&self, r: ops::RangeFrom<usize>) -> &BStr464 fn index(&self, r: ops::RangeFrom<usize>) -> &BStr {
465 BStr::new(&self.as_bytes()[r.start..])
466 }
467 }
468
469 impl ops::Index<ops::RangeTo<usize>> for BStr {
470 type Output = BStr;
471
472 #[inline]
index(&self, r: ops::RangeTo<usize>) -> &BStr473 fn index(&self, r: ops::RangeTo<usize>) -> &BStr {
474 BStr::new(&self.as_bytes()[..r.end])
475 }
476 }
477
478 impl ops::Index<ops::RangeToInclusive<usize>> for BStr {
479 type Output = BStr;
480
481 #[inline]
index(&self, r: ops::RangeToInclusive<usize>) -> &BStr482 fn index(&self, r: ops::RangeToInclusive<usize>) -> &BStr {
483 BStr::new(&self.as_bytes()[..=r.end])
484 }
485 }
486
487 impl ops::IndexMut<usize> for BStr {
488 #[inline]
index_mut(&mut self, idx: usize) -> &mut u8489 fn index_mut(&mut self, idx: usize) -> &mut u8 {
490 &mut self.bytes[idx]
491 }
492 }
493
494 impl ops::IndexMut<ops::RangeFull> for BStr {
495 #[inline]
index_mut(&mut self, _: ops::RangeFull) -> &mut BStr496 fn index_mut(&mut self, _: ops::RangeFull) -> &mut BStr {
497 self
498 }
499 }
500
501 impl ops::IndexMut<ops::Range<usize>> for BStr {
502 #[inline]
index_mut(&mut self, r: ops::Range<usize>) -> &mut BStr503 fn index_mut(&mut self, r: ops::Range<usize>) -> &mut BStr {
504 BStr::from_bytes_mut(&mut self.bytes[r.start..r.end])
505 }
506 }
507
508 impl ops::IndexMut<ops::RangeInclusive<usize>> for BStr {
509 #[inline]
index_mut(&mut self, r: ops::RangeInclusive<usize>) -> &mut BStr510 fn index_mut(&mut self, r: ops::RangeInclusive<usize>) -> &mut BStr {
511 BStr::from_bytes_mut(&mut self.bytes[*r.start()..=*r.end()])
512 }
513 }
514
515 impl ops::IndexMut<ops::RangeFrom<usize>> for BStr {
516 #[inline]
index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut BStr517 fn index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut BStr {
518 BStr::from_bytes_mut(&mut self.bytes[r.start..])
519 }
520 }
521
522 impl ops::IndexMut<ops::RangeTo<usize>> for BStr {
523 #[inline]
index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut BStr524 fn index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut BStr {
525 BStr::from_bytes_mut(&mut self.bytes[..r.end])
526 }
527 }
528
529 impl ops::IndexMut<ops::RangeToInclusive<usize>> for BStr {
530 #[inline]
index_mut(&mut self, r: ops::RangeToInclusive<usize>) -> &mut BStr531 fn index_mut(&mut self, r: ops::RangeToInclusive<usize>) -> &mut BStr {
532 BStr::from_bytes_mut(&mut self.bytes[..=r.end])
533 }
534 }
535
536 impl AsRef<[u8]> for BStr {
537 #[inline]
as_ref(&self) -> &[u8]538 fn as_ref(&self) -> &[u8] {
539 self.as_bytes()
540 }
541 }
542
543 impl AsRef<BStr> for [u8] {
544 #[inline]
as_ref(&self) -> &BStr545 fn as_ref(&self) -> &BStr {
546 BStr::new(self)
547 }
548 }
549
550 impl AsRef<BStr> for str {
551 #[inline]
as_ref(&self) -> &BStr552 fn as_ref(&self) -> &BStr {
553 BStr::new(self)
554 }
555 }
556
557 impl AsMut<[u8]> for BStr {
558 #[inline]
as_mut(&mut self) -> &mut [u8]559 fn as_mut(&mut self) -> &mut [u8] {
560 &mut self.bytes
561 }
562 }
563
564 impl AsMut<BStr> for [u8] {
565 #[inline]
as_mut(&mut self) -> &mut BStr566 fn as_mut(&mut self) -> &mut BStr {
567 BStr::new_mut(self)
568 }
569 }
570
571 impl<'a> Default for &'a BStr {
default() -> &'a BStr572 fn default() -> &'a BStr {
573 BStr::from_bytes(b"")
574 }
575 }
576
577 impl<'a> Default for &'a mut BStr {
default() -> &'a mut BStr578 fn default() -> &'a mut BStr {
579 BStr::from_bytes_mut(&mut [])
580 }
581 }
582
583 impl<'a> From<&'a [u8]> for &'a BStr {
584 #[inline]
from(s: &'a [u8]) -> &'a BStr585 fn from(s: &'a [u8]) -> &'a BStr {
586 BStr::from_bytes(s)
587 }
588 }
589
590 impl<'a> From<&'a str> for &'a BStr {
591 #[inline]
from(s: &'a str) -> &'a BStr592 fn from(s: &'a str) -> &'a BStr {
593 BStr::from_bytes(s.as_bytes())
594 }
595 }
596
597 #[cfg(feature = "std")]
598 impl<'a> From<&'a BStr> for Cow<'a, BStr> {
599 #[inline]
from(s: &'a BStr) -> Cow<'a, BStr>600 fn from(s: &'a BStr) -> Cow<'a, BStr> {
601 Cow::Borrowed(s)
602 }
603 }
604
605 #[cfg(feature = "std")]
606 impl From<Box<[u8]>> for Box<BStr> {
607 #[inline]
from(s: Box<[u8]>) -> Box<BStr>608 fn from(s: Box<[u8]>) -> Box<BStr> {
609 BStr::from_boxed_bytes(s)
610 }
611 }
612
613 #[cfg(feature = "std")]
614 impl From<Box<BStr>> for Box<[u8]> {
615 #[inline]
from(s: Box<BStr>) -> Box<[u8]>616 fn from(s: Box<BStr>) -> Box<[u8]> {
617 BStr::into_boxed_bytes(s)
618 }
619 }
620
621 impl Eq for BStr {}
622
623 impl PartialEq<BStr> for BStr {
624 #[inline]
eq(&self, other: &BStr) -> bool625 fn eq(&self, other: &BStr) -> bool {
626 self.as_bytes() == other.as_bytes()
627 }
628 }
629
630 impl_partial_eq!(BStr, [u8]);
631 impl_partial_eq!(BStr, &'a [u8]);
632 impl_partial_eq!(BStr, str);
633 impl_partial_eq!(BStr, &'a str);
634
635 #[cfg(feature = "std")]
636 impl_partial_eq!(BStr, Vec<u8>);
637 #[cfg(feature = "std")]
638 impl_partial_eq!(&'a BStr, Vec<u8>);
639 #[cfg(feature = "std")]
640 impl_partial_eq!(BStr, String);
641 #[cfg(feature = "std")]
642 impl_partial_eq!(&'a BStr, String);
643 #[cfg(feature = "std")]
644 impl_partial_eq_cow!(&'a BStr, Cow<'a, BStr>);
645 #[cfg(feature = "std")]
646 impl_partial_eq_cow!(&'a BStr, Cow<'a, str>);
647 #[cfg(feature = "std")]
648 impl_partial_eq_cow!(&'a BStr, Cow<'a, [u8]>);
649
650 impl PartialOrd for BStr {
651 #[inline]
partial_cmp(&self, other: &BStr) -> Option<Ordering>652 fn partial_cmp(&self, other: &BStr) -> Option<Ordering> {
653 PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes())
654 }
655 }
656
657 impl Ord for BStr {
658 #[inline]
cmp(&self, other: &BStr) -> Ordering659 fn cmp(&self, other: &BStr) -> Ordering {
660 self.partial_cmp(other).unwrap()
661 }
662 }
663
664 impl_partial_ord!(BStr, [u8]);
665 impl_partial_ord!(BStr, &'a [u8]);
666 impl_partial_ord!(BStr, str);
667 impl_partial_ord!(BStr, &'a str);
668
669 #[cfg(feature = "std")]
670 impl_partial_ord!(BStr, Vec<u8>);
671 #[cfg(feature = "std")]
672 impl_partial_ord!(&'a BStr, Vec<u8>);
673 #[cfg(feature = "std")]
674 impl_partial_ord!(BStr, String);
675 #[cfg(feature = "std")]
676 impl_partial_ord!(&'a BStr, String);
677 }
678
679 #[cfg(feature = "serde1-nostd")]
680 mod bstr_serde {
681 use core::fmt;
682
683 use serde::{
684 de::Error, de::Visitor, Deserialize, Deserializer, Serialize,
685 Serializer,
686 };
687
688 use bstr::BStr;
689
690 impl Serialize for BStr {
691 #[inline]
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,692 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
693 where
694 S: Serializer,
695 {
696 serializer.serialize_bytes(self.as_bytes())
697 }
698 }
699
700 impl<'a, 'de: 'a> Deserialize<'de> for &'a BStr {
701 #[inline]
deserialize<D>(deserializer: D) -> Result<&'a BStr, D::Error> where D: Deserializer<'de>,702 fn deserialize<D>(deserializer: D) -> Result<&'a BStr, D::Error>
703 where
704 D: Deserializer<'de>,
705 {
706 struct BStrVisitor;
707
708 impl<'de> Visitor<'de> for BStrVisitor {
709 type Value = &'de BStr;
710
711 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
712 f.write_str("a borrowed byte string")
713 }
714
715 #[inline]
716 fn visit_borrowed_bytes<E: Error>(
717 self,
718 value: &'de [u8],
719 ) -> Result<&'de BStr, E> {
720 Ok(BStr::new(value))
721 }
722
723 #[inline]
724 fn visit_borrowed_str<E: Error>(
725 self,
726 value: &'de str,
727 ) -> Result<&'de BStr, E> {
728 Ok(BStr::new(value))
729 }
730 }
731
732 deserializer.deserialize_bytes(BStrVisitor)
733 }
734 }
735 }
736
737 #[cfg(feature = "serde1")]
738 mod bstring_serde {
739 use std::cmp;
740 use std::fmt;
741
742 use serde::{
743 de::Error, de::SeqAccess, de::Visitor, Deserialize, Deserializer,
744 Serialize, Serializer,
745 };
746
747 use bstring::BString;
748
749 impl Serialize for BString {
750 #[inline]
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,751 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
752 where
753 S: Serializer,
754 {
755 serializer.serialize_bytes(self.as_bytes())
756 }
757 }
758
759 impl<'de> Deserialize<'de> for BString {
760 #[inline]
deserialize<D>(deserializer: D) -> Result<BString, D::Error> where D: Deserializer<'de>,761 fn deserialize<D>(deserializer: D) -> Result<BString, D::Error>
762 where
763 D: Deserializer<'de>,
764 {
765 struct BStringVisitor;
766
767 impl<'de> Visitor<'de> for BStringVisitor {
768 type Value = BString;
769
770 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
771 f.write_str("a byte string")
772 }
773
774 #[inline]
775 fn visit_seq<V: SeqAccess<'de>>(
776 self,
777 mut visitor: V,
778 ) -> Result<BString, V::Error> {
779 let len = cmp::min(visitor.size_hint().unwrap_or(0), 256);
780 let mut bytes = Vec::with_capacity(len);
781 while let Some(v) = visitor.next_element()? {
782 bytes.push(v);
783 }
784 Ok(BString::from(bytes))
785 }
786
787 #[inline]
788 fn visit_bytes<E: Error>(
789 self,
790 value: &[u8],
791 ) -> Result<BString, E> {
792 Ok(BString::from(value))
793 }
794
795 #[inline]
796 fn visit_byte_buf<E: Error>(
797 self,
798 value: Vec<u8>,
799 ) -> Result<BString, E> {
800 Ok(BString::from(value))
801 }
802
803 #[inline]
804 fn visit_str<E: Error>(
805 self,
806 value: &str,
807 ) -> Result<BString, E> {
808 Ok(BString::from(value))
809 }
810
811 #[inline]
812 fn visit_string<E: Error>(
813 self,
814 value: String,
815 ) -> Result<BString, E> {
816 Ok(BString::from(value))
817 }
818 }
819
820 deserializer.deserialize_byte_buf(BStringVisitor)
821 }
822 }
823 }
824
825 #[cfg(test)]
826 mod display {
827 use crate::ByteSlice;
828 use bstring::BString;
829
830 #[test]
clean()831 fn clean() {
832 assert_eq!(&format!("{}", &b"abc".as_bstr()), "abc");
833 assert_eq!(&format!("{}", &b"\xf0\x28\x8c\xbc".as_bstr()), "�(��");
834 }
835
836 #[test]
width_bigger_than_bstr()837 fn width_bigger_than_bstr() {
838 assert_eq!(&format!("{:<7}!", &b"abc".as_bstr()), "abc !");
839 assert_eq!(&format!("{:>7}!", &b"abc".as_bstr()), " abc!");
840 assert_eq!(&format!("{:^7}!", &b"abc".as_bstr()), " abc !");
841 assert_eq!(&format!("{:^6}!", &b"abc".as_bstr()), " abc !");
842 assert_eq!(&format!("{:-<7}!", &b"abc".as_bstr()), "abc----!");
843 assert_eq!(&format!("{:->7}!", &b"abc".as_bstr()), "----abc!");
844 assert_eq!(&format!("{:-^7}!", &b"abc".as_bstr()), "--abc--!");
845 assert_eq!(&format!("{:-^6}!", &b"abc".as_bstr()), "-abc--!");
846
847 assert_eq!(
848 &format!("{:<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
849 "�(�� !"
850 );
851 assert_eq!(
852 &format!("{:>7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
853 " �(��!"
854 );
855 assert_eq!(
856 &format!("{:^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
857 " �(�� !"
858 );
859 assert_eq!(
860 &format!("{:^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
861 " �(�� !"
862 );
863
864 assert_eq!(
865 &format!("{:-<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
866 "�(��---!"
867 );
868 assert_eq!(
869 &format!("{:->7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
870 "---�(��!"
871 );
872 assert_eq!(
873 &format!("{:-^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
874 "-�(��--!"
875 );
876 assert_eq!(
877 &format!("{:-^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
878 "-�(��-!"
879 );
880 }
881
882 #[test]
width_lesser_than_bstr()883 fn width_lesser_than_bstr() {
884 assert_eq!(&format!("{:<2}!", &b"abc".as_bstr()), "abc!");
885 assert_eq!(&format!("{:>2}!", &b"abc".as_bstr()), "abc!");
886 assert_eq!(&format!("{:^2}!", &b"abc".as_bstr()), "abc!");
887 assert_eq!(&format!("{:-<2}!", &b"abc".as_bstr()), "abc!");
888 assert_eq!(&format!("{:->2}!", &b"abc".as_bstr()), "abc!");
889 assert_eq!(&format!("{:-^2}!", &b"abc".as_bstr()), "abc!");
890
891 assert_eq!(
892 &format!("{:<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
893 "�(��!"
894 );
895 assert_eq!(
896 &format!("{:>3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
897 "�(��!"
898 );
899 assert_eq!(
900 &format!("{:^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
901 "�(��!"
902 );
903 assert_eq!(
904 &format!("{:^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
905 "�(��!"
906 );
907
908 assert_eq!(
909 &format!("{:-<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
910 "�(��!"
911 );
912 assert_eq!(
913 &format!("{:->3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
914 "�(��!"
915 );
916 assert_eq!(
917 &format!("{:-^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
918 "�(��!"
919 );
920 assert_eq!(
921 &format!("{:-^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
922 "�(��!"
923 );
924 }
925
926 quickcheck! {
927 fn total_length(bstr: BString) -> bool {
928 let size = bstr.chars().count();
929 format!("{:<1$}", bstr.as_bstr(), size).chars().count() >= size
930 }
931 }
932 }
933
934 #[cfg(test)]
935 mod bstring_arbitrary {
936 use bstring::BString;
937
938 use quickcheck::{Arbitrary, Gen};
939
940 impl Arbitrary for BString {
arbitrary(g: &mut Gen) -> BString941 fn arbitrary(g: &mut Gen) -> BString {
942 BString::from(Vec::<u8>::arbitrary(g))
943 }
944
shrink(&self) -> Box<dyn Iterator<Item = BString>>945 fn shrink(&self) -> Box<dyn Iterator<Item = BString>> {
946 Box::new(self.bytes.shrink().map(BString::from))
947 }
948 }
949 }
950
951 #[test]
test_debug()952 fn test_debug() {
953 use crate::{ByteSlice, B};
954
955 assert_eq!(
956 r#""\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp""#,
957 format!("{:?}", b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp".as_bstr()),
958 );
959
960 // Tests that if the underlying bytes contain the UTF-8 encoding of the
961 // replacement codepoint, then we emit the codepoint just like other
962 // non-printable Unicode characters.
963 assert_eq!(
964 b"\"\\xFF\xEF\xBF\xBD\\xFF\"".as_bstr(),
965 // Before fixing #72, the output here would be:
966 // \\xFF\\xEF\\xBF\\xBD\\xFF
967 B(&format!("{:?}", b"\xFF\xEF\xBF\xBD\xFF".as_bstr())).as_bstr(),
968 );
969 }
970
971 // See: https://github.com/BurntSushi/bstr/issues/82
972 #[test]
test_cows_regression()973 fn test_cows_regression() {
974 use crate::ByteSlice;
975 use std::borrow::Cow;
976
977 let c1 = Cow::from(b"hello bstr".as_bstr());
978 let c2 = b"goodbye bstr".as_bstr();
979 assert_ne!(c1, c2);
980
981 let c3 = Cow::from("hello str");
982 let c4 = "goodbye str";
983 assert_ne!(c3, c4);
984 }
985