1use core::num::NonZeroUsize;
2
3use crate::error::Needed;
4use crate::lib::std::iter::{Cloned, Enumerate};
5use crate::lib::std::slice::Iter;
6use crate::lib::std::{cmp::Ordering, fmt, ops};
7use crate::stream::AsBytes;
8use crate::stream::Checkpoint;
9use crate::stream::Compare;
10use crate::stream::CompareResult;
11use crate::stream::FindSlice;
12use crate::stream::Offset;
13#[cfg(feature = "unstable-recover")]
14#[cfg(feature = "std")]
15use crate::stream::Recover;
16use crate::stream::SliceLen;
17use crate::stream::Stream;
18use crate::stream::StreamIsPartial;
19use crate::stream::UpdateSlice;
20
21#[allow(clippy::derived_hash_with_manual_eq)]
23#[derive(Hash)]
24#[repr(transparent)]
25pub struct Bytes([u8]);
26
27impl Bytes {
28 #[inline]
30 pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &Self {
31 Self::from_bytes(bytes.as_ref())
32 }
33
34 #[inline]
35 fn from_bytes(slice: &[u8]) -> &Self {
36 unsafe { crate::lib::std::mem::transmute(slice) }
37 }
38
39 #[inline]
40 fn as_bytes(&self) -> &[u8] {
41 &self.0
42 }
43}
44
45impl SliceLen for &Bytes {
46 #[inline(always)]
47 fn slice_len(&self) -> usize {
48 self.len()
49 }
50}
51
52impl<'i> Stream for &'i Bytes {
53 type Token = u8;
54 type Slice = &'i [u8];
55
56 type IterOffsets = Enumerate<Cloned<Iter<'i, u8>>>;
57
58 type Checkpoint = Checkpoint<Self, Self>;
59
60 #[inline(always)]
61 fn iter_offsets(&self) -> Self::IterOffsets {
62 self.iter().cloned().enumerate()
63 }
64 #[inline(always)]
65 fn eof_offset(&self) -> usize {
66 self.len()
67 }
68
69 #[inline(always)]
70 fn next_token(&mut self) -> Option<Self::Token> {
71 if self.is_empty() {
72 None
73 } else {
74 let token = self[0];
75 *self = &self[1..];
76 Some(token)
77 }
78 }
79
80 #[inline(always)]
81 fn peek_token(&self) -> Option<Self::Token> {
82 if self.is_empty() {
83 None
84 } else {
85 Some(self[0])
86 }
87 }
88
89 #[inline(always)]
90 fn offset_for<P>(&self, predicate: P) -> Option<usize>
91 where
92 P: Fn(Self::Token) -> bool,
93 {
94 self.iter().position(|b| predicate(*b))
95 }
96 #[inline(always)]
97 fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
98 if let Some(needed) = tokens.checked_sub(self.len()).and_then(NonZeroUsize::new) {
99 Err(Needed::Size(needed))
100 } else {
101 Ok(tokens)
102 }
103 }
104 #[inline(always)]
105 fn next_slice(&mut self, offset: usize) -> Self::Slice {
106 let (slice, next) = self.0.split_at(offset);
107 *self = Bytes::from_bytes(next);
108 slice
109 }
110 #[inline(always)]
111 unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
112 #[cfg(debug_assertions)]
113 self.peek_slice(offset);
114
115 let slice = unsafe { self.0.get_unchecked(..offset) };
117 let next = unsafe { self.0.get_unchecked(offset..) };
119 *self = Bytes::from_bytes(next);
120 slice
121 }
122 #[inline(always)]
123 fn peek_slice(&self, offset: usize) -> Self::Slice {
124 &self[..offset]
125 }
126 #[inline(always)]
127 unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
128 #[cfg(debug_assertions)]
129 self.peek_slice(offset);
130
131 let slice = unsafe { self.0.get_unchecked(..offset) };
133 slice
134 }
135
136 #[inline(always)]
137 fn checkpoint(&self) -> Self::Checkpoint {
138 Checkpoint::<_, Self>::new(*self)
139 }
140 #[inline(always)]
141 fn reset(&mut self, checkpoint: &Self::Checkpoint) {
142 *self = checkpoint.inner;
143 }
144
145 #[inline(always)]
146 fn raw(&self) -> &dyn crate::lib::std::fmt::Debug {
147 self
148 }
149}
150
151#[cfg(feature = "unstable-recover")]
152#[cfg(feature = "std")]
153impl<E> Recover<E> for &Bytes {
154 #[inline(always)]
155 fn record_err(
156 &mut self,
157 _token_start: &Self::Checkpoint,
158 _err_start: &Self::Checkpoint,
159 err: E,
160 ) -> Result<(), E> {
161 Err(err)
162 }
163
164 #[inline(always)]
166 fn is_recovery_supported() -> bool {
167 false
168 }
169}
170
171impl StreamIsPartial for &Bytes {
172 type PartialState = ();
173
174 #[inline]
175 fn complete(&mut self) -> Self::PartialState {
176 }
178
179 #[inline]
180 fn restore_partial(&mut self, _state: Self::PartialState) {}
181
182 #[inline(always)]
183 fn is_partial_supported() -> bool {
184 false
185 }
186}
187
188impl Offset for &Bytes {
189 #[inline(always)]
190 fn offset_from(&self, start: &Self) -> usize {
191 self.as_bytes().offset_from(&start.as_bytes())
192 }
193}
194
195impl<'a> Offset<<&'a Bytes as Stream>::Checkpoint> for &'a Bytes {
196 #[inline(always)]
197 fn offset_from(&self, other: &<&'a Bytes as Stream>::Checkpoint) -> usize {
198 self.checkpoint().offset_from(other)
199 }
200}
201
202impl AsBytes for &Bytes {
203 #[inline(always)]
204 fn as_bytes(&self) -> &[u8] {
205 (*self).as_bytes()
206 }
207}
208
209impl<'a, T> Compare<T> for &'a Bytes
210where
211 &'a [u8]: Compare<T>,
212{
213 #[inline(always)]
214 fn compare(&self, t: T) -> CompareResult {
215 let bytes = (*self).as_bytes();
216 bytes.compare(t)
217 }
218}
219
220impl<'i, S> FindSlice<S> for &'i Bytes
221where
222 &'i [u8]: FindSlice<S>,
223{
224 #[inline(always)]
225 fn find_slice(&self, substr: S) -> Option<crate::lib::std::ops::Range<usize>> {
226 let bytes = (*self).as_bytes();
227 let offset = bytes.find_slice(substr);
228 offset
229 }
230}
231
232impl UpdateSlice for &Bytes {
233 #[inline(always)]
234 fn update_slice(self, inner: Self::Slice) -> Self {
235 Bytes::new(inner)
236 }
237}
238
239impl fmt::Display for Bytes {
240 #[inline]
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 <Self as fmt::UpperHex>::fmt(self, f)
243 }
244}
245
246impl fmt::Debug for Bytes {
247 #[inline]
248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249 <Self as fmt::UpperHex>::fmt(self, f)
250 }
251}
252
253impl fmt::LowerHex for Bytes {
254 #[inline]
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 for byte in self.as_bytes() {
257 write!(f, "{byte:0>2x}")?;
258 }
259 Ok(())
260 }
261}
262
263impl fmt::UpperHex for Bytes {
264 #[inline]
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 for (i, byte) in self.as_bytes().iter().enumerate() {
267 if 0 < i {
268 let absolute = (self.as_bytes().as_ptr() as usize) + i;
269 if f.alternate() && absolute != 0 && absolute % 4 == 0 {
270 write!(f, "_")?;
271 }
272 }
273 write!(f, "{byte:0>2X}")?;
274 }
275 Ok(())
276 }
277}
278
279impl ops::Deref for Bytes {
280 type Target = [u8];
281
282 #[inline]
283 fn deref(&self) -> &[u8] {
284 self.as_bytes()
285 }
286}
287
288impl ops::Index<usize> for Bytes {
289 type Output = u8;
290
291 #[inline]
292 fn index(&self, idx: usize) -> &u8 {
293 &self.as_bytes()[idx]
294 }
295}
296
297impl ops::Index<ops::RangeFull> for Bytes {
298 type Output = Bytes;
299
300 #[inline]
301 fn index(&self, _: ops::RangeFull) -> &Bytes {
302 self
303 }
304}
305
306impl ops::Index<ops::Range<usize>> for Bytes {
307 type Output = Bytes;
308
309 #[inline]
310 fn index(&self, r: ops::Range<usize>) -> &Bytes {
311 Bytes::new(&self.as_bytes()[r.start..r.end])
312 }
313}
314
315impl ops::Index<ops::RangeInclusive<usize>> for Bytes {
316 type Output = Bytes;
317
318 #[inline]
319 fn index(&self, r: ops::RangeInclusive<usize>) -> &Bytes {
320 Bytes::new(&self.as_bytes()[*r.start()..=*r.end()])
321 }
322}
323
324impl ops::Index<ops::RangeFrom<usize>> for Bytes {
325 type Output = Bytes;
326
327 #[inline]
328 fn index(&self, r: ops::RangeFrom<usize>) -> &Bytes {
329 Bytes::new(&self.as_bytes()[r.start..])
330 }
331}
332
333impl ops::Index<ops::RangeTo<usize>> for Bytes {
334 type Output = Bytes;
335
336 #[inline]
337 fn index(&self, r: ops::RangeTo<usize>) -> &Bytes {
338 Bytes::new(&self.as_bytes()[..r.end])
339 }
340}
341
342impl ops::Index<ops::RangeToInclusive<usize>> for Bytes {
343 type Output = Bytes;
344
345 #[inline]
346 fn index(&self, r: ops::RangeToInclusive<usize>) -> &Bytes {
347 Bytes::new(&self.as_bytes()[..=r.end])
348 }
349}
350
351impl AsRef<[u8]> for Bytes {
352 #[inline]
353 fn as_ref(&self) -> &[u8] {
354 self.as_bytes()
355 }
356}
357
358impl AsRef<Bytes> for [u8] {
359 #[inline]
360 fn as_ref(&self) -> &Bytes {
361 Bytes::new(self)
362 }
363}
364
365impl AsRef<Bytes> for str {
366 #[inline]
367 fn as_ref(&self) -> &Bytes {
368 Bytes::new(self)
369 }
370}
371
372#[cfg(feature = "alloc")]
373impl crate::lib::std::borrow::ToOwned for Bytes {
374 type Owned = crate::lib::std::vec::Vec<u8>;
375
376 #[inline]
377 fn to_owned(&self) -> Self::Owned {
378 crate::lib::std::vec::Vec::from(self.as_bytes())
379 }
380}
381
382#[cfg(feature = "alloc")]
383impl crate::lib::std::borrow::Borrow<Bytes> for crate::lib::std::vec::Vec<u8> {
384 #[inline]
385 fn borrow(&self) -> &Bytes {
386 Bytes::from_bytes(self.as_slice())
387 }
388}
389
390impl<'a> Default for &'a Bytes {
391 fn default() -> &'a Bytes {
392 Bytes::new(b"")
393 }
394}
395
396impl<'a> From<&'a [u8]> for &'a Bytes {
397 #[inline]
398 fn from(s: &'a [u8]) -> &'a Bytes {
399 Bytes::new(s)
400 }
401}
402
403impl<'a> From<&'a Bytes> for &'a [u8] {
404 #[inline]
405 fn from(s: &'a Bytes) -> &'a [u8] {
406 Bytes::as_bytes(s)
407 }
408}
409
410impl<'a> From<&'a str> for &'a Bytes {
411 #[inline]
412 fn from(s: &'a str) -> &'a Bytes {
413 Bytes::new(s.as_bytes())
414 }
415}
416
417impl Eq for Bytes {}
418
419impl PartialEq<Bytes> for Bytes {
420 #[inline]
421 fn eq(&self, other: &Bytes) -> bool {
422 self.as_bytes() == other.as_bytes()
423 }
424}
425
426impl_partial_eq!(Bytes, [u8]);
427impl_partial_eq!(Bytes, &'a [u8]);
428impl_partial_eq!(Bytes, str);
429impl_partial_eq!(Bytes, &'a str);
430
431impl PartialOrd for Bytes {
432 #[inline]
433 fn partial_cmp(&self, other: &Bytes) -> Option<Ordering> {
434 Some(self.cmp(other))
435 }
436}
437
438impl Ord for Bytes {
439 #[inline]
440 fn cmp(&self, other: &Bytes) -> Ordering {
441 Ord::cmp(self.as_bytes(), other.as_bytes())
442 }
443}
444
445impl_partial_ord!(Bytes, [u8]);
446impl_partial_ord!(Bytes, &'a [u8]);
447impl_partial_ord!(Bytes, str);
448impl_partial_ord!(Bytes, &'a str);
449
450#[cfg(all(test, feature = "std"))]
451mod display {
452 use crate::stream::Bytes;
453
454 #[test]
455 fn clean() {
456 assert_eq!(&format!("{}", Bytes::new(b"abc")), "616263");
457 assert_eq!(&format!("{}", Bytes::new(b"\xf0\x28\x8c\xbc")), "F0288CBC");
458 }
459}
460
461#[cfg(all(test, feature = "std"))]
462mod debug {
463 use crate::stream::Bytes;
464
465 #[test]
466 fn test_debug() {
467 assert_eq!(
468 "000000206674797069736F6D0000020069736F6D69736F32617663316D70",
469 format!(
470 "{:?}",
471 Bytes::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp")
472 ),
473 );
474 }
475
476 #[test]
477 fn test_pretty_debug() {
478 let _ = format!(
480 "{:#?}",
481 Bytes::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp")
482 );
483 }
484
485 #[test]
486 fn test_sliced() {
487 let total = Bytes::new(b"12345678901234567890");
489 let _ = format!("{total:#?}");
490 let _ = format!("{:#?}", &total[1..]);
491 let _ = format!("{:#?}", &total[10..]);
492 }
493}