ntex_bytes/bytes.rs
1use std::{cmp, hash, mem, ops};
2
3use crate::{Buf, BytesMut, storage::Storage};
4
5/// A reference counted contiguous slice of memory.
6///
7/// `Bytes` is an efficient container for storing and operating on contiguous
8/// slices of memory. It is intended primarily for use in networking code, but
9/// could have applications elsewhere as well.
10///
11/// `Bytes` values facilitate zero-copy network programming by allowing multiple
12/// `Bytes` objects to point to the same underlying memory. This is managed by
13/// using a reference count to track when the memory is no longer needed and can
14/// be freed.
15///
16/// ```
17/// use ntex_bytes::Bytes;
18///
19/// let mut mem = Bytes::from(&b"Hello world"[..]);
20/// let a = mem.slice(0..5);
21///
22/// assert_eq!(a, b"Hello");
23///
24/// let b = mem.split_to(6);
25///
26/// assert_eq!(mem, b"world");
27/// assert_eq!(b, b"Hello ");
28/// ```
29///
30/// # Memory layout
31///
32/// The `Bytes` struct itself is fairly small, limited to a pointer to the
33/// memory and two `usize` fields used to track information about which segment of
34/// the underlying memory the `Bytes` handle has access to.
35///
36/// The memory layout looks like this:
37///
38/// ```text
39/// +-------+
40/// | Bytes |
41/// +-------+
42/// / \_____
43/// | \
44/// v v
45/// +-----+------------------------------------+
46/// | MD | | Data | |
47/// +-----+------------------------------------+
48/// ```
49///
50/// `Bytes` keeps a pointer to the start of the region visible to the handle and
51/// an `offset` that can be used to calculate the beginning of the heap-allocated
52/// buffer. `Bytes` also tracks the length of its view into the memory.
53///
54/// # Sharing
55///
56/// The memory itself is reference counted, and multiple `Bytes` objects may
57/// point to the same region. Each `Bytes` handle points to a section of the
58/// memory region, and `Bytes` handles may or may not have overlapping views
59/// into the memory.
60///
61/// ```text
62///
63/// Arc ptrs +---------+
64/// ________________________ / | Bytes 2 |
65/// / +---------+
66/// / +-----------+ | |
67/// |_________/ | Bytes 1 | | |
68/// | +-----------+ | |
69/// | | | ___/ data | tail
70/// | data | tail |/ |
71/// v v v v
72/// +-----+---------------------------------+-----+
73/// | MD | | | | |
74/// +-----+---------------------------------+-----+
75/// ```
76///
77/// # Mutating
78///
79/// While `Bytes` handles may represent overlapping views of the underlying
80/// memory slice and therefore cannot be mutated, `BytesMut` handles are
81/// guaranteed to be the only handle able to view that slice of memory. As such,
82/// `BytesMut` handles may mutate the underlying memory. Note that holding a
83/// unique view of a region of memory does not mean there are no other `Bytes`
84/// handles with disjoint views of the same underlying allocation.
85///
86/// # Inline bytes
87///
88/// As an optimization, when the slice referenced by a `Bytes` handle is small
89/// enough [^1], the data may be stored inline. In this case, a clone is no longer
90/// “shallow”, and the data will be copied. `BytesMut` does not support data
91/// inlining and always allocates, but during conversion to `Bytes`, data from
92/// `BytesMut` may be inlined.
93///
94/// [^1]: Small enough: 23 bytes on 64 bit systems, 11 on 32 bit systems.
95///
96pub struct Bytes {
97 pub(crate) storage: Storage,
98}
99
100/*
101 *
102 * ===== Bytes =====
103 *
104 */
105
106impl Bytes {
107 /// Creates a new empty `Bytes`.
108 ///
109 /// This will not allocate and the returned `Bytes` handle will be empty.
110 ///
111 /// # Examples
112 ///
113 /// ```
114 /// use ntex_bytes::Bytes;
115 ///
116 /// let b = Bytes::new();
117 /// assert_eq!(&b[..], b"");
118 /// ```
119 #[inline]
120 pub const fn new() -> Bytes {
121 Bytes {
122 storage: Storage::empty(),
123 }
124 }
125
126 /// Creates a new `Bytes` from a static slice.
127 ///
128 /// The returned `Bytes` will point directly to the static slice. There is
129 /// no allocating or copying.
130 ///
131 /// # Examples
132 ///
133 /// ```
134 /// use ntex_bytes::Bytes;
135 ///
136 /// let b = Bytes::from_static(b"hello");
137 /// assert_eq!(&b[..], b"hello");
138 /// ```
139 #[inline]
140 #[must_use]
141 pub const fn from_static(bytes: &'static [u8]) -> Bytes {
142 Bytes {
143 storage: Storage::from_static(bytes),
144 }
145 }
146
147 /// Returns the number of bytes contained in this `Bytes`.
148 ///
149 /// # Examples
150 ///
151 /// ```
152 /// use ntex_bytes::Bytes;
153 ///
154 /// let b = Bytes::from(&b"hello"[..]);
155 /// assert_eq!(b.len(), 5);
156 /// ```
157 #[inline]
158 pub fn len(&self) -> usize {
159 self.storage.len()
160 }
161
162 /// Returns true if the `Bytes` has a length of 0.
163 ///
164 /// # Examples
165 ///
166 /// ```
167 /// use ntex_bytes::Bytes;
168 ///
169 /// let b = Bytes::new();
170 /// assert!(b.is_empty());
171 /// ```
172 #[inline]
173 pub fn is_empty(&self) -> bool {
174 self.storage.is_empty()
175 }
176
177 /// Returns `true` if the bytes are stored inline.
178 ///
179 /// # Examples
180 /// ```
181 /// use ntex_bytes::{Bytes, BytesMut};
182 ///
183 /// assert!(Bytes::from(BytesMut::from(&[0, 0, 0, 0][..])).is_inline());
184 /// assert!(Bytes::from(Vec::with_capacity(4)).is_inline());
185 /// assert!(!Bytes::from(&[0; 1024][..]).is_inline());
186 /// ```
187 pub fn is_inline(&self) -> bool {
188 self.storage.is_inline()
189 }
190
191 /// Creates a `Bytes` value by copying a byte slice.
192 ///
193 /// Data from the slice could be inlined.
194 #[must_use]
195 pub fn copy_from_slice(data: &[u8]) -> Self {
196 Bytes {
197 storage: Storage::from_slice(data),
198 }
199 }
200
201 /// Returns a slice of self for the provided range.
202 ///
203 /// This will increment the reference count for the underlying memory and
204 /// return a new `Bytes` handle set to the slice. A slice that fits inline
205 /// is copied instead.
206 ///
207 /// This operation is `O(1)`.
208 ///
209 /// # Examples
210 ///
211 /// ```
212 /// use ntex_bytes::Bytes;
213 ///
214 /// let a = Bytes::from(b"hello world");
215 /// let b = a.slice(2..5);
216 ///
217 /// assert_eq!(&b[..], b"llo");
218 /// assert_eq!(&b[..=1], b"ll");
219 /// assert_eq!(&b[1..=1], b"l");
220 /// ```
221 ///
222 /// # Panics
223 ///
224 /// Requires that `begin <= end` and `end <= self.len()`, otherwise slicing
225 /// will panic.
226 #[must_use]
227 pub fn slice(&self, range: impl ops::RangeBounds<usize>) -> Bytes {
228 self.slice_checked(range)
229 .expect("Requires that `begin <= end` and `end <= self.len()`")
230 }
231
232 /// Returns a slice of self for the provided range.
233 ///
234 /// Returns `None` unless `begin <= end` and `end <= self.len()`.
235 #[must_use]
236 pub fn slice_checked(&self, range: impl ops::RangeBounds<usize>) -> Option<Bytes> {
237 use std::ops::Bound;
238
239 let len = self.len();
240
241 let begin = match range.start_bound() {
242 Bound::Included(&n) => n,
243 Bound::Excluded(&n) => n.checked_add(1)?,
244 Bound::Unbounded => 0,
245 };
246
247 let end = match range.end_bound() {
248 Bound::Included(&n) => n.checked_add(1)?,
249 Bound::Excluded(&n) => n,
250 Bound::Unbounded => len,
251 };
252
253 if begin <= end && end <= len {
254 Some(Bytes {
255 storage: self.storage.slice(begin, end),
256 })
257 } else {
258 None
259 }
260 }
261
262 /// Returns a slice of self that is equivalent to the given `subset`.
263 ///
264 /// When processing a `Bytes` buffer with other tools, one often gets a
265 /// `&[u8]` which is in fact a slice of the `Bytes`, i.e. a subset of it.
266 /// This function turns that `&[u8]` into another `Bytes`, as if one had
267 /// called `self.slice()` with the offsets that correspond to `subset`.
268 ///
269 /// This operation is `O(1)`.
270 ///
271 /// # Examples
272 ///
273 /// ```
274 /// use ntex_bytes::Bytes;
275 ///
276 /// let bytes = Bytes::from(&b"012345678"[..]);
277 /// let as_slice = bytes.as_ref();
278 /// let subset = &as_slice[2..6];
279 /// let subslice = bytes.slice_ref(&subset);
280 /// assert_eq!(subslice, b"2345");
281 /// ```
282 ///
283 /// # Panics
284 ///
285 /// Requires that the given `subset` slice is in fact contained within the
286 /// `Bytes` buffer; otherwise this function will panic.
287 #[must_use]
288 pub fn slice_ref(&self, subset: &[u8]) -> Bytes {
289 self.slice_ref_checked(subset)
290 .expect("Given `subset` slice is not contained within the `Bytes` buffer")
291 }
292
293 /// Returns a slice of self that is equivalent to the given `subset`.
294 ///
295 /// Returns `None` if `subset` is not contained within the `Bytes` buffer.
296 #[must_use]
297 pub fn slice_ref_checked(&self, subset: &[u8]) -> Option<Bytes> {
298 let bytes_p = self.as_ptr() as usize;
299 let bytes_len = self.len();
300
301 let sub_p = subset.as_ptr() as usize;
302 let sub_len = subset.len();
303
304 if sub_p >= bytes_p && sub_p + sub_len <= bytes_p + bytes_len {
305 let sub_offset = sub_p - bytes_p;
306 Some(self.slice(sub_offset..(sub_offset + sub_len)))
307 } else {
308 None
309 }
310 }
311
312 /// Splits the bytes into two at the given index.
313 ///
314 /// Afterwards `self` contains elements `[0, at)`, and the returned `Bytes`
315 /// contains elements `[at, len)`.
316 ///
317 /// This is an `O(1)` operation that just increases the reference count and
318 /// sets a few indices.
319 ///
320 /// # Examples
321 ///
322 /// ```
323 /// use ntex_bytes::Bytes;
324 ///
325 /// let mut a = Bytes::from(&b"hello world"[..]);
326 /// let b = a.split_off(5);
327 ///
328 /// assert_eq!(a, b"hello");
329 /// assert_eq!(b, b" world");
330 /// ```
331 ///
332 /// # Panics
333 ///
334 /// Panics if `at > self.len()`.
335 #[must_use]
336 #[inline]
337 pub fn split_off(&mut self, at: usize) -> Bytes {
338 self.split_off_checked(at)
339 .expect("at value must be <= self.len()`")
340 }
341
342 /// Splits the bytes into two at the given index.
343 ///
344 /// Returns `None` if `at > self.len()`.
345 #[must_use]
346 #[inline]
347 pub fn split_off_checked(&mut self, at: usize) -> Option<Bytes> {
348 if at <= self.len() {
349 if at == self.len() {
350 Some(Bytes::new())
351 } else if at == 0 {
352 Some(mem::take(self))
353 } else {
354 Some(Bytes {
355 storage: self.storage.split_off(at, true),
356 })
357 }
358 } else {
359 None
360 }
361 }
362
363 /// Splits the bytes into two at the given index.
364 ///
365 /// Afterwards `self` contains elements `[at, len)`, and the returned
366 /// `Bytes` contains elements `[0, at)`.
367 ///
368 /// This is an `O(1)` operation that just increases the reference count and
369 /// sets a few indices.
370 ///
371 /// # Examples
372 ///
373 /// ```
374 /// use ntex_bytes::Bytes;
375 ///
376 /// let mut a = Bytes::from(&b"hello world"[..]);
377 /// let b = a.split_to(5);
378 ///
379 /// assert_eq!(a, b" world");
380 /// assert_eq!(b, b"hello");
381 /// ```
382 ///
383 /// # Panics
384 ///
385 /// Panics if `at > len`.
386 #[must_use]
387 #[inline]
388 pub fn split_to(&mut self, at: usize) -> Bytes {
389 self.split_to_checked(at)
390 .expect("at value must be <= self.len()`")
391 }
392
393 /// Splits the bytes into two at the given index.
394 ///
395 /// Returns `None` if `at > len`.
396 #[must_use]
397 #[inline]
398 pub fn split_to_checked(&mut self, at: usize) -> Option<Bytes> {
399 if at <= self.len() {
400 if at == self.len() {
401 Some(mem::take(self))
402 } else if at == 0 {
403 Some(Bytes::new())
404 } else {
405 Some(Bytes {
406 storage: self.storage.split_to(at),
407 })
408 }
409 } else {
410 None
411 }
412 }
413
414 /// Advance the internal cursor.
415 ///
416 /// Afterwards `self` contains elements `[cnt, len)`.
417 /// This is an `O(1)` operation.
418 ///
419 /// # Examples
420 ///
421 /// ```
422 /// use ntex_bytes::Bytes;
423 ///
424 /// let mut a = Bytes::copy_from_slice(&b"hello world"[..]);
425 /// a.advance_to(5);
426 ///
427 /// assert_eq!(&a[..], b" world");
428 /// ```
429 ///
430 /// # Panics
431 ///
432 /// Panics if `cnt > len`.
433 #[inline]
434 pub fn advance_to(&mut self, cnt: usize) {
435 // SAFETY: `set_start` checks `cnt <= len` before advancing within this live view.
436 unsafe {
437 self.storage.set_start(cnt);
438 }
439 }
440
441 /// Shortens the buffer, keeping the first `len` bytes and dropping the
442 /// rest.
443 ///
444 /// If `len` is greater than the buffer's current length, this has no
445 /// effect. The data may be inlined if it fits.
446 ///
447 /// The [`split_off`] method can emulate `truncate`, but this causes the
448 /// excess bytes to be returned instead of dropped.
449 ///
450 /// # Examples
451 ///
452 /// ```
453 /// use ntex_bytes::Bytes;
454 ///
455 /// let mut buf = Bytes::from(&b"hello world"[..]);
456 /// buf.truncate(5);
457 /// assert_eq!(buf, b"hello"[..]);
458 /// ```
459 ///
460 /// [`split_off`]: #method.split_off
461 #[inline]
462 pub fn truncate(&mut self, len: usize) {
463 self.storage.truncate(len);
464 }
465
466 /// Compacts the underlying storage to this value's current byte range.
467 ///
468 /// This can reduce retained capacity when this value is a small view into a
469 /// larger allocation, anywhere within the allocation. The data is copied if
470 /// the allocation is larger than the view by at least 64 bytes, views up to
471 /// the inline capacity are always inlined. The visible bytes are unchanged.
472 ///
473 /// # Examples
474 ///
475 /// ```
476 /// use ntex_bytes::Bytes;
477 ///
478 /// let mut buf = Bytes::from(&b"hello world"[..]);
479 /// buf.trimdown();
480 /// assert_eq!(buf, b"hello world"[..]);
481 /// ```
482 #[inline]
483 pub fn trimdown(&mut self) {
484 self.storage.trimdown();
485 }
486
487 /// Clears the buffer, removing all data.
488 ///
489 /// # Examples
490 ///
491 /// ```
492 /// use ntex_bytes::Bytes;
493 ///
494 /// let mut buf = Bytes::from(&b"hello world"[..]);
495 /// buf.clear();
496 /// assert!(buf.is_empty());
497 /// ```
498 #[inline]
499 pub fn clear(&mut self) {
500 self.storage = Storage::empty();
501 }
502
503 /// Returns an iterator over the bytes contained by the buffer.
504 ///
505 /// # Examples
506 ///
507 /// ```
508 /// use ntex_bytes::{Buf, Bytes};
509 ///
510 /// let buf = Bytes::from(&b"abc"[..]);
511 /// let mut iter = buf.iter();
512 ///
513 /// assert_eq!(iter.next().map(|b| *b), Some(b'a'));
514 /// assert_eq!(iter.next().map(|b| *b), Some(b'b'));
515 /// assert_eq!(iter.next().map(|b| *b), Some(b'c'));
516 /// assert_eq!(iter.next(), None);
517 /// ```
518 pub fn iter(&'_ self) -> std::slice::Iter<'_, u8> {
519 self.chunk().iter()
520 }
521
522 #[inline]
523 #[doc(hidden)]
524 pub fn info(&self) -> crate::info::Info {
525 self.storage.info()
526 }
527}
528
529impl_buf!(Bytes {
530 #[inline]
531 fn get_u8(&mut self) -> u8 {
532 self.storage.get_u8()
533 }
534});
535
536impl_slice_traits!(Bytes);
537
538impl Clone for Bytes {
539 #[inline]
540 fn clone(&self) -> Bytes {
541 Bytes {
542 storage: self.storage.clone(),
543 }
544 }
545}
546
547impl From<&Bytes> for Bytes {
548 fn from(src: &Bytes) -> Bytes {
549 src.clone()
550 }
551}
552
553impl From<crate::ByteString> for Bytes {
554 fn from(src: crate::ByteString) -> Bytes {
555 src.into_bytes()
556 }
557}
558
559impl From<&crate::ByteString> for Bytes {
560 fn from(src: &crate::ByteString) -> Bytes {
561 src.clone().into_bytes()
562 }
563}
564
565impl From<Vec<u8>> for Bytes {
566 /// Convert a `Vec` into a `Bytes`
567 fn from(src: Vec<u8>) -> Bytes {
568 Bytes {
569 storage: Storage::from_slice(&src),
570 }
571 }
572}
573
574impl From<String> for Bytes {
575 fn from(src: String) -> Bytes {
576 Bytes {
577 storage: Storage::from_slice(src.as_bytes()),
578 }
579 }
580}
581
582impl From<&'static [u8]> for Bytes {
583 fn from(src: &'static [u8]) -> Bytes {
584 Bytes::from_static(src)
585 }
586}
587
588impl From<&'static str> for Bytes {
589 fn from(src: &'static str) -> Bytes {
590 Bytes::from_static(src.as_bytes())
591 }
592}
593
594impl<'a, const N: usize> From<&'a [u8; N]> for Bytes {
595 fn from(src: &'a [u8; N]) -> Bytes {
596 Bytes::copy_from_slice(src)
597 }
598}
599
600impl FromIterator<u8> for Bytes {
601 fn from_iter<T: IntoIterator<Item = u8>>(into_iter: T) -> Self {
602 BytesMut::from_iter(into_iter).freeze()
603 }
604}
605
606impl<'a> FromIterator<&'a u8> for Bytes {
607 fn from_iter<T: IntoIterator<Item = &'a u8>>(into_iter: T) -> Self {
608 BytesMut::from_iter(into_iter).freeze()
609 }
610}
611
612impl Eq for Bytes {}
613
614impl PartialEq for Bytes {
615 fn eq(&self, other: &Bytes) -> bool {
616 self.storage.as_ref() == other.storage.as_ref()
617 }
618}
619
620impl PartialOrd for Bytes {
621 fn partial_cmp(&self, other: &Bytes) -> Option<cmp::Ordering> {
622 Some(self.cmp(other))
623 }
624}
625
626impl Ord for Bytes {
627 fn cmp(&self, other: &Bytes) -> cmp::Ordering {
628 self.storage.as_ref().cmp(other.storage.as_ref())
629 }
630}
631
632impl_read!(Bytes);
633
634impl hash::Hash for Bytes {
635 fn hash<H>(&self, state: &mut H)
636 where
637 H: hash::Hasher,
638 {
639 let s: &[u8] = self.as_ref();
640 s.hash(state);
641 }
642}
643
644impl_partial_eq!(Bytes);
645impl_partial_ord!(Bytes);
646
647#[cfg(test)]
648#[allow(unused_must_use)]
649mod tests {
650 use std::collections::HashMap;
651
652 use super::*;
653 use crate::{BufMut, storage::INLINE_CAP};
654
655 const LONG: &[u8] = b"mary had a1 little la2mb, little lamb, little lamb, little lamb, little lamb, little lamb \
656 mary had a little lamb, little lamb, little lamb, little lamb, little lamb, little lamb \
657 mary had a little lamb, little lamb, little lamb, little lamb, little lamb, little lamb \0";
658
659 /// STATEMENT: Reverse comparisons with `Bytes` order strings and byte containers by content.
660 ///
661 /// HOW:
662 /// - Compare slices, arrays, strings, and owned containers containing `a`, `b`, or `c` with `Bytes` containing `b` and check ordering.
663 #[test]
664 #[allow(clippy::op_ref, clippy::cmp_owned)]
665 fn partial_ord_reverse() {
666 let b = Bytes::from_static(b"b");
667 assert!(b"a"[..] < b);
668 assert!(*b"a" < b);
669 assert!(*"a" < b);
670 assert!(b"a".to_vec() < b);
671 assert!(String::from("a") < b);
672 assert!(&b"a"[..] < b);
673 assert!("a" < b);
674 assert!(b"c"[..] > b);
675 assert!("c" > b);
676 assert_eq!(b"b"[..].partial_cmp(&b), Some(cmp::Ordering::Equal));
677 }
678
679 /// STATEMENT: `slice_checked` rejects range bounds whose normalization would overflow.
680 ///
681 /// HOW:
682 /// - Slice vector-backed `LONG` with an inclusive end and excluded start at `usize::MAX` and verify both return `None`.
683 #[test]
684 fn slice_checked_max_bounds() {
685 use std::ops::Bound;
686
687 let b = Bytes::from(LONG.to_vec());
688 assert!(b.slice_checked(..=usize::MAX).is_none());
689 assert!(
690 b.slice_checked((Bound::Excluded(usize::MAX), Bound::Unbounded))
691 .is_none()
692 );
693 }
694
695 /// STATEMENT: `Bytes` views and buffer traits preserve content across storage representations.
696 ///
697 /// HOW:
698 /// - Advance, split, clear, and truncate vector, static, and inline bytes and check visible ranges.
699 /// - Exercise conversions, comparisons, hashing, `Buf` reads, `BufMut` writes, and iterator accessors against expected bytes.
700 #[test]
701 #[allow(
702 clippy::op_ref,
703 clippy::len_zero,
704 clippy::nonminimal_bool,
705 clippy::unnecessary_fallible_conversions
706 )]
707 fn bytes() {
708 let mut b = Bytes::from(LONG.to_vec());
709 b.advance_to(10);
710 assert_eq!(&b, &LONG[10..]);
711 b.advance_to(10);
712 assert_eq!(&b[..], &LONG[20..]);
713 assert_eq!(&b, &LONG[20..]);
714 b.clear();
715 assert!(b.is_inline());
716 assert!(b.is_empty());
717 assert_eq!(b.len(), 0);
718
719 let mut b = Bytes::from(LONG);
720 b.advance_to(10);
721 assert_eq!(&b, &LONG[10..]);
722 b.advance_to(10);
723 assert_eq!(&b[..], &LONG[20..]);
724 assert_eq!(&b, &LONG[20..]);
725 b.clear();
726 assert!(b.is_empty());
727 assert_eq!(b.len(), 0);
728
729 let mut b = Bytes::from(LONG);
730 b.split_off(10);
731 assert_eq!(&b, &LONG[..10]);
732 b.advance_to(5);
733 assert_eq!(&b, &LONG[5..10]);
734
735 let mut b = Bytes::copy_from_slice(&LONG[..INLINE_CAP]);
736 assert!(b.is_inline());
737 b.split_off(10);
738 assert_eq!(&b, &LONG[..10]);
739 b.advance_to(1);
740 assert_eq!(&b, &LONG[1..10]);
741
742 let mut b = Bytes::from(b"123");
743 assert!(&b"12"[..] < &b);
744 assert_eq!("123", &b);
745 assert!("12" < &b);
746 assert!("12" < b);
747 assert_eq!(b.get_u8(), b'1');
748 assert_eq!("23", &b);
749
750 let mut b = Bytes::from(&Bytes::from(LONG));
751 assert_eq!(b, LONG);
752 assert_eq!(b.get_u8(), LONG[0]);
753 assert_eq!(b.get_u8(), LONG[1]);
754 assert_eq!(b.len(), LONG.len() - 2);
755
756 let b = Bytes::from(BytesMut::from(LONG));
757 assert_eq!(b, LONG);
758
759 let mut b: Bytes = BytesMut::try_from(b).unwrap().freeze();
760 assert_eq!(b, LONG);
761 assert!(!(b > b));
762 assert_eq!(<Bytes as Buf>::remaining(&b), LONG.len());
763 assert_eq!(<Bytes as Buf>::chunk(&b), LONG);
764 <Bytes as Buf>::advance(&mut b, 10);
765 assert_eq!(Buf::chunk(&b), &LONG[10..]);
766 <Bytes as Buf>::advance(&mut b, 10);
767 assert_eq!(Buf::chunk(&b), &LONG[20..]);
768
769 let mut h: HashMap<Bytes, usize> = HashMap::default();
770 h.insert(b.clone(), 1);
771 assert_eq!(h.get(&b), Some(&1));
772
773 let mut b = BytesMut::try_from(LONG).unwrap();
774 assert_eq!(b, LONG);
775 assert_eq!(<BytesMut as Buf>::remaining(&b), LONG.len());
776 assert_eq!(<BytesMut as BufMut>::remaining_mut(&b), 0);
777 assert_eq!(<BytesMut as Buf>::chunk(&b), LONG);
778 <BytesMut as Buf>::advance(&mut b, 10);
779 assert_eq!(<BytesMut as Buf>::chunk(&b), &LONG[10..]);
780
781 let mut b = BytesMut::with_capacity(12);
782 <BytesMut as BufMut>::put_i8(&mut b, 1);
783 assert_eq!(b, b"\x01".as_ref());
784 <BytesMut as BufMut>::put_u8(&mut b, 2);
785 assert_eq!(b, b"\x01\x02".as_ref());
786 <BytesMut as BufMut>::put_slice(&mut b, b"12345");
787 assert_eq!(b, b"\x01\x0212345".as_ref());
788 <BytesMut as BufMut>::chunk_mut(&mut b).write_byte(0, b'1');
789 // SAFETY: The first spare byte was initialized by `write_byte` immediately above.
790 unsafe { <BytesMut as BufMut>::advance_mut(&mut b, 1) };
791 assert_eq!(b, b"\x01\x02123451".as_ref());
792
793 let mut iter = Bytes::from(LONG.to_vec()).into_iter();
794 assert_eq!(iter.next(), Some(LONG[0]));
795 assert_eq!(iter.next(), Some(LONG[1]));
796 assert_eq!(iter.next(), Some(LONG[2]));
797 assert_eq!(iter.next(), Some(LONG[3]));
798 assert_eq!(iter.get_ref(), &LONG[4..]);
799 assert_eq!(iter.get_mut(), &LONG[4..]);
800 let b = iter.into_inner();
801 assert_eq!(b, &LONG[4..]);
802
803 let mut b = Bytes::copy_from_slice(b"123");
804 assert!(b.is_inline());
805 assert_eq!(b.storage.capacity(), INLINE_CAP);
806 b.truncate(2);
807 assert_eq!(b, *b"12");
808 assert_eq!(bytes::buf::Buf::get_u8(&mut b), 49);
809 assert_eq!(b.len(), 1);
810 }
811
812 /// STATEMENT: Reading `Bytes` consumes available bytes without overwriting unused output space.
813 ///
814 /// HOW:
815 /// - Read `123` into a ten-byte zeroed array and check a three-byte read, an empty source, and seven untouched zeros.
816 #[test]
817 fn bytes_read() {
818 use std::io::Read;
819
820 let mut b = Bytes::copy_from_slice(b"123");
821
822 let mut buf = [0; 10];
823 assert_eq!(b.read(&mut buf).unwrap(), 3);
824 assert_eq!(b.len(), 0);
825 assert_eq!(buf, [49, 50, 51, 0, 0, 0, 0, 0, 0, 0]);
826 }
827
828 /// STATEMENT: Owned and borrowed `ByteString` conversions preserve the string bytes.
829 ///
830 /// HOW:
831 /// - Convert a static `ByteString` by reference and by value and compare both `Bytes` results with `string`.
832 #[test]
833 fn from_byte_string() {
834 let s = crate::ByteString::from_static("string");
835 assert_eq!(Bytes::from(&s), "string");
836 assert_eq!(Bytes::from(s), "string");
837 }
838}