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