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 crate::bstr::BStr;
71 use crate::bstring::BString;
72 use crate::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 crate::bstr::BStr;
312 use crate::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(
333 f: &mut fmt::Formatter<'_>,
334 num: usize,
335 ) -> fmt::Result {
336 let fill = f.fill();
337 for _ in 0..num {
338 f.write_fmt(format_args!("{}", fill))?;
339 }
340 Ok(())
341 }
342
343 if let Some(align) = f.align() {
344 let width = f.width().unwrap_or(0);
345 let nchars = self.chars().count();
346 let remaining_pads = width.saturating_sub(nchars);
347 match align {
348 fmt::Alignment::Left => {
349 write_bstr(f, self)?;
350 write_pads(f, remaining_pads)?;
351 }
352 fmt::Alignment::Right => {
353 write_pads(f, remaining_pads)?;
354 write_bstr(f, self)?;
355 }
356 fmt::Alignment::Center => {
357 let half = remaining_pads / 2;
358 let second_half = if remaining_pads % 2 == 0 {
359 half
360 } else {
361 half + 1
362 };
363 write_pads(f, half)?;
364 write_bstr(f, self)?;
365 write_pads(f, second_half)?;
366 }
367 }
368 Ok(())
369 } else {
370 write_bstr(f, self)?;
371 Ok(())
372 }
373 }
374 }
375
376 impl fmt::Debug for BStr {
377 #[inline]
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result378 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379 write!(f, "\"")?;
380 for (s, e, ch) in self.char_indices() {
381 match ch {
382 '\0' => write!(f, "\\0")?,
383 '\u{FFFD}' => {
384 let bytes = self[s..e].as_bytes();
385 if bytes == b"\xEF\xBF\xBD" {
386 write!(f, "{}", ch.escape_debug())?;
387 } else {
388 for &b in self[s..e].as_bytes() {
389 write!(f, r"\x{:02X}", b)?;
390 }
391 }
392 }
393 // ASCII control characters except \0, \n, \r, \t
394 '\x01'..='\x08'
395 | '\x0b'
396 | '\x0c'
397 | '\x0e'..='\x19'
398 | '\x7f' => {
399 write!(f, "\\x{:02x}", ch as u32)?;
400 }
401 '\n' | '\r' | '\t' | _ => {
402 write!(f, "{}", ch.escape_debug())?;
403 }
404 }
405 }
406 write!(f, "\"")?;
407 Ok(())
408 }
409 }
410
411 impl ops::Deref for BStr {
412 type Target = [u8];
413
414 #[inline]
deref(&self) -> &[u8]415 fn deref(&self) -> &[u8] {
416 &self.bytes
417 }
418 }
419
420 impl ops::DerefMut for BStr {
421 #[inline]
deref_mut(&mut self) -> &mut [u8]422 fn deref_mut(&mut self) -> &mut [u8] {
423 &mut self.bytes
424 }
425 }
426
427 impl ops::Index<usize> for BStr {
428 type Output = u8;
429
430 #[inline]
index(&self, idx: usize) -> &u8431 fn index(&self, idx: usize) -> &u8 {
432 &self.as_bytes()[idx]
433 }
434 }
435
436 impl ops::Index<ops::RangeFull> for BStr {
437 type Output = BStr;
438
439 #[inline]
index(&self, _: ops::RangeFull) -> &BStr440 fn index(&self, _: ops::RangeFull) -> &BStr {
441 self
442 }
443 }
444
445 impl ops::Index<ops::Range<usize>> for BStr {
446 type Output = BStr;
447
448 #[inline]
index(&self, r: ops::Range<usize>) -> &BStr449 fn index(&self, r: ops::Range<usize>) -> &BStr {
450 BStr::new(&self.as_bytes()[r.start..r.end])
451 }
452 }
453
454 impl ops::Index<ops::RangeInclusive<usize>> for BStr {
455 type Output = BStr;
456
457 #[inline]
index(&self, r: ops::RangeInclusive<usize>) -> &BStr458 fn index(&self, r: ops::RangeInclusive<usize>) -> &BStr {
459 BStr::new(&self.as_bytes()[*r.start()..=*r.end()])
460 }
461 }
462
463 impl ops::Index<ops::RangeFrom<usize>> for BStr {
464 type Output = BStr;
465
466 #[inline]
index(&self, r: ops::RangeFrom<usize>) -> &BStr467 fn index(&self, r: ops::RangeFrom<usize>) -> &BStr {
468 BStr::new(&self.as_bytes()[r.start..])
469 }
470 }
471
472 impl ops::Index<ops::RangeTo<usize>> for BStr {
473 type Output = BStr;
474
475 #[inline]
index(&self, r: ops::RangeTo<usize>) -> &BStr476 fn index(&self, r: ops::RangeTo<usize>) -> &BStr {
477 BStr::new(&self.as_bytes()[..r.end])
478 }
479 }
480
481 impl ops::Index<ops::RangeToInclusive<usize>> for BStr {
482 type Output = BStr;
483
484 #[inline]
index(&self, r: ops::RangeToInclusive<usize>) -> &BStr485 fn index(&self, r: ops::RangeToInclusive<usize>) -> &BStr {
486 BStr::new(&self.as_bytes()[..=r.end])
487 }
488 }
489
490 impl ops::IndexMut<usize> for BStr {
491 #[inline]
index_mut(&mut self, idx: usize) -> &mut u8492 fn index_mut(&mut self, idx: usize) -> &mut u8 {
493 &mut self.bytes[idx]
494 }
495 }
496
497 impl ops::IndexMut<ops::RangeFull> for BStr {
498 #[inline]
index_mut(&mut self, _: ops::RangeFull) -> &mut BStr499 fn index_mut(&mut self, _: ops::RangeFull) -> &mut BStr {
500 self
501 }
502 }
503
504 impl ops::IndexMut<ops::Range<usize>> for BStr {
505 #[inline]
index_mut(&mut self, r: ops::Range<usize>) -> &mut BStr506 fn index_mut(&mut self, r: ops::Range<usize>) -> &mut BStr {
507 BStr::from_bytes_mut(&mut self.bytes[r.start..r.end])
508 }
509 }
510
511 impl ops::IndexMut<ops::RangeInclusive<usize>> for BStr {
512 #[inline]
index_mut(&mut self, r: ops::RangeInclusive<usize>) -> &mut BStr513 fn index_mut(&mut self, r: ops::RangeInclusive<usize>) -> &mut BStr {
514 BStr::from_bytes_mut(&mut self.bytes[*r.start()..=*r.end()])
515 }
516 }
517
518 impl ops::IndexMut<ops::RangeFrom<usize>> for BStr {
519 #[inline]
index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut BStr520 fn index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut BStr {
521 BStr::from_bytes_mut(&mut self.bytes[r.start..])
522 }
523 }
524
525 impl ops::IndexMut<ops::RangeTo<usize>> for BStr {
526 #[inline]
index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut BStr527 fn index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut BStr {
528 BStr::from_bytes_mut(&mut self.bytes[..r.end])
529 }
530 }
531
532 impl ops::IndexMut<ops::RangeToInclusive<usize>> for BStr {
533 #[inline]
index_mut(&mut self, r: ops::RangeToInclusive<usize>) -> &mut BStr534 fn index_mut(&mut self, r: ops::RangeToInclusive<usize>) -> &mut BStr {
535 BStr::from_bytes_mut(&mut self.bytes[..=r.end])
536 }
537 }
538
539 impl AsRef<[u8]> for BStr {
540 #[inline]
as_ref(&self) -> &[u8]541 fn as_ref(&self) -> &[u8] {
542 self.as_bytes()
543 }
544 }
545
546 impl AsRef<BStr> for [u8] {
547 #[inline]
as_ref(&self) -> &BStr548 fn as_ref(&self) -> &BStr {
549 BStr::new(self)
550 }
551 }
552
553 impl AsRef<BStr> for str {
554 #[inline]
as_ref(&self) -> &BStr555 fn as_ref(&self) -> &BStr {
556 BStr::new(self)
557 }
558 }
559
560 impl AsMut<[u8]> for BStr {
561 #[inline]
as_mut(&mut self) -> &mut [u8]562 fn as_mut(&mut self) -> &mut [u8] {
563 &mut self.bytes
564 }
565 }
566
567 impl AsMut<BStr> for [u8] {
568 #[inline]
as_mut(&mut self) -> &mut BStr569 fn as_mut(&mut self) -> &mut BStr {
570 BStr::new_mut(self)
571 }
572 }
573
574 impl<'a> Default for &'a BStr {
default() -> &'a BStr575 fn default() -> &'a BStr {
576 BStr::from_bytes(b"")
577 }
578 }
579
580 impl<'a> Default for &'a mut BStr {
default() -> &'a mut BStr581 fn default() -> &'a mut BStr {
582 BStr::from_bytes_mut(&mut [])
583 }
584 }
585
586 impl<'a> From<&'a [u8]> for &'a BStr {
587 #[inline]
from(s: &'a [u8]) -> &'a BStr588 fn from(s: &'a [u8]) -> &'a BStr {
589 BStr::from_bytes(s)
590 }
591 }
592
593 impl<'a> From<&'a str> for &'a BStr {
594 #[inline]
from(s: &'a str) -> &'a BStr595 fn from(s: &'a str) -> &'a BStr {
596 BStr::from_bytes(s.as_bytes())
597 }
598 }
599
600 #[cfg(feature = "std")]
601 impl<'a> From<&'a BStr> for Cow<'a, BStr> {
602 #[inline]
from(s: &'a BStr) -> Cow<'a, BStr>603 fn from(s: &'a BStr) -> Cow<'a, BStr> {
604 Cow::Borrowed(s)
605 }
606 }
607
608 #[cfg(feature = "std")]
609 impl From<Box<[u8]>> for Box<BStr> {
610 #[inline]
from(s: Box<[u8]>) -> Box<BStr>611 fn from(s: Box<[u8]>) -> Box<BStr> {
612 BStr::from_boxed_bytes(s)
613 }
614 }
615
616 #[cfg(feature = "std")]
617 impl From<Box<BStr>> for Box<[u8]> {
618 #[inline]
from(s: Box<BStr>) -> Box<[u8]>619 fn from(s: Box<BStr>) -> Box<[u8]> {
620 BStr::into_boxed_bytes(s)
621 }
622 }
623
624 impl Eq for BStr {}
625
626 impl PartialEq<BStr> for BStr {
627 #[inline]
eq(&self, other: &BStr) -> bool628 fn eq(&self, other: &BStr) -> bool {
629 self.as_bytes() == other.as_bytes()
630 }
631 }
632
633 impl_partial_eq!(BStr, [u8]);
634 impl_partial_eq!(BStr, &'a [u8]);
635 impl_partial_eq!(BStr, str);
636 impl_partial_eq!(BStr, &'a str);
637
638 #[cfg(feature = "std")]
639 impl_partial_eq!(BStr, Vec<u8>);
640 #[cfg(feature = "std")]
641 impl_partial_eq!(&'a BStr, Vec<u8>);
642 #[cfg(feature = "std")]
643 impl_partial_eq!(BStr, String);
644 #[cfg(feature = "std")]
645 impl_partial_eq!(&'a BStr, String);
646 #[cfg(feature = "std")]
647 impl_partial_eq_cow!(&'a BStr, Cow<'a, BStr>);
648 #[cfg(feature = "std")]
649 impl_partial_eq_cow!(&'a BStr, Cow<'a, str>);
650 #[cfg(feature = "std")]
651 impl_partial_eq_cow!(&'a BStr, Cow<'a, [u8]>);
652
653 impl PartialOrd for BStr {
654 #[inline]
partial_cmp(&self, other: &BStr) -> Option<Ordering>655 fn partial_cmp(&self, other: &BStr) -> Option<Ordering> {
656 PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes())
657 }
658 }
659
660 impl Ord for BStr {
661 #[inline]
cmp(&self, other: &BStr) -> Ordering662 fn cmp(&self, other: &BStr) -> Ordering {
663 self.partial_cmp(other).unwrap()
664 }
665 }
666
667 impl_partial_ord!(BStr, [u8]);
668 impl_partial_ord!(BStr, &'a [u8]);
669 impl_partial_ord!(BStr, str);
670 impl_partial_ord!(BStr, &'a str);
671
672 #[cfg(feature = "std")]
673 impl_partial_ord!(BStr, Vec<u8>);
674 #[cfg(feature = "std")]
675 impl_partial_ord!(&'a BStr, Vec<u8>);
676 #[cfg(feature = "std")]
677 impl_partial_ord!(BStr, String);
678 #[cfg(feature = "std")]
679 impl_partial_ord!(&'a BStr, String);
680 }
681
682 #[cfg(feature = "serde1-nostd")]
683 mod bstr_serde {
684 use core::fmt;
685
686 use serde::{
687 de::Error, de::Visitor, Deserialize, Deserializer, Serialize,
688 Serializer,
689 };
690
691 use crate::bstr::BStr;
692
693 impl Serialize for BStr {
694 #[inline]
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,695 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
696 where
697 S: Serializer,
698 {
699 serializer.serialize_bytes(self.as_bytes())
700 }
701 }
702
703 impl<'a, 'de: 'a> Deserialize<'de> for &'a BStr {
704 #[inline]
deserialize<D>(deserializer: D) -> Result<&'a BStr, D::Error> where D: Deserializer<'de>,705 fn deserialize<D>(deserializer: D) -> Result<&'a BStr, D::Error>
706 where
707 D: Deserializer<'de>,
708 {
709 struct BStrVisitor;
710
711 impl<'de> Visitor<'de> for BStrVisitor {
712 type Value = &'de BStr;
713
714 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
715 f.write_str("a borrowed byte string")
716 }
717
718 #[inline]
719 fn visit_borrowed_bytes<E: Error>(
720 self,
721 value: &'de [u8],
722 ) -> Result<&'de BStr, E> {
723 Ok(BStr::new(value))
724 }
725
726 #[inline]
727 fn visit_borrowed_str<E: Error>(
728 self,
729 value: &'de str,
730 ) -> Result<&'de BStr, E> {
731 Ok(BStr::new(value))
732 }
733 }
734
735 deserializer.deserialize_bytes(BStrVisitor)
736 }
737 }
738 }
739
740 #[cfg(feature = "serde1")]
741 mod bstring_serde {
742 use std::cmp;
743 use std::fmt;
744
745 use serde::{
746 de::Error, de::SeqAccess, de::Visitor, Deserialize, Deserializer,
747 Serialize, Serializer,
748 };
749
750 use crate::bstring::BString;
751
752 impl Serialize for BString {
753 #[inline]
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,754 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
755 where
756 S: Serializer,
757 {
758 serializer.serialize_bytes(self.as_bytes())
759 }
760 }
761
762 impl<'de> Deserialize<'de> for BString {
763 #[inline]
deserialize<D>(deserializer: D) -> Result<BString, D::Error> where D: Deserializer<'de>,764 fn deserialize<D>(deserializer: D) -> Result<BString, D::Error>
765 where
766 D: Deserializer<'de>,
767 {
768 struct BStringVisitor;
769
770 impl<'de> Visitor<'de> for BStringVisitor {
771 type Value = BString;
772
773 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
774 f.write_str("a byte string")
775 }
776
777 #[inline]
778 fn visit_seq<V: SeqAccess<'de>>(
779 self,
780 mut visitor: V,
781 ) -> Result<BString, V::Error> {
782 let len = cmp::min(visitor.size_hint().unwrap_or(0), 256);
783 let mut bytes = Vec::with_capacity(len);
784 while let Some(v) = visitor.next_element()? {
785 bytes.push(v);
786 }
787 Ok(BString::from(bytes))
788 }
789
790 #[inline]
791 fn visit_bytes<E: Error>(
792 self,
793 value: &[u8],
794 ) -> Result<BString, E> {
795 Ok(BString::from(value))
796 }
797
798 #[inline]
799 fn visit_byte_buf<E: Error>(
800 self,
801 value: Vec<u8>,
802 ) -> Result<BString, E> {
803 Ok(BString::from(value))
804 }
805
806 #[inline]
807 fn visit_str<E: Error>(
808 self,
809 value: &str,
810 ) -> Result<BString, E> {
811 Ok(BString::from(value))
812 }
813
814 #[inline]
815 fn visit_string<E: Error>(
816 self,
817 value: String,
818 ) -> Result<BString, E> {
819 Ok(BString::from(value))
820 }
821 }
822
823 deserializer.deserialize_byte_buf(BStringVisitor)
824 }
825 }
826 }
827
828 #[cfg(test)]
829 mod display {
830 use crate::bstring::BString;
831 use crate::ByteSlice;
832
833 #[test]
clean()834 fn clean() {
835 assert_eq!(&format!("{}", &b"abc".as_bstr()), "abc");
836 assert_eq!(&format!("{}", &b"\xf0\x28\x8c\xbc".as_bstr()), "�(��");
837 }
838
839 #[test]
width_bigger_than_bstr()840 fn width_bigger_than_bstr() {
841 assert_eq!(&format!("{:<7}!", &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!("{:^6}!", &b"abc".as_bstr()), " abc !");
845 assert_eq!(&format!("{:-<7}!", &b"abc".as_bstr()), "abc----!");
846 assert_eq!(&format!("{:->7}!", &b"abc".as_bstr()), "----abc!");
847 assert_eq!(&format!("{:-^7}!", &b"abc".as_bstr()), "--abc--!");
848 assert_eq!(&format!("{:-^6}!", &b"abc".as_bstr()), "-abc--!");
849
850 assert_eq!(
851 &format!("{:<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
852 "�(�� !"
853 );
854 assert_eq!(
855 &format!("{:>7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
856 " �(��!"
857 );
858 assert_eq!(
859 &format!("{:^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
860 " �(�� !"
861 );
862 assert_eq!(
863 &format!("{:^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
864 " �(�� !"
865 );
866
867 assert_eq!(
868 &format!("{:-<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
869 "�(��---!"
870 );
871 assert_eq!(
872 &format!("{:->7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
873 "---�(��!"
874 );
875 assert_eq!(
876 &format!("{:-^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
877 "-�(��--!"
878 );
879 assert_eq!(
880 &format!("{:-^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
881 "-�(��-!"
882 );
883 }
884
885 #[test]
width_lesser_than_bstr()886 fn width_lesser_than_bstr() {
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 assert_eq!(&format!("{:-<2}!", &b"abc".as_bstr()), "abc!");
891 assert_eq!(&format!("{:->2}!", &b"abc".as_bstr()), "abc!");
892 assert_eq!(&format!("{:-^2}!", &b"abc".as_bstr()), "abc!");
893
894 assert_eq!(
895 &format!("{:<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
896 "�(��!"
897 );
898 assert_eq!(
899 &format!("{:>3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
900 "�(��!"
901 );
902 assert_eq!(
903 &format!("{:^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
904 "�(��!"
905 );
906 assert_eq!(
907 &format!("{:^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
908 "�(��!"
909 );
910
911 assert_eq!(
912 &format!("{:-<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
913 "�(��!"
914 );
915 assert_eq!(
916 &format!("{:->3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
917 "�(��!"
918 );
919 assert_eq!(
920 &format!("{:-^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
921 "�(��!"
922 );
923 assert_eq!(
924 &format!("{:-^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
925 "�(��!"
926 );
927 }
928
929 quickcheck::quickcheck! {
930 fn total_length(bstr: BString) -> bool {
931 let size = bstr.chars().count();
932 format!("{:<1$}", bstr.as_bstr(), size).chars().count() >= size
933 }
934 }
935 }
936
937 #[cfg(test)]
938 mod bstring_arbitrary {
939 use crate::bstring::BString;
940
941 use quickcheck::{Arbitrary, Gen};
942
943 impl Arbitrary for BString {
arbitrary(g: &mut Gen) -> BString944 fn arbitrary(g: &mut Gen) -> BString {
945 BString::from(Vec::<u8>::arbitrary(g))
946 }
947
shrink(&self) -> Box<dyn Iterator<Item = BString>>948 fn shrink(&self) -> Box<dyn Iterator<Item = BString>> {
949 Box::new(self.bytes.shrink().map(BString::from))
950 }
951 }
952 }
953
954 #[test]
test_debug()955 fn test_debug() {
956 use crate::{ByteSlice, B};
957
958 assert_eq!(
959 r#""\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp""#,
960 format!("{:?}", b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp".as_bstr()),
961 );
962
963 // Tests that if the underlying bytes contain the UTF-8 encoding of the
964 // replacement codepoint, then we emit the codepoint just like other
965 // non-printable Unicode characters.
966 assert_eq!(
967 b"\"\\xFF\xEF\xBF\xBD\\xFF\"".as_bstr(),
968 // Before fixing #72, the output here would be:
969 // \\xFF\\xEF\\xBF\\xBD\\xFF
970 B(&format!("{:?}", b"\xFF\xEF\xBF\xBD\xFF".as_bstr())).as_bstr(),
971 );
972 }
973
974 // See: https://github.com/BurntSushi/bstr/issues/82
975 #[test]
test_cows_regression()976 fn test_cows_regression() {
977 use crate::ByteSlice;
978 use std::borrow::Cow;
979
980 let c1 = Cow::from(b"hello bstr".as_bstr());
981 let c2 = b"goodbye bstr".as_bstr();
982 assert_ne!(c1, c2);
983
984 let c3 = Cow::from("hello str");
985 let c4 = "goodbye str";
986 assert_ne!(c3, c4);
987 }
988