macro_rules! impl_partial_eq { ($lhs:ty, $rhs:ty) => { impl<'a, 'b> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { let l = self.as_ref(); let r: &Self = other.as_ref(); PartialEq::eq(l, r) } } impl<'a, 'b> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(other, self) } } }; } macro_rules! impl_partial_ord { ($lhs:ty, $rhs:ty) => { impl<'a, 'b> PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { let l = self.as_ref(); let r: &Self = other.as_ref(); PartialOrd::partial_cmp(l, r) } } impl<'a, 'b> PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { PartialOrd::partial_cmp(other, self) } } }; } mod bytes { use crate::lib::std::{cmp::Ordering, fmt, ops}; use crate::stream::Bytes; impl fmt::Display for Bytes { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ::fmt(self, f) } } impl fmt::Debug for Bytes { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ::fmt(self, f) } } impl fmt::LowerHex for Bytes { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for byte in self.as_bytes() { write!(f, "{:0>2x}", byte)?; } Ok(()) } } impl fmt::UpperHex for Bytes { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for (i, byte) in self.as_bytes().iter().enumerate() { if 0 < i { let absolute = (self.as_bytes().as_ptr() as usize) + i; if f.alternate() && absolute != 0 && absolute % 4 == 0 { write!(f, "_")?; } } write!(f, "{:0>2X}", byte)?; } Ok(()) } } impl ops::Deref for Bytes { type Target = [u8]; #[inline] fn deref(&self) -> &[u8] { self.as_bytes() } } impl ops::Index for Bytes { type Output = u8; #[inline] fn index(&self, idx: usize) -> &u8 { &self.as_bytes()[idx] } } impl ops::Index for Bytes { type Output = Bytes; #[inline] fn index(&self, _: ops::RangeFull) -> &Bytes { self } } impl ops::Index> for Bytes { type Output = Bytes; #[inline] fn index(&self, r: ops::Range) -> &Bytes { Bytes::new(&self.as_bytes()[r.start..r.end]) } } impl ops::Index> for Bytes { type Output = Bytes; #[inline] fn index(&self, r: ops::RangeInclusive) -> &Bytes { Bytes::new(&self.as_bytes()[*r.start()..=*r.end()]) } } impl ops::Index> for Bytes { type Output = Bytes; #[inline] fn index(&self, r: ops::RangeFrom) -> &Bytes { Bytes::new(&self.as_bytes()[r.start..]) } } impl ops::Index> for Bytes { type Output = Bytes; #[inline] fn index(&self, r: ops::RangeTo) -> &Bytes { Bytes::new(&self.as_bytes()[..r.end]) } } impl ops::Index> for Bytes { type Output = Bytes; #[inline] fn index(&self, r: ops::RangeToInclusive) -> &Bytes { Bytes::new(&self.as_bytes()[..=r.end]) } } impl AsRef<[u8]> for Bytes { #[inline] fn as_ref(&self) -> &[u8] { self.as_bytes() } } impl AsRef for [u8] { #[inline] fn as_ref(&self) -> &Bytes { Bytes::new(self) } } impl AsRef for str { #[inline] fn as_ref(&self) -> &Bytes { Bytes::new(self) } } #[cfg(feature = "alloc")] impl crate::lib::std::borrow::ToOwned for Bytes { type Owned = crate::lib::std::vec::Vec; #[inline] fn to_owned(&self) -> Self::Owned { crate::lib::std::vec::Vec::from(self.as_bytes()) } } #[cfg(feature = "alloc")] impl crate::lib::std::borrow::Borrow for crate::lib::std::vec::Vec { #[inline] fn borrow(&self) -> &Bytes { Bytes::from_bytes(self.as_slice()) } } impl<'a> Default for &'a Bytes { fn default() -> &'a Bytes { Bytes::new(b"") } } impl<'a> From<&'a [u8]> for &'a Bytes { #[inline] fn from(s: &'a [u8]) -> &'a Bytes { Bytes::new(s) } } impl<'a> From<&'a Bytes> for &'a [u8] { #[inline] fn from(s: &'a Bytes) -> &'a [u8] { Bytes::as_bytes(s) } } impl<'a> From<&'a str> for &'a Bytes { #[inline] fn from(s: &'a str) -> &'a Bytes { Bytes::new(s.as_bytes()) } } impl Eq for Bytes {} impl PartialEq for Bytes { #[inline] fn eq(&self, other: &Bytes) -> bool { self.as_bytes() == other.as_bytes() } } impl_partial_eq!(Bytes, [u8]); impl_partial_eq!(Bytes, &'a [u8]); impl_partial_eq!(Bytes, str); impl_partial_eq!(Bytes, &'a str); impl PartialOrd for Bytes { #[inline] fn partial_cmp(&self, other: &Bytes) -> Option { PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes()) } } impl Ord for Bytes { #[inline] fn cmp(&self, other: &Bytes) -> Ordering { self.partial_cmp(other).unwrap() } } impl_partial_ord!(Bytes, [u8]); impl_partial_ord!(Bytes, &'a [u8]); impl_partial_ord!(Bytes, str); impl_partial_ord!(Bytes, &'a str); #[cfg(all(test, feature = "std"))] mod display { use crate::stream::Bytes; #[test] fn clean() { assert_eq!(&format!("{}", Bytes::new(b"abc")), "616263"); assert_eq!(&format!("{}", Bytes::new(b"\xf0\x28\x8c\xbc")), "F0288CBC"); } } #[cfg(all(test, feature = "std"))] mod debug { use crate::stream::Bytes; #[test] fn test_debug() { assert_eq!( "000000206674797069736F6D0000020069736F6D69736F32617663316D70", format!( "{:?}", Bytes::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp") ), ); } #[test] fn test_pretty_debug() { // Output can change from run-to-run format!( "{:#?}", Bytes::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp") ); } #[test] fn test_sliced() { // Output can change from run-to-run let total = Bytes::new(b"12345678901234567890"); format!("{:#?}", total); format!("{:#?}", &total[1..]); format!("{:#?}", &total[10..]); } } } mod bstr { use crate::lib::std::{cmp::Ordering, fmt, ops}; use crate::stream::BStr; #[cfg(feature = "alloc")] impl fmt::Display for BStr { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { crate::lib::std::string::String::from_utf8_lossy(self.as_bytes()).fmt(f) } } impl fmt::Debug for BStr { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if !f.alternate() { write!(f, "\"")?; } for byte in self.as_bytes() { let c = *byte as char; write!(f, "{}", c.escape_debug())?; } if !f.alternate() { write!(f, "\"")?; } Ok(()) } } impl ops::Deref for BStr { type Target = [u8]; #[inline] fn deref(&self) -> &[u8] { self.as_bytes() } } impl ops::Index for BStr { type Output = u8; #[inline] fn index(&self, idx: usize) -> &u8 { &self.as_bytes()[idx] } } impl ops::Index for BStr { type Output = BStr; #[inline] fn index(&self, _: ops::RangeFull) -> &BStr { self } } impl ops::Index> for BStr { type Output = BStr; #[inline] fn index(&self, r: ops::Range) -> &BStr { BStr::new(&self.as_bytes()[r.start..r.end]) } } impl ops::Index> for BStr { type Output = BStr; #[inline] fn index(&self, r: ops::RangeInclusive) -> &BStr { BStr::new(&self.as_bytes()[*r.start()..=*r.end()]) } } impl ops::Index> for BStr { type Output = BStr; #[inline] fn index(&self, r: ops::RangeFrom) -> &BStr { BStr::new(&self.as_bytes()[r.start..]) } } impl ops::Index> for BStr { type Output = BStr; #[inline] fn index(&self, r: ops::RangeTo) -> &BStr { BStr::new(&self.as_bytes()[..r.end]) } } impl ops::Index> for BStr { type Output = BStr; #[inline] fn index(&self, r: ops::RangeToInclusive) -> &BStr { BStr::new(&self.as_bytes()[..=r.end]) } } impl AsRef<[u8]> for BStr { #[inline] fn as_ref(&self) -> &[u8] { self.as_bytes() } } impl AsRef for [u8] { #[inline] fn as_ref(&self) -> &BStr { BStr::new(self) } } impl AsRef for str { #[inline] fn as_ref(&self) -> &BStr { BStr::new(self) } } #[cfg(feature = "alloc")] impl crate::lib::std::borrow::ToOwned for BStr { type Owned = crate::lib::std::vec::Vec; #[inline] fn to_owned(&self) -> Self::Owned { crate::lib::std::vec::Vec::from(self.as_bytes()) } } #[cfg(feature = "alloc")] impl crate::lib::std::borrow::Borrow for crate::lib::std::vec::Vec { #[inline] fn borrow(&self) -> &BStr { BStr::from_bytes(self.as_slice()) } } impl<'a> Default for &'a BStr { fn default() -> &'a BStr { BStr::new(b"") } } impl<'a> From<&'a [u8]> for &'a BStr { #[inline] fn from(s: &'a [u8]) -> &'a BStr { BStr::new(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::new(s.as_bytes()) } } impl Eq for BStr {} impl PartialEq 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); impl PartialOrd for BStr { #[inline] fn partial_cmp(&self, other: &BStr) -> Option { 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(all(test, feature = "std"))] mod display { use crate::stream::BStr; #[test] fn clean() { assert_eq!(&format!("{}", BStr::new(b"abc")), "abc"); assert_eq!(&format!("{}", BStr::new(b"\xf0\x28\x8c\xbc")), "�(��"); } } #[cfg(all(test, feature = "std"))] mod debug { use crate::stream::BStr; #[test] fn test_debug() { assert_eq!(&format!("{:?}", BStr::new(b"abc")), "\"abc\""); assert_eq!( "\"\\0\\0\\0 ftypisom\\0\\0\\u{2}\\0isomiso2avc1mp\"", format!( "{:?}", BStr::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp") ), ); } #[test] fn test_pretty_debug() { assert_eq!(&format!("{:#?}", BStr::new(b"abc")), "abc"); } } }