1 macro_rules! impl_partial_eq { 2 ($lhs:ty, $rhs:ty) => { 3 #[allow(unused_lifetimes)] 4 impl<'a> PartialEq<$rhs> for $lhs { 5 #[inline] 6 fn eq(&self, other: &$rhs) -> bool { 7 let l = self.as_ref(); 8 let r: &Self = other.as_ref(); 9 PartialEq::eq(l, r) 10 } 11 } 12 13 #[allow(unused_lifetimes)] 14 impl<'a> PartialEq<$lhs> for $rhs { 15 #[inline] 16 fn eq(&self, other: &$lhs) -> bool { 17 PartialEq::eq(other, self) 18 } 19 } 20 }; 21 } 22 23 macro_rules! impl_partial_ord { 24 ($lhs:ty, $rhs:ty) => { 25 #[allow(unused_lifetimes)] 26 impl<'a> PartialOrd<$rhs> for $lhs { 27 #[inline] 28 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> { 29 let l = self.as_ref(); 30 let r: &Self = other.as_ref(); 31 PartialOrd::partial_cmp(l, r) 32 } 33 } 34 35 #[allow(unused_lifetimes)] 36 impl<'a> PartialOrd<$lhs> for $rhs { 37 #[inline] 38 fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> { 39 PartialOrd::partial_cmp(other, self) 40 } 41 } 42 }; 43 } 44 45 mod bytes { 46 use crate::lib::std::{cmp::Ordering, fmt, ops}; 47 48 use crate::stream::Bytes; 49 50 impl fmt::Display for Bytes { 51 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 53 <Self as fmt::UpperHex>::fmt(self, f) 54 } 55 } 56 57 impl fmt::Debug for Bytes { 58 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 60 <Self as fmt::UpperHex>::fmt(self, f) 61 } 62 } 63 64 impl fmt::LowerHex for Bytes { 65 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 67 for byte in self.as_bytes() { 68 write!(f, "{byte:0>2x}")?; 69 } 70 Ok(()) 71 } 72 } 73 74 impl fmt::UpperHex for Bytes { 75 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 77 for (i, byte) in self.as_bytes().iter().enumerate() { 78 if 0 < i { 79 let absolute = (self.as_bytes().as_ptr() as usize) + i; 80 if f.alternate() && absolute != 0 && absolute % 4 == 0 { 81 write!(f, "_")?; 82 } 83 } 84 write!(f, "{byte:0>2X}")?; 85 } 86 Ok(()) 87 } 88 } 89 90 impl ops::Deref for Bytes { 91 type Target = [u8]; 92 93 #[inline] deref(&self) -> &[u8]94 fn deref(&self) -> &[u8] { 95 self.as_bytes() 96 } 97 } 98 99 impl ops::Index<usize> for Bytes { 100 type Output = u8; 101 102 #[inline] index(&self, idx: usize) -> &u8103 fn index(&self, idx: usize) -> &u8 { 104 &self.as_bytes()[idx] 105 } 106 } 107 108 impl ops::Index<ops::RangeFull> for Bytes { 109 type Output = Bytes; 110 111 #[inline] index(&self, _: ops::RangeFull) -> &Bytes112 fn index(&self, _: ops::RangeFull) -> &Bytes { 113 self 114 } 115 } 116 117 impl ops::Index<ops::Range<usize>> for Bytes { 118 type Output = Bytes; 119 120 #[inline] index(&self, r: ops::Range<usize>) -> &Bytes121 fn index(&self, r: ops::Range<usize>) -> &Bytes { 122 Bytes::new(&self.as_bytes()[r.start..r.end]) 123 } 124 } 125 126 impl ops::Index<ops::RangeInclusive<usize>> for Bytes { 127 type Output = Bytes; 128 129 #[inline] index(&self, r: ops::RangeInclusive<usize>) -> &Bytes130 fn index(&self, r: ops::RangeInclusive<usize>) -> &Bytes { 131 Bytes::new(&self.as_bytes()[*r.start()..=*r.end()]) 132 } 133 } 134 135 impl ops::Index<ops::RangeFrom<usize>> for Bytes { 136 type Output = Bytes; 137 138 #[inline] index(&self, r: ops::RangeFrom<usize>) -> &Bytes139 fn index(&self, r: ops::RangeFrom<usize>) -> &Bytes { 140 Bytes::new(&self.as_bytes()[r.start..]) 141 } 142 } 143 144 impl ops::Index<ops::RangeTo<usize>> for Bytes { 145 type Output = Bytes; 146 147 #[inline] index(&self, r: ops::RangeTo<usize>) -> &Bytes148 fn index(&self, r: ops::RangeTo<usize>) -> &Bytes { 149 Bytes::new(&self.as_bytes()[..r.end]) 150 } 151 } 152 153 impl ops::Index<ops::RangeToInclusive<usize>> for Bytes { 154 type Output = Bytes; 155 156 #[inline] index(&self, r: ops::RangeToInclusive<usize>) -> &Bytes157 fn index(&self, r: ops::RangeToInclusive<usize>) -> &Bytes { 158 Bytes::new(&self.as_bytes()[..=r.end]) 159 } 160 } 161 162 impl AsRef<[u8]> for Bytes { 163 #[inline] as_ref(&self) -> &[u8]164 fn as_ref(&self) -> &[u8] { 165 self.as_bytes() 166 } 167 } 168 169 impl AsRef<Bytes> for [u8] { 170 #[inline] as_ref(&self) -> &Bytes171 fn as_ref(&self) -> &Bytes { 172 Bytes::new(self) 173 } 174 } 175 176 impl AsRef<Bytes> for str { 177 #[inline] as_ref(&self) -> &Bytes178 fn as_ref(&self) -> &Bytes { 179 Bytes::new(self) 180 } 181 } 182 183 #[cfg(feature = "alloc")] 184 impl crate::lib::std::borrow::ToOwned for Bytes { 185 type Owned = crate::lib::std::vec::Vec<u8>; 186 187 #[inline] to_owned(&self) -> Self::Owned188 fn to_owned(&self) -> Self::Owned { 189 crate::lib::std::vec::Vec::from(self.as_bytes()) 190 } 191 } 192 193 #[cfg(feature = "alloc")] 194 impl crate::lib::std::borrow::Borrow<Bytes> for crate::lib::std::vec::Vec<u8> { 195 #[inline] borrow(&self) -> &Bytes196 fn borrow(&self) -> &Bytes { 197 Bytes::from_bytes(self.as_slice()) 198 } 199 } 200 201 impl<'a> Default for &'a Bytes { default() -> &'a Bytes202 fn default() -> &'a Bytes { 203 Bytes::new(b"") 204 } 205 } 206 207 impl<'a> From<&'a [u8]> for &'a Bytes { 208 #[inline] from(s: &'a [u8]) -> &'a Bytes209 fn from(s: &'a [u8]) -> &'a Bytes { 210 Bytes::new(s) 211 } 212 } 213 214 impl<'a> From<&'a Bytes> for &'a [u8] { 215 #[inline] from(s: &'a Bytes) -> &'a [u8]216 fn from(s: &'a Bytes) -> &'a [u8] { 217 Bytes::as_bytes(s) 218 } 219 } 220 221 impl<'a> From<&'a str> for &'a Bytes { 222 #[inline] from(s: &'a str) -> &'a Bytes223 fn from(s: &'a str) -> &'a Bytes { 224 Bytes::new(s.as_bytes()) 225 } 226 } 227 228 impl Eq for Bytes {} 229 230 impl PartialEq<Bytes> for Bytes { 231 #[inline] eq(&self, other: &Bytes) -> bool232 fn eq(&self, other: &Bytes) -> bool { 233 self.as_bytes() == other.as_bytes() 234 } 235 } 236 237 impl_partial_eq!(Bytes, [u8]); 238 impl_partial_eq!(Bytes, &'a [u8]); 239 impl_partial_eq!(Bytes, str); 240 impl_partial_eq!(Bytes, &'a str); 241 242 impl PartialOrd for Bytes { 243 #[inline] partial_cmp(&self, other: &Bytes) -> Option<Ordering>244 fn partial_cmp(&self, other: &Bytes) -> Option<Ordering> { 245 Some(self.cmp(other)) 246 } 247 } 248 249 impl Ord for Bytes { 250 #[inline] cmp(&self, other: &Bytes) -> Ordering251 fn cmp(&self, other: &Bytes) -> Ordering { 252 Ord::cmp(self.as_bytes(), other.as_bytes()) 253 } 254 } 255 256 impl_partial_ord!(Bytes, [u8]); 257 impl_partial_ord!(Bytes, &'a [u8]); 258 impl_partial_ord!(Bytes, str); 259 impl_partial_ord!(Bytes, &'a str); 260 261 #[cfg(all(test, feature = "std"))] 262 mod display { 263 use crate::stream::Bytes; 264 265 #[test] clean()266 fn clean() { 267 assert_eq!(&format!("{}", Bytes::new(b"abc")), "616263"); 268 assert_eq!(&format!("{}", Bytes::new(b"\xf0\x28\x8c\xbc")), "F0288CBC"); 269 } 270 } 271 272 #[cfg(all(test, feature = "std"))] 273 mod debug { 274 use crate::stream::Bytes; 275 276 #[test] test_debug()277 fn test_debug() { 278 assert_eq!( 279 "000000206674797069736F6D0000020069736F6D69736F32617663316D70", 280 format!( 281 "{:?}", 282 Bytes::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp") 283 ), 284 ); 285 } 286 287 #[test] test_pretty_debug()288 fn test_pretty_debug() { 289 // Output can change from run-to-run 290 let _ = format!( 291 "{:#?}", 292 Bytes::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp") 293 ); 294 } 295 296 #[test] test_sliced()297 fn test_sliced() { 298 // Output can change from run-to-run 299 let total = Bytes::new(b"12345678901234567890"); 300 let _ = format!("{total:#?}"); 301 let _ = format!("{:#?}", &total[1..]); 302 let _ = format!("{:#?}", &total[10..]); 303 } 304 } 305 } 306 307 mod bstr { 308 use crate::lib::std::{cmp::Ordering, fmt, ops}; 309 310 use crate::stream::BStr; 311 312 #[cfg(feature = "alloc")] 313 impl fmt::Display for BStr { 314 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result315 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 316 crate::lib::std::string::String::from_utf8_lossy(self.as_bytes()).fmt(f) 317 } 318 } 319 320 impl fmt::Debug for BStr { 321 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result322 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 323 if !f.alternate() { 324 write!(f, "\"")?; 325 } 326 for byte in self.as_bytes() { 327 let c = *byte as char; 328 write!(f, "{}", c.escape_debug())?; 329 } 330 if !f.alternate() { 331 write!(f, "\"")?; 332 } 333 Ok(()) 334 } 335 } 336 337 impl ops::Deref for BStr { 338 type Target = [u8]; 339 340 #[inline] deref(&self) -> &[u8]341 fn deref(&self) -> &[u8] { 342 self.as_bytes() 343 } 344 } 345 346 impl ops::Index<usize> for BStr { 347 type Output = u8; 348 349 #[inline] index(&self, idx: usize) -> &u8350 fn index(&self, idx: usize) -> &u8 { 351 &self.as_bytes()[idx] 352 } 353 } 354 355 impl ops::Index<ops::RangeFull> for BStr { 356 type Output = BStr; 357 358 #[inline] index(&self, _: ops::RangeFull) -> &BStr359 fn index(&self, _: ops::RangeFull) -> &BStr { 360 self 361 } 362 } 363 364 impl ops::Index<ops::Range<usize>> for BStr { 365 type Output = BStr; 366 367 #[inline] index(&self, r: ops::Range<usize>) -> &BStr368 fn index(&self, r: ops::Range<usize>) -> &BStr { 369 BStr::new(&self.as_bytes()[r.start..r.end]) 370 } 371 } 372 373 impl ops::Index<ops::RangeInclusive<usize>> for BStr { 374 type Output = BStr; 375 376 #[inline] index(&self, r: ops::RangeInclusive<usize>) -> &BStr377 fn index(&self, r: ops::RangeInclusive<usize>) -> &BStr { 378 BStr::new(&self.as_bytes()[*r.start()..=*r.end()]) 379 } 380 } 381 382 impl ops::Index<ops::RangeFrom<usize>> for BStr { 383 type Output = BStr; 384 385 #[inline] index(&self, r: ops::RangeFrom<usize>) -> &BStr386 fn index(&self, r: ops::RangeFrom<usize>) -> &BStr { 387 BStr::new(&self.as_bytes()[r.start..]) 388 } 389 } 390 391 impl ops::Index<ops::RangeTo<usize>> for BStr { 392 type Output = BStr; 393 394 #[inline] index(&self, r: ops::RangeTo<usize>) -> &BStr395 fn index(&self, r: ops::RangeTo<usize>) -> &BStr { 396 BStr::new(&self.as_bytes()[..r.end]) 397 } 398 } 399 400 impl ops::Index<ops::RangeToInclusive<usize>> for BStr { 401 type Output = BStr; 402 403 #[inline] index(&self, r: ops::RangeToInclusive<usize>) -> &BStr404 fn index(&self, r: ops::RangeToInclusive<usize>) -> &BStr { 405 BStr::new(&self.as_bytes()[..=r.end]) 406 } 407 } 408 409 impl AsRef<[u8]> for BStr { 410 #[inline] as_ref(&self) -> &[u8]411 fn as_ref(&self) -> &[u8] { 412 self.as_bytes() 413 } 414 } 415 416 impl AsRef<BStr> for [u8] { 417 #[inline] as_ref(&self) -> &BStr418 fn as_ref(&self) -> &BStr { 419 BStr::new(self) 420 } 421 } 422 423 impl AsRef<BStr> for str { 424 #[inline] as_ref(&self) -> &BStr425 fn as_ref(&self) -> &BStr { 426 BStr::new(self) 427 } 428 } 429 430 #[cfg(feature = "alloc")] 431 impl crate::lib::std::borrow::ToOwned for BStr { 432 type Owned = crate::lib::std::vec::Vec<u8>; 433 434 #[inline] to_owned(&self) -> Self::Owned435 fn to_owned(&self) -> Self::Owned { 436 crate::lib::std::vec::Vec::from(self.as_bytes()) 437 } 438 } 439 440 #[cfg(feature = "alloc")] 441 impl crate::lib::std::borrow::Borrow<BStr> for crate::lib::std::vec::Vec<u8> { 442 #[inline] borrow(&self) -> &BStr443 fn borrow(&self) -> &BStr { 444 BStr::from_bytes(self.as_slice()) 445 } 446 } 447 448 impl<'a> Default for &'a BStr { default() -> &'a BStr449 fn default() -> &'a BStr { 450 BStr::new(b"") 451 } 452 } 453 454 impl<'a> From<&'a [u8]> for &'a BStr { 455 #[inline] from(s: &'a [u8]) -> &'a BStr456 fn from(s: &'a [u8]) -> &'a BStr { 457 BStr::new(s) 458 } 459 } 460 461 impl<'a> From<&'a BStr> for &'a [u8] { 462 #[inline] from(s: &'a BStr) -> &'a [u8]463 fn from(s: &'a BStr) -> &'a [u8] { 464 BStr::as_bytes(s) 465 } 466 } 467 468 impl<'a> From<&'a str> for &'a BStr { 469 #[inline] from(s: &'a str) -> &'a BStr470 fn from(s: &'a str) -> &'a BStr { 471 BStr::new(s.as_bytes()) 472 } 473 } 474 475 impl Eq for BStr {} 476 477 impl PartialEq<BStr> for BStr { 478 #[inline] eq(&self, other: &BStr) -> bool479 fn eq(&self, other: &BStr) -> bool { 480 self.as_bytes() == other.as_bytes() 481 } 482 } 483 484 impl_partial_eq!(BStr, [u8]); 485 impl_partial_eq!(BStr, &'a [u8]); 486 impl_partial_eq!(BStr, str); 487 impl_partial_eq!(BStr, &'a str); 488 489 impl PartialOrd for BStr { 490 #[inline] partial_cmp(&self, other: &BStr) -> Option<Ordering>491 fn partial_cmp(&self, other: &BStr) -> Option<Ordering> { 492 Some(self.cmp(other)) 493 } 494 } 495 496 impl Ord for BStr { 497 #[inline] cmp(&self, other: &BStr) -> Ordering498 fn cmp(&self, other: &BStr) -> Ordering { 499 Ord::cmp(self.as_bytes(), other.as_bytes()) 500 } 501 } 502 503 impl_partial_ord!(BStr, [u8]); 504 impl_partial_ord!(BStr, &'a [u8]); 505 impl_partial_ord!(BStr, str); 506 impl_partial_ord!(BStr, &'a str); 507 508 #[cfg(all(test, feature = "std"))] 509 mod display { 510 use crate::stream::BStr; 511 512 #[test] clean()513 fn clean() { 514 assert_eq!(&format!("{}", BStr::new(b"abc")), "abc"); 515 assert_eq!(&format!("{}", BStr::new(b"\xf0\x28\x8c\xbc")), "�(��"); 516 } 517 } 518 519 #[cfg(all(test, feature = "std"))] 520 mod debug { 521 use crate::stream::BStr; 522 523 #[test] test_debug()524 fn test_debug() { 525 assert_eq!(&format!("{:?}", BStr::new(b"abc")), "\"abc\""); 526 527 assert_eq!( 528 "\"\\0\\0\\0 ftypisom\\0\\0\\u{2}\\0isomiso2avc1mp\"", 529 format!( 530 "{:?}", 531 BStr::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp") 532 ), 533 ); 534 } 535 536 #[test] test_pretty_debug()537 fn test_pretty_debug() { 538 assert_eq!(&format!("{:#?}", BStr::new(b"abc")), "abc"); 539 } 540 } 541 } 542