summaryrefslogtreecommitdiffstats
path: root/vendor/bstr/src/impls.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
commit2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4 (patch)
tree033cc839730fda84ff08db877037977be94e5e3a /vendor/bstr/src/impls.rs
parentInitial commit. (diff)
downloadcargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.tar.xz
cargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.zip
Adding upstream version 0.70.1+ds1.upstream/0.70.1+ds1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/bstr/src/impls.rs')
-rw-r--r--vendor/bstr/src/impls.rs1228
1 files changed, 1228 insertions, 0 deletions
diff --git a/vendor/bstr/src/impls.rs b/vendor/bstr/src/impls.rs
new file mode 100644
index 0000000..861ca53
--- /dev/null
+++ b/vendor/bstr/src/impls.rs
@@ -0,0 +1,1228 @@
+macro_rules! impl_partial_eq {
+ ($lhs:ty, $rhs:ty) => {
+ impl<'a, 'b> PartialEq<$rhs> for $lhs {
+ #[inline]
+ fn eq(&self, other: &$rhs) -> bool {
+ let other: &[u8] = other.as_ref();
+ PartialEq::eq(self.as_bytes(), other)
+ }
+ }
+
+ impl<'a, 'b> PartialEq<$lhs> for $rhs {
+ #[inline]
+ fn eq(&self, other: &$lhs) -> bool {
+ let this: &[u8] = self.as_ref();
+ PartialEq::eq(this, other.as_bytes())
+ }
+ }
+ };
+}
+
+#[cfg(feature = "alloc")]
+macro_rules! impl_partial_eq_cow {
+ ($lhs:ty, $rhs:ty) => {
+ impl<'a, 'b> PartialEq<$rhs> for $lhs {
+ #[inline]
+ fn eq(&self, other: &$rhs) -> bool {
+ let other: &[u8] = (&**other).as_ref();
+ PartialEq::eq(self.as_bytes(), other)
+ }
+ }
+
+ impl<'a, 'b> PartialEq<$lhs> for $rhs {
+ #[inline]
+ fn eq(&self, other: &$lhs) -> bool {
+ let this: &[u8] = (&**other).as_ref();
+ PartialEq::eq(this, self.as_bytes())
+ }
+ }
+ };
+}
+
+macro_rules! impl_partial_ord {
+ ($lhs:ty, $rhs:ty) => {
+ impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
+ let other: &[u8] = other.as_ref();
+ PartialOrd::partial_cmp(self.as_bytes(), other)
+ }
+ }
+
+ impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
+ let this: &[u8] = self.as_ref();
+ PartialOrd::partial_cmp(this, other.as_bytes())
+ }
+ }
+ };
+}
+
+#[cfg(feature = "alloc")]
+mod bstring {
+ use core::{
+ cmp::Ordering, convert::TryFrom, fmt, iter::FromIterator, ops,
+ };
+
+ use alloc::{
+ borrow::{Borrow, BorrowMut, Cow, ToOwned},
+ string::String,
+ vec,
+ vec::Vec,
+ };
+
+ use crate::{
+ bstr::BStr, bstring::BString, ext_slice::ByteSlice, ext_vec::ByteVec,
+ };
+
+ impl fmt::Display for BString {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self.as_bstr(), f)
+ }
+ }
+
+ impl fmt::Debug for BString {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(self.as_bstr(), f)
+ }
+ }
+
+ impl ops::Deref for BString {
+ type Target = Vec<u8>;
+
+ #[inline]
+ fn deref(&self) -> &Vec<u8> {
+ self.as_vec()
+ }
+ }
+
+ impl ops::DerefMut for BString {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Vec<u8> {
+ self.as_vec_mut()
+ }
+ }
+
+ impl AsRef<[u8]> for BString {
+ #[inline]
+ fn as_ref(&self) -> &[u8] {
+ self.as_bytes()
+ }
+ }
+
+ impl AsRef<BStr> for BString {
+ #[inline]
+ fn as_ref(&self) -> &BStr {
+ self.as_bstr()
+ }
+ }
+
+ impl AsMut<[u8]> for BString {
+ #[inline]
+ fn as_mut(&mut self) -> &mut [u8] {
+ self.as_bytes_mut()
+ }
+ }
+
+ impl AsMut<BStr> for BString {
+ #[inline]
+ fn as_mut(&mut self) -> &mut BStr {
+ self.as_mut_bstr()
+ }
+ }
+
+ impl Borrow<[u8]> for BString {
+ #[inline]
+ fn borrow(&self) -> &[u8] {
+ self.as_bytes()
+ }
+ }
+
+ impl Borrow<BStr> for BString {
+ #[inline]
+ fn borrow(&self) -> &BStr {
+ self.as_bstr()
+ }
+ }
+
+ impl Borrow<BStr> for Vec<u8> {
+ #[inline]
+ fn borrow(&self) -> &BStr {
+ self.as_slice().as_bstr()
+ }
+ }
+
+ impl Borrow<BStr> for String {
+ #[inline]
+ fn borrow(&self) -> &BStr {
+ self.as_bytes().as_bstr()
+ }
+ }
+
+ impl BorrowMut<[u8]> for BString {
+ #[inline]
+ fn borrow_mut(&mut self) -> &mut [u8] {
+ self.as_bytes_mut()
+ }
+ }
+
+ impl BorrowMut<BStr> for BString {
+ #[inline]
+ fn borrow_mut(&mut self) -> &mut BStr {
+ self.as_mut_bstr()
+ }
+ }
+
+ impl BorrowMut<BStr> for Vec<u8> {
+ #[inline]
+ fn borrow_mut(&mut self) -> &mut BStr {
+ BStr::new_mut(self.as_mut_slice())
+ }
+ }
+
+ impl ToOwned for BStr {
+ type Owned = BString;
+
+ #[inline]
+ fn to_owned(&self) -> BString {
+ BString::from(self)
+ }
+ }
+
+ impl Default for BString {
+ fn default() -> BString {
+ BString::from(vec![])
+ }
+ }
+
+ impl<'a, const N: usize> From<&'a [u8; N]> for BString {
+ #[inline]
+ fn from(s: &'a [u8; N]) -> BString {
+ BString::from(&s[..])
+ }
+ }
+
+ impl<const N: usize> From<[u8; N]> for BString {
+ #[inline]
+ fn from(s: [u8; N]) -> BString {
+ BString::from(&s[..])
+ }
+ }
+
+ impl<'a> From<&'a [u8]> for BString {
+ #[inline]
+ fn from(s: &'a [u8]) -> BString {
+ BString::from(s.to_vec())
+ }
+ }
+
+ impl From<Vec<u8>> for BString {
+ #[inline]
+ fn from(s: Vec<u8>) -> BString {
+ BString::new(s)
+ }
+ }
+
+ impl From<BString> for Vec<u8> {
+ #[inline]
+ fn from(s: BString) -> Vec<u8> {
+ s.into_vec()
+ }
+ }
+
+ impl<'a> From<&'a str> for BString {
+ #[inline]
+ fn from(s: &'a str) -> BString {
+ BString::from(s.as_bytes().to_vec())
+ }
+ }
+
+ impl From<String> for BString {
+ #[inline]
+ fn from(s: String) -> BString {
+ BString::from(s.into_bytes())
+ }
+ }
+
+ impl<'a> From<&'a BStr> for BString {
+ #[inline]
+ fn from(s: &'a BStr) -> BString {
+ BString::from(s.bytes.to_vec())
+ }
+ }
+
+ impl<'a> From<BString> for Cow<'a, BStr> {
+ #[inline]
+ fn from(s: BString) -> Cow<'a, BStr> {
+ Cow::Owned(s)
+ }
+ }
+
+ impl TryFrom<BString> for String {
+ type Error = crate::FromUtf8Error;
+
+ #[inline]
+ fn try_from(s: BString) -> Result<String, crate::FromUtf8Error> {
+ s.into_vec().into_string()
+ }
+ }
+
+ impl<'a> TryFrom<&'a BString> for &'a str {
+ type Error = crate::Utf8Error;
+
+ #[inline]
+ fn try_from(s: &'a BString) -> Result<&'a str, crate::Utf8Error> {
+ s.as_bytes().to_str()
+ }
+ }
+
+ impl FromIterator<char> for BString {
+ #[inline]
+ fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> BString {
+ BString::from(iter.into_iter().collect::<String>())
+ }
+ }
+
+ impl FromIterator<u8> for BString {
+ #[inline]
+ fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> BString {
+ BString::from(iter.into_iter().collect::<Vec<u8>>())
+ }
+ }
+
+ impl<'a> FromIterator<&'a str> for BString {
+ #[inline]
+ fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> BString {
+ let mut buf = vec![];
+ for b in iter {
+ buf.push_str(b);
+ }
+ BString::from(buf)
+ }
+ }
+
+ impl<'a> FromIterator<&'a [u8]> for BString {
+ #[inline]
+ fn from_iter<T: IntoIterator<Item = &'a [u8]>>(iter: T) -> BString {
+ let mut buf = vec![];
+ for b in iter {
+ buf.push_str(b);
+ }
+ BString::from(buf)
+ }
+ }
+
+ impl<'a> FromIterator<&'a BStr> for BString {
+ #[inline]
+ fn from_iter<T: IntoIterator<Item = &'a BStr>>(iter: T) -> BString {
+ let mut buf = vec![];
+ for b in iter {
+ buf.push_str(b);
+ }
+ BString::from(buf)
+ }
+ }
+
+ impl FromIterator<BString> for BString {
+ #[inline]
+ fn from_iter<T: IntoIterator<Item = BString>>(iter: T) -> BString {
+ let mut buf = vec![];
+ for b in iter {
+ buf.push_str(b);
+ }
+ BString::from(buf)
+ }
+ }
+
+ impl Eq for BString {}
+
+ impl PartialEq for BString {
+ #[inline]
+ fn eq(&self, other: &BString) -> bool {
+ &self[..] == &other[..]
+ }
+ }
+
+ impl_partial_eq!(BString, Vec<u8>);
+ impl_partial_eq!(BString, [u8]);
+ impl_partial_eq!(BString, &'a [u8]);
+ impl_partial_eq!(BString, String);
+ impl_partial_eq!(BString, str);
+ impl_partial_eq!(BString, &'a str);
+ impl_partial_eq!(BString, BStr);
+ impl_partial_eq!(BString, &'a BStr);
+
+ impl PartialOrd for BString {
+ #[inline]
+ fn partial_cmp(&self, other: &BString) -> Option<Ordering> {
+ PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes())
+ }
+ }
+
+ impl Ord for BString {
+ #[inline]
+ fn cmp(&self, other: &BString) -> Ordering {
+ self.partial_cmp(other).unwrap()
+ }
+ }
+
+ impl_partial_ord!(BString, Vec<u8>);
+ impl_partial_ord!(BString, [u8]);
+ impl_partial_ord!(BString, &'a [u8]);
+ impl_partial_ord!(BString, String);
+ impl_partial_ord!(BString, str);
+ impl_partial_ord!(BString, &'a str);
+ impl_partial_ord!(BString, BStr);
+ impl_partial_ord!(BString, &'a BStr);
+}
+
+mod bstr {
+ use core::{
+ borrow::{Borrow, BorrowMut},
+ cmp::Ordering,
+ convert::TryFrom,
+ fmt, ops,
+ };
+
+ #[cfg(feature = "alloc")]
+ use alloc::{borrow::Cow, boxed::Box, string::String, vec::Vec};
+
+ use crate::{bstr::BStr, ext_slice::ByteSlice};
+
+ impl fmt::Display for BStr {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ /// Write the given bstr (lossily) to the given formatter.
+ fn write_bstr(
+ f: &mut fmt::Formatter<'_>,
+ bstr: &BStr,
+ ) -> Result<(), fmt::Error> {
+ for chunk in bstr.utf8_chunks() {
+ f.write_str(chunk.valid())?;
+ if !chunk.invalid().is_empty() {
+ f.write_str("\u{FFFD}")?;
+ }
+ }
+ Ok(())
+ }
+
+ /// Write 'num' fill characters to the given formatter.
+ fn write_pads(
+ f: &mut fmt::Formatter<'_>,
+ num: usize,
+ ) -> fmt::Result {
+ let fill = f.fill();
+ for _ in 0..num {
+ f.write_fmt(format_args!("{}", fill))?;
+ }
+ Ok(())
+ }
+
+ if let Some(align) = f.align() {
+ let width = f.width().unwrap_or(0);
+ let nchars = self.chars().count();
+ let remaining_pads = width.saturating_sub(nchars);
+ match align {
+ fmt::Alignment::Left => {
+ write_bstr(f, self)?;
+ write_pads(f, remaining_pads)?;
+ }
+ fmt::Alignment::Right => {
+ write_pads(f, remaining_pads)?;
+ write_bstr(f, self)?;
+ }
+ fmt::Alignment::Center => {
+ let half = remaining_pads / 2;
+ let second_half = if remaining_pads % 2 == 0 {
+ half
+ } else {
+ half + 1
+ };
+ write_pads(f, half)?;
+ write_bstr(f, self)?;
+ write_pads(f, second_half)?;
+ }
+ }
+ Ok(())
+ } else {
+ write_bstr(f, self)?;
+ Ok(())
+ }
+ }
+ }
+
+ impl fmt::Debug for BStr {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "\"")?;
+ for (s, e, ch) in self.char_indices() {
+ match ch {
+ '\0' => write!(f, "\\0")?,
+ '\u{FFFD}' => {
+ let bytes = self[s..e].as_bytes();
+ if bytes == b"\xEF\xBF\xBD" {
+ write!(f, "{}", ch.escape_debug())?;
+ } else {
+ for &b in self[s..e].as_bytes() {
+ write!(f, r"\x{:02X}", b)?;
+ }
+ }
+ }
+ // ASCII control characters except \0, \n, \r, \t
+ '\x01'..='\x08'
+ | '\x0b'
+ | '\x0c'
+ | '\x0e'..='\x19'
+ | '\x7f' => {
+ write!(f, "\\x{:02x}", ch as u32)?;
+ }
+ '\n' | '\r' | '\t' | _ => {
+ write!(f, "{}", ch.escape_debug())?;
+ }
+ }
+ }
+ write!(f, "\"")?;
+ Ok(())
+ }
+ }
+
+ impl ops::Deref for BStr {
+ type Target = [u8];
+
+ #[inline]
+ fn deref(&self) -> &[u8] {
+ &self.bytes
+ }
+ }
+
+ impl ops::DerefMut for BStr {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut [u8] {
+ &mut self.bytes
+ }
+ }
+
+ impl ops::Index<usize> for BStr {
+ type Output = u8;
+
+ #[inline]
+ fn index(&self, idx: usize) -> &u8 {
+ &self.as_bytes()[idx]
+ }
+ }
+
+ impl ops::Index<ops::RangeFull> for BStr {
+ type Output = BStr;
+
+ #[inline]
+ fn index(&self, _: ops::RangeFull) -> &BStr {
+ self
+ }
+ }
+
+ impl ops::Index<ops::Range<usize>> for BStr {
+ type Output = BStr;
+
+ #[inline]
+ fn index(&self, r: ops::Range<usize>) -> &BStr {
+ BStr::new(&self.as_bytes()[r.start..r.end])
+ }
+ }
+
+ impl ops::Index<ops::RangeInclusive<usize>> for BStr {
+ type Output = BStr;
+
+ #[inline]
+ fn index(&self, r: ops::RangeInclusive<usize>) -> &BStr {
+ BStr::new(&self.as_bytes()[*r.start()..=*r.end()])
+ }
+ }
+
+ impl ops::Index<ops::RangeFrom<usize>> for BStr {
+ type Output = BStr;
+
+ #[inline]
+ fn index(&self, r: ops::RangeFrom<usize>) -> &BStr {
+ BStr::new(&self.as_bytes()[r.start..])
+ }
+ }
+
+ impl ops::Index<ops::RangeTo<usize>> for BStr {
+ type Output = BStr;
+
+ #[inline]
+ fn index(&self, r: ops::RangeTo<usize>) -> &BStr {
+ BStr::new(&self.as_bytes()[..r.end])
+ }
+ }
+
+ impl ops::Index<ops::RangeToInclusive<usize>> for BStr {
+ type Output = BStr;
+
+ #[inline]
+ fn index(&self, r: ops::RangeToInclusive<usize>) -> &BStr {
+ BStr::new(&self.as_bytes()[..=r.end])
+ }
+ }
+
+ impl ops::IndexMut<usize> for BStr {
+ #[inline]
+ fn index_mut(&mut self, idx: usize) -> &mut u8 {
+ &mut self.bytes[idx]
+ }
+ }
+
+ impl ops::IndexMut<ops::RangeFull> for BStr {
+ #[inline]
+ fn index_mut(&mut self, _: ops::RangeFull) -> &mut BStr {
+ self
+ }
+ }
+
+ impl ops::IndexMut<ops::Range<usize>> for BStr {
+ #[inline]
+ fn index_mut(&mut self, r: ops::Range<usize>) -> &mut BStr {
+ BStr::from_bytes_mut(&mut self.bytes[r.start..r.end])
+ }
+ }
+
+ impl ops::IndexMut<ops::RangeInclusive<usize>> for BStr {
+ #[inline]
+ fn index_mut(&mut self, r: ops::RangeInclusive<usize>) -> &mut BStr {
+ BStr::from_bytes_mut(&mut self.bytes[*r.start()..=*r.end()])
+ }
+ }
+
+ impl ops::IndexMut<ops::RangeFrom<usize>> for BStr {
+ #[inline]
+ fn index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut BStr {
+ BStr::from_bytes_mut(&mut self.bytes[r.start..])
+ }
+ }
+
+ impl ops::IndexMut<ops::RangeTo<usize>> for BStr {
+ #[inline]
+ fn index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut BStr {
+ BStr::from_bytes_mut(&mut self.bytes[..r.end])
+ }
+ }
+
+ impl ops::IndexMut<ops::RangeToInclusive<usize>> for BStr {
+ #[inline]
+ fn index_mut(&mut self, r: ops::RangeToInclusive<usize>) -> &mut BStr {
+ BStr::from_bytes_mut(&mut self.bytes[..=r.end])
+ }
+ }
+
+ impl AsRef<[u8]> for BStr {
+ #[inline]
+ fn as_ref(&self) -> &[u8] {
+ self.as_bytes()
+ }
+ }
+
+ impl AsRef<BStr> for BStr {
+ #[inline]
+ fn as_ref(&self) -> &BStr {
+ self
+ }
+ }
+
+ impl AsRef<BStr> for [u8] {
+ #[inline]
+ fn as_ref(&self) -> &BStr {
+ BStr::new(self)
+ }
+ }
+
+ impl AsRef<BStr> for str {
+ #[inline]
+ fn as_ref(&self) -> &BStr {
+ BStr::new(self)
+ }
+ }
+
+ impl AsMut<[u8]> for BStr {
+ #[inline]
+ fn as_mut(&mut self) -> &mut [u8] {
+ &mut self.bytes
+ }
+ }
+
+ impl AsMut<BStr> for [u8] {
+ #[inline]
+ fn as_mut(&mut self) -> &mut BStr {
+ BStr::new_mut(self)
+ }
+ }
+
+ impl Borrow<BStr> for [u8] {
+ #[inline]
+ fn borrow(&self) -> &BStr {
+ self.as_bstr()
+ }
+ }
+
+ impl Borrow<BStr> for str {
+ #[inline]
+ fn borrow(&self) -> &BStr {
+ self.as_bytes().as_bstr()
+ }
+ }
+
+ impl Borrow<[u8]> for BStr {
+ #[inline]
+ fn borrow(&self) -> &[u8] {
+ self.as_bytes()
+ }
+ }
+
+ impl BorrowMut<BStr> for [u8] {
+ #[inline]
+ fn borrow_mut(&mut self) -> &mut BStr {
+ BStr::new_mut(self)
+ }
+ }
+
+ impl BorrowMut<[u8]> for BStr {
+ #[inline]
+ fn borrow_mut(&mut self) -> &mut [u8] {
+ self.as_bytes_mut()
+ }
+ }
+
+ impl<'a> Default for &'a BStr {
+ fn default() -> &'a BStr {
+ BStr::from_bytes(b"")
+ }
+ }
+
+ impl<'a> Default for &'a mut BStr {
+ fn default() -> &'a mut BStr {
+ BStr::from_bytes_mut(&mut [])
+ }
+ }
+
+ impl<'a, const N: usize> From<&'a [u8; N]> for &'a BStr {
+ #[inline]
+ fn from(s: &'a [u8; N]) -> &'a BStr {
+ BStr::from_bytes(s)
+ }
+ }
+
+ impl<'a> From<&'a [u8]> for &'a BStr {
+ #[inline]
+ fn from(s: &'a [u8]) -> &'a BStr {
+ BStr::from_bytes(s)
+ }
+ }
+
+ impl<'a> From<&'a BStr> for &'a [u8] {
+ #[inline]
+ fn from(s: &'a BStr) -> &'a [u8] {
+ BStr::as_bytes(s)
+ }
+ }
+
+ impl<'a> From<&'a str> for &'a BStr {
+ #[inline]
+ fn from(s: &'a str) -> &'a BStr {
+ BStr::from_bytes(s.as_bytes())
+ }
+ }
+
+ #[cfg(feature = "alloc")]
+ impl<'a> From<&'a BStr> for Cow<'a, BStr> {
+ #[inline]
+ fn from(s: &'a BStr) -> Cow<'a, BStr> {
+ Cow::Borrowed(s)
+ }
+ }
+
+ #[cfg(feature = "alloc")]
+ impl From<Box<[u8]>> for Box<BStr> {
+ #[inline]
+ fn from(s: Box<[u8]>) -> Box<BStr> {
+ BStr::from_boxed_bytes(s)
+ }
+ }
+
+ #[cfg(feature = "alloc")]
+ impl From<Box<BStr>> for Box<[u8]> {
+ #[inline]
+ fn from(s: Box<BStr>) -> Box<[u8]> {
+ BStr::into_boxed_bytes(s)
+ }
+ }
+
+ impl<'a> TryFrom<&'a BStr> for &'a str {
+ type Error = crate::Utf8Error;
+
+ #[inline]
+ fn try_from(s: &'a BStr) -> Result<&'a str, crate::Utf8Error> {
+ s.as_bytes().to_str()
+ }
+ }
+
+ #[cfg(feature = "alloc")]
+ impl<'a> TryFrom<&'a BStr> for String {
+ type Error = crate::Utf8Error;
+
+ #[inline]
+ fn try_from(s: &'a BStr) -> Result<String, crate::Utf8Error> {
+ Ok(s.as_bytes().to_str()?.into())
+ }
+ }
+
+ #[cfg(feature = "alloc")]
+ impl Clone for Box<BStr> {
+ #[inline]
+ fn clone(&self) -> Self {
+ BStr::from_boxed_bytes(self.as_bytes().into())
+ }
+ }
+
+ impl Eq for BStr {}
+
+ impl PartialEq<BStr> for BStr {
+ #[inline]
+ fn eq(&self, other: &BStr) -> bool {
+ self.as_bytes() == other.as_bytes()
+ }
+ }
+
+ impl_partial_eq!(BStr, [u8]);
+ impl_partial_eq!(BStr, &'a [u8]);
+ impl_partial_eq!(BStr, str);
+ impl_partial_eq!(BStr, &'a str);
+
+ #[cfg(feature = "alloc")]
+ impl_partial_eq!(BStr, Vec<u8>);
+ #[cfg(feature = "alloc")]
+ impl_partial_eq!(&'a BStr, Vec<u8>);
+ #[cfg(feature = "alloc")]
+ impl_partial_eq!(BStr, String);
+ #[cfg(feature = "alloc")]
+ impl_partial_eq!(&'a BStr, String);
+ #[cfg(feature = "alloc")]
+ impl_partial_eq_cow!(&'a BStr, Cow<'a, BStr>);
+ #[cfg(feature = "alloc")]
+ impl_partial_eq_cow!(&'a BStr, Cow<'a, str>);
+ #[cfg(feature = "alloc")]
+ impl_partial_eq_cow!(&'a BStr, Cow<'a, [u8]>);
+
+ impl PartialOrd for BStr {
+ #[inline]
+ fn partial_cmp(&self, other: &BStr) -> Option<Ordering> {
+ PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes())
+ }
+ }
+
+ impl Ord for BStr {
+ #[inline]
+ fn cmp(&self, other: &BStr) -> Ordering {
+ self.partial_cmp(other).unwrap()
+ }
+ }
+
+ impl_partial_ord!(BStr, [u8]);
+ impl_partial_ord!(BStr, &'a [u8]);
+ impl_partial_ord!(BStr, str);
+ impl_partial_ord!(BStr, &'a str);
+
+ #[cfg(feature = "alloc")]
+ impl_partial_ord!(BStr, Vec<u8>);
+ #[cfg(feature = "alloc")]
+ impl_partial_ord!(&'a BStr, Vec<u8>);
+ #[cfg(feature = "alloc")]
+ impl_partial_ord!(BStr, String);
+ #[cfg(feature = "alloc")]
+ impl_partial_ord!(&'a BStr, String);
+}
+
+#[cfg(feature = "serde")]
+mod bstr_serde {
+ use core::fmt;
+
+ use serde::{
+ de::Error, de::Visitor, Deserialize, Deserializer, Serialize,
+ Serializer,
+ };
+
+ use crate::bstr::BStr;
+
+ impl Serialize for BStr {
+ #[inline]
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ serializer.serialize_bytes(self.as_bytes())
+ }
+ }
+
+ impl<'a, 'de: 'a> Deserialize<'de> for &'a BStr {
+ #[inline]
+ fn deserialize<D>(deserializer: D) -> Result<&'a BStr, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct BStrVisitor;
+
+ impl<'de> Visitor<'de> for BStrVisitor {
+ type Value = &'de BStr;
+
+ fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("a borrowed byte string")
+ }
+
+ #[inline]
+ fn visit_borrowed_bytes<E: Error>(
+ self,
+ value: &'de [u8],
+ ) -> Result<&'de BStr, E> {
+ Ok(BStr::new(value))
+ }
+
+ #[inline]
+ fn visit_borrowed_str<E: Error>(
+ self,
+ value: &'de str,
+ ) -> Result<&'de BStr, E> {
+ Ok(BStr::new(value))
+ }
+ }
+
+ deserializer.deserialize_bytes(BStrVisitor)
+ }
+ }
+}
+
+#[cfg(all(feature = "serde", feature = "alloc"))]
+mod bstring_serde {
+ use core::{cmp, fmt};
+
+ use alloc::{boxed::Box, string::String, vec::Vec};
+
+ use serde::{
+ de::Error, de::SeqAccess, de::Visitor, Deserialize, Deserializer,
+ Serialize, Serializer,
+ };
+
+ use crate::{bstr::BStr, bstring::BString};
+
+ impl Serialize for BString {
+ #[inline]
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ serializer.serialize_bytes(self.as_bytes())
+ }
+ }
+
+ impl<'de> Deserialize<'de> for BString {
+ #[inline]
+ fn deserialize<D>(deserializer: D) -> Result<BString, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct BStringVisitor;
+
+ impl<'de> Visitor<'de> for BStringVisitor {
+ type Value = BString;
+
+ fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("a byte string")
+ }
+
+ #[inline]
+ fn visit_seq<V: SeqAccess<'de>>(
+ self,
+ mut visitor: V,
+ ) -> Result<BString, V::Error> {
+ let len = cmp::min(visitor.size_hint().unwrap_or(0), 256);
+ let mut bytes = Vec::with_capacity(len);
+ while let Some(v) = visitor.next_element()? {
+ bytes.push(v);
+ }
+ Ok(BString::from(bytes))
+ }
+
+ #[inline]
+ fn visit_bytes<E: Error>(
+ self,
+ value: &[u8],
+ ) -> Result<BString, E> {
+ Ok(BString::from(value))
+ }
+
+ #[inline]
+ fn visit_byte_buf<E: Error>(
+ self,
+ value: Vec<u8>,
+ ) -> Result<BString, E> {
+ Ok(BString::from(value))
+ }
+
+ #[inline]
+ fn visit_str<E: Error>(
+ self,
+ value: &str,
+ ) -> Result<BString, E> {
+ Ok(BString::from(value))
+ }
+
+ #[inline]
+ fn visit_string<E: Error>(
+ self,
+ value: String,
+ ) -> Result<BString, E> {
+ Ok(BString::from(value))
+ }
+ }
+
+ deserializer.deserialize_byte_buf(BStringVisitor)
+ }
+ }
+
+ impl<'de> Deserialize<'de> for Box<BStr> {
+ #[inline]
+ fn deserialize<D>(deserializer: D) -> Result<Box<BStr>, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct BoxedBStrVisitor;
+
+ impl<'de> Visitor<'de> for BoxedBStrVisitor {
+ type Value = Box<BStr>;
+
+ fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("a boxed byte string")
+ }
+
+ #[inline]
+ fn visit_seq<V: SeqAccess<'de>>(
+ self,
+ mut visitor: V,
+ ) -> Result<Box<BStr>, V::Error> {
+ let len = cmp::min(visitor.size_hint().unwrap_or(0), 256);
+ let mut bytes = Vec::with_capacity(len);
+ while let Some(v) = visitor.next_element()? {
+ bytes.push(v);
+ }
+ Ok(BStr::from_boxed_bytes(bytes.into_boxed_slice()))
+ }
+
+ #[inline]
+ fn visit_bytes<E: Error>(
+ self,
+ value: &[u8],
+ ) -> Result<Box<BStr>, E> {
+ Ok(BStr::from_boxed_bytes(
+ value.to_vec().into_boxed_slice(),
+ ))
+ }
+
+ #[inline]
+ fn visit_byte_buf<E: Error>(
+ self,
+ value: Vec<u8>,
+ ) -> Result<Box<BStr>, E> {
+ Ok(BStr::from_boxed_bytes(value.into_boxed_slice()))
+ }
+
+ #[inline]
+ fn visit_str<E: Error>(
+ self,
+ value: &str,
+ ) -> Result<Box<BStr>, E> {
+ Ok(BStr::from_boxed_bytes(
+ value.as_bytes().to_vec().into_boxed_slice(),
+ ))
+ }
+
+ #[inline]
+ fn visit_string<E: Error>(
+ self,
+ value: String,
+ ) -> Result<Box<BStr>, E> {
+ Ok(BStr::from_boxed_bytes(
+ value.into_bytes().into_boxed_slice(),
+ ))
+ }
+ }
+
+ deserializer.deserialize_byte_buf(BoxedBStrVisitor)
+ }
+ }
+}
+
+#[cfg(all(test, feature = "std"))]
+mod display {
+ #[cfg(not(miri))]
+ use crate::bstring::BString;
+ use crate::ByteSlice;
+
+ #[test]
+ fn clean() {
+ assert_eq!(&format!("{}", &b"abc".as_bstr()), "abc");
+ assert_eq!(&format!("{}", &b"\xf0\x28\x8c\xbc".as_bstr()), "�(��");
+ }
+
+ #[test]
+ fn width_bigger_than_bstr() {
+ assert_eq!(&format!("{:<7}!", &b"abc".as_bstr()), "abc !");
+ assert_eq!(&format!("{:>7}!", &b"abc".as_bstr()), " abc!");
+ assert_eq!(&format!("{:^7}!", &b"abc".as_bstr()), " abc !");
+ assert_eq!(&format!("{:^6}!", &b"abc".as_bstr()), " abc !");
+ assert_eq!(&format!("{:-<7}!", &b"abc".as_bstr()), "abc----!");
+ assert_eq!(&format!("{:->7}!", &b"abc".as_bstr()), "----abc!");
+ assert_eq!(&format!("{:-^7}!", &b"abc".as_bstr()), "--abc--!");
+ assert_eq!(&format!("{:-^6}!", &b"abc".as_bstr()), "-abc--!");
+
+ assert_eq!(
+ &format!("{:<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(�� !"
+ );
+ assert_eq!(
+ &format!("{:>7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ " �(��!"
+ );
+ assert_eq!(
+ &format!("{:^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ " �(�� !"
+ );
+ assert_eq!(
+ &format!("{:^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ " �(�� !"
+ );
+
+ assert_eq!(
+ &format!("{:-<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(��---!"
+ );
+ assert_eq!(
+ &format!("{:->7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "---�(��!"
+ );
+ assert_eq!(
+ &format!("{:-^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "-�(��--!"
+ );
+ assert_eq!(
+ &format!("{:-^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "-�(��-!"
+ );
+ }
+
+ #[test]
+ fn width_lesser_than_bstr() {
+ assert_eq!(&format!("{:<2}!", &b"abc".as_bstr()), "abc!");
+ assert_eq!(&format!("{:>2}!", &b"abc".as_bstr()), "abc!");
+ assert_eq!(&format!("{:^2}!", &b"abc".as_bstr()), "abc!");
+ assert_eq!(&format!("{:-<2}!", &b"abc".as_bstr()), "abc!");
+ assert_eq!(&format!("{:->2}!", &b"abc".as_bstr()), "abc!");
+ assert_eq!(&format!("{:-^2}!", &b"abc".as_bstr()), "abc!");
+
+ assert_eq!(
+ &format!("{:<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(��!"
+ );
+ assert_eq!(
+ &format!("{:>3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(��!"
+ );
+ assert_eq!(
+ &format!("{:^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(��!"
+ );
+ assert_eq!(
+ &format!("{:^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(��!"
+ );
+
+ assert_eq!(
+ &format!("{:-<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(��!"
+ );
+ assert_eq!(
+ &format!("{:->3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(��!"
+ );
+ assert_eq!(
+ &format!("{:-^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(��!"
+ );
+ assert_eq!(
+ &format!("{:-^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+ "�(��!"
+ );
+ }
+
+ #[cfg(not(miri))]
+ quickcheck::quickcheck! {
+ fn total_length(bstr: BString) -> bool {
+ let size = bstr.chars().count();
+ format!("{:<1$}", bstr.as_bstr(), size).chars().count() >= size
+ }
+ }
+}
+
+#[cfg(all(test, feature = "alloc"))]
+mod bstring_arbitrary {
+ use crate::bstring::BString;
+
+ use quickcheck::{Arbitrary, Gen};
+
+ impl Arbitrary for BString {
+ fn arbitrary(g: &mut Gen) -> BString {
+ BString::from(Vec::<u8>::arbitrary(g))
+ }
+
+ fn shrink(&self) -> Box<dyn Iterator<Item = BString>> {
+ Box::new(self.as_vec().shrink().map(BString::from))
+ }
+ }
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn test_debug() {
+ use crate::{ByteSlice, B};
+
+ assert_eq!(
+ r#""\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp""#,
+ format!("{:?}", b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp".as_bstr()),
+ );
+
+ // Tests that if the underlying bytes contain the UTF-8 encoding of the
+ // replacement codepoint, then we emit the codepoint just like other
+ // non-printable Unicode characters.
+ assert_eq!(
+ b"\"\\xFF\xEF\xBF\xBD\\xFF\"".as_bstr(),
+ // Before fixing #72, the output here would be:
+ // \\xFF\\xEF\\xBF\\xBD\\xFF
+ B(&format!("{:?}", b"\xFF\xEF\xBF\xBD\xFF".as_bstr())).as_bstr(),
+ );
+}
+
+// See: https://github.com/BurntSushi/bstr/issues/82
+#[test]
+#[cfg(feature = "std")]
+fn test_cows_regression() {
+ use std::borrow::Cow;
+
+ use crate::ByteSlice;
+
+ let c1 = Cow::from(b"hello bstr".as_bstr());
+ let c2 = b"goodbye bstr".as_bstr();
+ assert_ne!(c1, c2);
+
+ let c3 = Cow::from("hello str");
+ let c4 = "goodbye str";
+ assert_ne!(c3, c4);
+}