Skip to main content

smol_bytes/
bytes_mut.rs

1use core::{mem::MaybeUninit, ops::RangeBounds};
2
3use ::bytes::BufMut;
4use bytes::Buf;
5
6use crate::{
7  INLINE_CAP, InvalidIntegerLength, OutOfBounds, RangeOutOfBounds, TryPutIntegerCheckedError,
8  buffer::{Buffer, checked_signed_range, checked_unsigned_range},
9  bytes::RawBytes,
10  utf8_edit::{RawUtf8Storage, replace_bytes},
11};
12
13mod cmp;
14mod fmt;
15mod from;
16mod iter;
17mod ops;
18
19#[cfg(feature = "arbitrary")]
20mod arbitrary;
21#[cfg(feature = "borsh")]
22mod borsh;
23#[cfg(feature = "quickcheck")]
24mod quickcheck;
25#[cfg(feature = "serde")]
26mod serde;
27
28#[cfg(feature = "pyo3")]
29mod python;
30
31#[cfg(feature = "wasm")]
32mod wasm;
33
34#[doc = "Growable mutable byte buffer with inline/heap storage."]
35#[doc = ""]
36#[doc = "Stores up to 62 bytes inline on the stack. Larger data automatically"]
37#[doc = "promotes to heap allocation. Heap storage does not automatically return"]
38#[doc = "to inline storage."]
39#[cfg_attr(
40  not(feature = "wasm"),
41  doc = " Call [`try_make_inline`](Self::try_make_inline) to compact an eligible Rust value."
42)]
43#[cfg_attr(not(feature = "wasm"), doc = "")]
44#[cfg_attr(not(feature = "wasm"), doc = "# Inline vs Heap Storage")]
45#[cfg_attr(not(feature = "wasm"), doc = "")]
46#[cfg_attr(
47  not(feature = "wasm"),
48  doc = "- **Inline**: Buffers ≤62 bytes are stored directly in the `BytesMut` struct"
49)]
50#[cfg_attr(
51  not(feature = "wasm"),
52  doc = "- **Heap**: Buffers >62 bytes are automatically promoted to heap allocation"
53)]
54#[cfg_attr(
55  not(feature = "wasm"),
56  doc = "- Once promoted to heap, the buffer stays on the heap (no automatic demotion)"
57)]
58#[cfg_attr(not(feature = "wasm"), doc = "")]
59#[cfg_attr(not(feature = "wasm"), doc = "# Split Operations")]
60#[cfg_attr(not(feature = "wasm"), doc = "")]
61#[cfg_attr(
62  not(feature = "wasm"),
63  doc = "Split operations have different behavior based on storage type:"
64)]
65#[cfg_attr(
66  not(feature = "wasm"),
67  doc = "- [`split_off`](Self::split_off): Returns `BytesMut` for both heap and inline storage"
68)]
69#[cfg_attr(
70  not(feature = "wasm"),
71  doc = "- [`split_to`](Self::split_to): Returns `BytesMut` for both heap and inline storage"
72)]
73#[cfg_attr(
74  not(feature = "wasm"),
75  doc = "- [`split`](Self::split): Returns `BytesMut` for both heap and inline storage"
76)]
77#[cfg_attr(
78  not(feature = "wasm"),
79  doc = "- [`unsplit`](Self::unsplit): Always consumes and appends the other buffer"
80)]
81#[cfg_attr(not(feature = "wasm"), doc = "")]
82#[cfg_attr(not(feature = "wasm"), doc = "## Examples")]
83#[cfg_attr(not(feature = "wasm"), doc = "")]
84#[cfg_attr(not(feature = "wasm"), doc = "```")]
85#[cfg_attr(not(feature = "wasm"), doc = "use smol_bytes::BytesMut;")]
86#[cfg_attr(not(feature = "wasm"), doc = "")]
87#[cfg_attr(
88  not(feature = "wasm"),
89  doc = "let mut buf = BytesMut::from(&b\"hello\"[..]);"
90)]
91#[cfg_attr(not(feature = "wasm"), doc = "assert!(buf.is_inline());")]
92#[cfg_attr(not(feature = "wasm"), doc = "```")]
93#[cfg_attr(feature = "wasm", doc = "")]
94#[cfg_attr(feature = "wasm", doc = "@example")]
95#[cfg_attr(feature = "wasm", doc = "```typescript")]
96#[cfg_attr(feature = "wasm", doc = "import { BytesMut } from 'smol-bytes';")]
97#[cfg_attr(feature = "wasm", doc = "const buf = BytesMut.withCapacity(100);")]
98#[cfg_attr(feature = "wasm", doc = "buf.putSlice(new Uint8Array([1, 2, 3]));")]
99#[cfg_attr(feature = "wasm", doc = "console.log(buf.len()); // 3")]
100#[cfg_attr(feature = "wasm", doc = "```")]
101#[derive(Clone)]
102#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass(from_py_object))]
103#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen)]
104pub struct BytesMut(Repr);
105
106impl Default for BytesMut {
107  #[cfg_attr(not(coverage), inline(always))]
108  fn default() -> Self {
109    Self::new()
110  }
111}
112
113impl BytesMut {
114  #[cfg_attr(not(coverage), inline(always))]
115  pub(crate) fn from_bytes(bytes: bytes::Bytes) -> Self {
116    if !bytes.is_unique() && bytes.len() <= INLINE_CAP {
117      // SAFETY: bytes.len() is guaranteed to be less than or equal to INLINE_CAP
118      return Self(Repr::Inline(unsafe { Buffer::copy_from_slice(&bytes) }));
119    }
120
121    Self(Repr::Heap(bytes.into()))
122  }
123
124  #[cfg_attr(not(coverage), inline(always))]
125  pub(crate) fn from_bytes_mut(bytes: bytes::BytesMut) -> Self {
126    Self(Repr::Heap(bytes))
127  }
128
129  #[cfg_attr(not(coverage), inline(always))]
130  pub(crate) fn from_inline(bytes: Buffer) -> Self {
131    Self(Repr::Inline(bytes))
132  }
133}
134
135impl BytesMut {
136  /// Creates a new `BytesMut` containing `len` zeros.
137  ///
138  /// The resulting object has a length of `len` and a capacity greater
139  /// than or equal to `len`. The entire length of the object will be filled
140  /// with zeros.
141  ///
142  /// On some platforms or allocators this function may be faster than
143  /// a manual implementation.
144  ///
145  /// ## Examples
146  ///
147  /// ```
148  /// use smol_bytes::BytesMut;
149  ///
150  /// let zeros = BytesMut::zeroed(42);
151  ///
152  /// assert!(zeros.capacity() >= 42);
153  /// assert_eq!(zeros.len(), 42);
154  /// zeros.into_iter().for_each(|x| assert_eq!(x, 0));
155  /// ```
156  pub fn zeroed(len: usize) -> Self {
157    if len <= INLINE_CAP {
158      // SAFETY: len is guaranteed to be less than or equal to INLINE_CAP
159      Self(Repr::Inline(unsafe { Buffer::zeroed(len) }))
160    } else {
161      Self(Repr::Heap(bytes::BytesMut::zeroed(len)))
162    }
163  }
164
165  /// Creates a new, empty `BytesMut`.
166  ///
167  /// ## Example
168  ///
169  /// ```rust
170  /// use smol_bytes::BytesMut;
171  ///
172  /// let bytes = BytesMut::new();
173  /// assert_eq!(bytes.len(), 0);
174  /// ```
175  #[cfg_attr(not(coverage), inline(always))]
176  pub const fn new() -> Self {
177    Self(Repr::Inline(Buffer::new()))
178  }
179
180  /// Creates a new `BytesMut` with the specified capacity.
181  ///
182  /// The returned `BytesMut` will be able to hold at least capacity bytes without reallocating.
183  ///
184  /// It is important to note that this function does not specify the length of the returned BytesMut, but only the capacity.
185  #[cfg_attr(not(coverage), inline(always))]
186  pub fn with_capacity(capacity: usize) -> Self {
187    if capacity <= INLINE_CAP {
188      Self(Repr::Inline(Buffer::new()))
189    } else {
190      Self(Repr::Heap(bytes::BytesMut::with_capacity(capacity)))
191    }
192  }
193
194  /// Appends given bytes to this `BytesMut`.
195  ///
196  /// If this `BytesMut` object does not have enough capacity, it is resized
197  /// first.
198  ///
199  /// ## Examples
200  ///
201  /// ```
202  /// use smol_bytes::BytesMut;
203  ///
204  /// let mut buf = BytesMut::with_capacity(0);
205  /// buf.extend_from_slice(b"aaabbb");
206  /// buf.extend_from_slice(b"cccddd");
207  ///
208  /// assert_eq!(b"aaabbbcccddd", &buf[..]);
209  /// ```
210  #[inline]
211  pub fn extend_from_slice(&mut self, extend: &[u8]) {
212    match &mut self.0 {
213      Repr::Inline(b) => {
214        let requested = extend.len();
215        if b.try_reclaim(requested) {
216          b.put_slice(extend);
217          return;
218        }
219
220        let required = b.len().checked_add(requested).expect("capacity overflow");
221        let mut new_buf = bytes::BytesMut::with_capacity(required);
222        new_buf.put_slice(b.as_slice());
223        new_buf.extend_from_slice(extend);
224        self.0 = Repr::Heap(new_buf);
225      }
226      Repr::Heap(b) => b.extend_from_slice(extend),
227    }
228  }
229
230  /// Replaces a range of visible bytes with `replacement`.
231  ///
232  /// # Panics
233  ///
234  /// Panics if the range is invalid.
235  pub fn replace_range(&mut self, range: impl RangeBounds<usize>, replacement: &[u8]) {
236    self
237      .try_replace_range(range, replacement)
238      .unwrap_or_else(|error| panic!("replace_range failed: {error}"));
239  }
240
241  /// Tries to replace a range of visible bytes with `replacement`.
242  ///
243  /// The range is normalized before this growable buffer reserves storage, so
244  /// an invalid range leaves it unchanged.
245  pub fn try_replace_range(
246    &mut self,
247    range: impl RangeBounds<usize>,
248    replacement: &[u8],
249  ) -> Result<(), RangeOutOfBounds> {
250    let (start, end) = crate::normalize_range(range, self.len())?;
251    let mut storage = RawUtf8Storage::growable(self);
252    replace_bytes(&mut storage, start, end, replacement);
253    Ok(())
254  }
255
256  /// Appends a copy of the specified visible byte range.
257  ///
258  /// # Panics
259  ///
260  /// Panics if the range is invalid or growing the buffer overflows the
261  /// address space.
262  pub fn extend_from_within(&mut self, range: impl RangeBounds<usize>) {
263    self
264      .try_extend_from_within(range)
265      .unwrap_or_else(|error| panic!("extend_from_within failed: {error}"));
266  }
267
268  /// Tries to append a copy of the specified visible byte range.
269  ///
270  /// The range is normalized before this growable buffer reserves storage, so
271  /// an invalid range leaves it unchanged.
272  pub fn try_extend_from_within(
273    &mut self,
274    range: impl RangeBounds<usize>,
275  ) -> Result<(), RangeOutOfBounds> {
276    let old_len = self.len();
277    let (start, end) = crate::normalize_range(range, old_len)?;
278    let count = end - start;
279    let new_len = old_len.checked_add(count).expect("buffer length overflow");
280    if count == 0 {
281      return Ok(());
282    }
283
284    self.resize(new_len, 0);
285    self.as_mut_slice().copy_within(start..end, old_len);
286    Ok(())
287  }
288
289  /// Clears the buffer, removing all data. Existing capacity is preserved.
290  ///
291  /// ## Example
292  ///
293  /// ```rust
294  /// use smol_bytes::BytesMut;
295  ///
296  /// let mut bytes = BytesMut::from(&b"hello world"[..]);
297  /// bytes.clear();
298  /// assert_eq!(bytes.len(), 0);
299  /// ```
300  #[cfg_attr(not(coverage), inline(always))]
301  pub fn clear(&mut self) {
302    match &mut self.0 {
303      Repr::Inline(b) => b.clear(),
304      Repr::Heap(b) => b.clear(),
305    }
306  }
307
308  /// Shortens the buffer, keeping the first len bytes and dropping the rest.
309  ///
310  /// If len is greater than the buffer’s current length, this has no effect.
311  ///
312  /// Existing underlying capacity is preserved.
313  ///
314  /// ## Example
315  ///
316  /// ```rust
317  /// use smol_bytes::BytesMut;
318  ///
319  /// let mut bytes = BytesMut::from(&b"hello world"[..]);
320  ///
321  /// bytes.truncate(5);
322  /// assert_eq!(bytes.as_slice(), b"hello");
323  /// ```
324  #[cfg_attr(not(coverage), inline(always))]
325  pub fn truncate(&mut self, len: usize) {
326    match &mut self.0 {
327      Repr::Inline(b) => b.truncate(len),
328      Repr::Heap(b) => b.truncate(len),
329    }
330  }
331
332  /// Returns the number of bytes the `BytesMut` can hold without reallocating.
333  ///
334  /// ## Example
335  ///
336  /// ```rust
337  ///
338  /// use smol_bytes::BytesMut;
339  ///
340  /// let bytes = BytesMut::with_capacity(100);
341  ///
342  /// assert_eq!(bytes.capacity(), 100);
343  /// ```
344  #[cfg_attr(not(coverage), inline(always))]
345  pub fn capacity(&self) -> usize {
346    match &self.0 {
347      Repr::Inline(b) => b.capacity(),
348      Repr::Heap(b) => b.capacity(),
349    }
350  }
351
352  /// Returns `true` if the `BytesMut` is using inline storage.
353  ///
354  /// ## Examples
355  ///
356  /// ```rust
357  /// use smol_bytes::BytesMut;
358  ///
359  /// let inline_buf = BytesMut::with_capacity(10);
360  /// assert!(inline_buf.is_inline());
361  ///
362  /// let heap_buf = BytesMut::with_capacity(100);
363  /// assert!(!heap_buf.is_inline());
364  /// ```
365  #[cfg_attr(not(coverage), inline(always))]
366  pub const fn is_inline(&self) -> bool {
367    matches!(&self.0, Repr::Inline(_))
368  }
369
370  /// Returns `true` if the `BytesMut` is using heap storage.
371  ///
372  /// ## Examples
373  ///
374  /// ```
375  /// use smol_bytes::BytesMut;
376  ///
377  /// let inline_buf = BytesMut::with_capacity(10);
378  /// assert!(!inline_buf.is_heap());
379  ///
380  /// let heap_buf = BytesMut::with_capacity(100);
381  /// assert!(heap_buf.is_heap());
382  /// ```
383  pub const fn is_heap(&self) -> bool {
384    matches!(&self.0, Repr::Heap(_))
385  }
386
387  /// Unwraps the inline buffer, consuming `self`.
388  ///
389  /// ## Panics
390  /// - Panics if the buffer is heap allocated.
391  ///
392  /// ## Examples
393  ///
394  /// ```
395  /// use smol_bytes::BytesMut;
396  ///
397  /// let buf = BytesMut::from(&b"hello"[..]);
398  ///
399  /// let inline_buffer = buf.unwrap_inline();
400  /// assert_eq!(&inline_buffer[..], b"hello");
401  /// ```
402  #[inline]
403  pub fn unwrap_inline(self) -> Buffer {
404    match self.0 {
405      Repr::Inline(b) => b,
406      Repr::Heap(_) => panic!("called `BytesMut::unwrap_inline()` on a heap allocated buffer"),
407    }
408  }
409
410  /// Attempts to unwrap the inline buffer, consuming `self`.
411  ///
412  /// ## Examples
413  ///
414  /// ```
415  /// use smol_bytes::BytesMut;
416  ///
417  /// let inline_buf = BytesMut::from(&b"hello"[..]);
418  /// let heap_buf = BytesMut::with_capacity(100);
419  ///
420  /// assert!(inline_buf.try_unwrap_inline().is_ok());
421  /// assert!(heap_buf.try_unwrap_inline().is_err());
422  /// ```
423  #[inline]
424  pub fn try_unwrap_inline(self) -> Result<Buffer, bytes::BytesMut> {
425    match self.0 {
426      Repr::Inline(b) => Ok(b),
427      Repr::Heap(b) => Err(b),
428    }
429  }
430
431  /// Unwraps the heap buffer, consuming `self`.
432  ///
433  /// ## Panics
434  /// - Panics if the buffer is inline.
435  ///
436  /// ## Examples
437  ///
438  /// ```
439  /// use smol_bytes::BytesMut;
440  ///
441  /// let mut buf = BytesMut::with_capacity(100);
442  /// buf.extend_from_slice(b"hello world and more data that exceeds inline capacity................................");
443  ///
444  /// let heap_buffer = buf.unwrap_heap();
445  /// assert_eq!(&heap_buffer[..], b"hello world and more data that exceeds inline capacity................................");
446  /// ```
447  #[inline]
448  pub fn unwrap_heap(self) -> bytes::BytesMut {
449    match self.0 {
450      Repr::Inline(_) => panic!("called `BytesMut::unwrap_heap()` on an inline buffer"),
451      Repr::Heap(b) => b,
452    }
453  }
454
455  /// Attempts to unwrap the heap buffer, consuming `self`.
456  ///
457  /// ## Examples
458  ///
459  /// ```
460  /// use smol_bytes::BytesMut;
461  ///
462  /// let inline_buf = BytesMut::from(&b"hello"[..]);
463  /// let mut heap_buf = BytesMut::with_capacity(100);
464  /// heap_buf.extend_from_slice(b"hello world and more data that exceeds inline capacity................................");
465  ///
466  /// assert!(heap_buf.try_unwrap_heap().is_ok());
467  /// assert!(inline_buf.try_unwrap_heap().is_err());
468  /// ```
469  #[inline]
470  pub fn try_unwrap_heap(self) -> Result<bytes::BytesMut, Buffer> {
471    match self.0 {
472      Repr::Inline(b) => Err(b),
473      Repr::Heap(b) => Ok(b),
474    }
475  }
476
477  /// Tries to move this visible byte view into a fixed inline [`Buffer`].
478  ///
479  /// Inline values move their inline storage while preserving the cursor.
480  /// Short heap views are copied into a new inline buffer with cursor zero.
481  /// Longer values are returned unchanged.
482  pub fn try_into_buffer(self) -> Result<Buffer, Self> {
483    if self.len() > INLINE_CAP {
484      return Err(self);
485    }
486
487    match self.0 {
488      Repr::Inline(storage) => Ok(storage),
489      Repr::Heap(bytes) => {
490        let visible: &[u8] = bytes.as_ref();
491        Ok(Buffer::try_from(visible).expect("length checked before conversion"))
492      }
493    }
494  }
495
496  /// Converts the `BytesMut` into a heap allocated buffer if it is currently inline.
497  ///
498  /// If the buffer is already heap allocated, this function does nothing.
499  ///
500  /// ## Examples
501  ///
502  /// ```
503  /// use smol_bytes::BytesMut;
504  ///
505  /// let mut buf = BytesMut::from(&b"hello"[..]);
506  /// assert!(buf.is_inline());
507  /// buf.make_heap();
508  /// assert!(buf.is_heap());
509  /// ```
510  pub fn make_heap(&mut self) {
511    match &mut self.0 {
512      Repr::Inline(b) => {
513        let mut new_buf = bytes::BytesMut::with_capacity(b.len());
514        new_buf.put_slice(b.as_slice());
515        self.0 = Repr::Heap(new_buf);
516      }
517      Repr::Heap(_) => {}
518    }
519  }
520
521  /// Copies the current heap view into inline storage when it fits.
522  ///
523  /// Returns `false` without changing the buffer when the current view is
524  /// larger than [`INLINE_CAP`]. Existing inline buffers are left unchanged
525  /// and return `true`. This never allocates, but a successful conversion
526  /// discards hidden heap bytes and excess capacity.
527  ///
528  /// ```
529  /// use smol_bytes::{BytesMut, INLINE_CAP};
530  ///
531  /// let mut bytes = BytesMut::with_capacity(128);
532  /// bytes.extend_from_slice(b"short");
533  /// assert!(bytes.try_make_inline());
534  /// assert!(bytes.is_inline());
535  /// assert_eq!(bytes.capacity(), INLINE_CAP);
536  /// ```
537  pub fn try_make_inline(&mut self) -> bool {
538    let inline = match &self.0 {
539      Repr::Inline(_) => return true,
540      Repr::Heap(bytes) if bytes.len() > INLINE_CAP => return false,
541      Repr::Heap(bytes) => {
542        let visible: &[u8] = bytes.as_ref();
543        Buffer::try_from(visible).expect("heap view fits inline capacity")
544      }
545    };
546
547    self.0 = Repr::Inline(inline);
548    true
549  }
550
551  /// Splits the bytes into two at the given index.
552  ///
553  /// Afterwards `self` contains elements `[0, at)`, and the returned value
554  /// contains elements `[at, capacity)`. Any reserved-but-unwritten
555  /// capacity is partitioned between the two halves — this matches the
556  /// semantics of [`bytes::BytesMut::split_off`].
557  ///
558  /// For heap-allocated buffers, this is an `O(1)` operation that increases the
559  /// reference count.
560  ///
561  /// For inline buffers where `at` lies within the written length, the tail is
562  /// copied into another inline `BytesMut`.
563  /// For inline buffers where `at > len` (splitting into uninitialized
564  /// capacity), the buffer is first promoted to heap before splitting.
565  ///
566  /// ## Examples
567  ///
568  /// Splitting within written data on an inline buffer:
569  ///
570  /// ```
571  /// use smol_bytes::BytesMut;
572  ///
573  /// let mut a = BytesMut::from(&b"hello world"[..]);
574  /// let mut b = a.split_off(5);
575  /// b[0] = b'!';
576  /// assert_eq!(&b[..], b"!world");
577  /// assert_eq!(&a[..], b"hello");
578  /// ```
579  ///
580  /// Splitting into uninitialized capacity on a heap buffer:
581  ///
582  /// ```
583  /// use smol_bytes::BytesMut;
584  ///
585  /// let mut a = BytesMut::with_capacity(1024);
586  /// let b = a.split_off(128);
587  /// assert_eq!(a.len(), 0);
588  /// assert_eq!(a.capacity(), 128);
589  /// assert_eq!(b.len(), 0);
590  /// assert_eq!(b.capacity(), 896);
591  /// ```
592  ///
593  /// ## Panics
594  ///
595  /// Panics if `at > capacity`.
596  #[must_use = "consider BytesMut::truncate if you don't need the other half"]
597  pub fn split_off(&mut self, at: usize) -> Self {
598    self
599      .try_split_off(at)
600      .unwrap_or_else(|_| panic!("split_off out of bounds: {} > {}", at, self.capacity()))
601  }
602
603  /// Attempts to split the buffer at `at`.
604  ///
605  /// Returns [`OutOfBounds`] instead of panicking when `at > capacity`.
606  ///
607  /// See also [`split_off`](Self::split_off).
608  pub fn try_split_off(&mut self, at: usize) -> Result<Self, OutOfBounds> {
609    let cap = self.capacity();
610    if at > cap {
611      return Err(OutOfBounds::new(at, cap));
612    }
613
614    // For inline buffers where `at` exceeds the written length, the `Buffer`
615    // type has no way to represent "reserved but unwritten" capacity, so we
616    // promote to heap before splitting.
617    if let Repr::Inline(b) = &self.0
618      && at > b.remaining()
619    {
620      let mut new_heap = bytes::BytesMut::with_capacity(cap);
621      new_heap.extend_from_slice(b.as_slice());
622      self.0 = Repr::Heap(new_heap);
623    }
624
625    let result = match &mut self.0 {
626      Repr::Inline(b) => Self::from_inline(b.try_split_off(at).expect("validated bounds")),
627      Repr::Heap(b) => Self(Repr::Heap(b.split_off(at))),
628    };
629    Ok(result)
630  }
631
632  /// Removes the bytes from the current view, returning them in a new buffer.
633  ///
634  /// Afterwards, `self` will be empty, but will retain any additional
635  /// capacity that it had before the operation. This is identical to
636  /// `self.split_to(self.len())`.
637  ///
638  /// For heap buffers, this is an `O(1)` operation.
639  /// For inline buffers, the data is copied into a `Buffer`.
640  ///
641  /// ## Examples
642  ///
643  /// ```
644  /// use smol_bytes::{BytesMut, BufMut};
645  ///
646  /// let mut buf = BytesMut::with_capacity(1024);
647  /// buf.put(&b"hello world"[..]);
648  /// let other = buf.split();
649  /// assert!(buf.is_empty());
650  /// assert_eq!(other, b"hello world"[..]);
651  /// ```
652  #[must_use = "consider BytesMut::clear if you don't need the other half"]
653  pub fn split(&mut self) -> Self {
654    let len = self.len();
655    self.split_to(len)
656  }
657
658  /// Splits the buffer into two at the given index.
659  ///
660  /// Afterwards `self` contains elements `[at, len)`, and the returned value
661  /// contains elements `[0, at)`.
662  ///
663  /// For heap-allocated buffers, this is an `O(1)` operation that increases the
664  /// reference count. For inline buffers, the head is copied into another
665  /// inline `BytesMut`.
666  ///
667  /// ## Examples
668  ///
669  /// ```
670  /// use smol_bytes::BytesMut;
671  ///
672  /// // Inline buffer
673  /// let mut a = BytesMut::from(&b"hello world"[..]);
674  /// let mut b = a.split_to(5);
675  /// b[0] = b'j';
676  /// assert_eq!(&b[..], b"jello");
677  /// assert_eq!(&a[..], b" world");
678  ///
679  /// // Heap buffer
680  /// let mut a = BytesMut::with_capacity(64);
681  /// a.extend_from_slice(b"hello world");
682  /// let mut b = a.split_to(5);
683  /// a[0] = b'!';  // Replaces the space with '!'
684  /// b[0] = b'j';
685  /// assert_eq!(&a[..], b"!world");
686  /// assert_eq!(&b[..], b"jello");
687  /// ```
688  ///
689  /// ## Panics
690  ///
691  /// Panics if `at > len`.
692  #[must_use = "consider BytesMut::advance if you don't need the other half"]
693  pub fn split_to(&mut self, at: usize) -> Self {
694    self
695      .try_split_to(at)
696      .unwrap_or_else(|_| panic!("split_to out of bounds: {} > {}", at, self.len()))
697  }
698
699  /// Attempts to split at `at`, returning [`OutOfBounds`] on failure instead of panicking.
700  ///
701  /// See also [`split_to`](Self::split_to).
702  pub fn try_split_to(&mut self, at: usize) -> Result<Self, OutOfBounds> {
703    let len = self.len();
704    if at > len {
705      return Err(OutOfBounds::new(at, len));
706    }
707
708    let result = match &mut self.0 {
709      Repr::Inline(b) => Self::from_inline(b.try_split_to(at).expect("validated bounds")),
710      Repr::Heap(b) => Self(Repr::Heap(b.split_to(at))),
711    };
712    Ok(result)
713  }
714
715  /// Attempts to advance the readable cursor by `cnt` bytes.
716  pub fn try_advance(&mut self, cnt: usize) -> Result<(), OutOfBounds> {
717    let len = self.len();
718    if cnt > len {
719      return Err(OutOfBounds::new(cnt, len));
720    }
721
722    match &mut self.0 {
723      Repr::Inline(buffer) => buffer.try_advance(cnt),
724      Repr::Heap(bytes) => {
725        Buf::advance(bytes, cnt);
726        Ok(())
727      }
728    }
729  }
730
731  /// Attempts to write an unsigned n-byte integer in big-endian byte order.
732  pub fn try_put_uint(&mut self, n: u64, nbytes: usize) -> Result<(), InvalidIntegerLength> {
733    if nbytes > 8 {
734      return Err(InvalidIntegerLength(nbytes));
735    }
736
737    self.put_uint(n, nbytes);
738    Ok(())
739  }
740
741  /// Attempts to write an unsigned n-byte integer in little-endian byte order.
742  pub fn try_put_uint_le(&mut self, n: u64, nbytes: usize) -> Result<(), InvalidIntegerLength> {
743    if nbytes > 8 {
744      return Err(InvalidIntegerLength(nbytes));
745    }
746    self.put_uint_le(n, nbytes);
747    Ok(())
748  }
749
750  /// Attempts to write a signed n-byte integer in big-endian byte order.
751  pub fn try_put_int(&mut self, n: i64, nbytes: usize) -> Result<(), InvalidIntegerLength> {
752    if nbytes > 8 {
753      return Err(InvalidIntegerLength(nbytes));
754    }
755    self.put_int(n, nbytes);
756    Ok(())
757  }
758
759  /// Attempts to write a signed n-byte integer in little-endian byte order.
760  pub fn try_put_int_le(&mut self, n: i64, nbytes: usize) -> Result<(), InvalidIntegerLength> {
761    if nbytes > 8 {
762      return Err(InvalidIntegerLength(nbytes));
763    }
764    self.put_int_le(n, nbytes);
765    Ok(())
766  }
767
768  /// Attempts to write an unsigned n-byte integer in native-endian byte order
769  pub fn try_put_uint_ne(&mut self, n: u64, nbytes: usize) -> Result<(), InvalidIntegerLength> {
770    if nbytes > 8 {
771      return Err(InvalidIntegerLength(nbytes));
772    }
773    self.put_uint_ne(n, nbytes);
774    Ok(())
775  }
776
777  /// Attempts to write a signed n-byte integer in native-endian byte order
778  pub fn try_put_int_ne(&mut self, n: i64, nbytes: usize) -> Result<(), InvalidIntegerLength> {
779    if nbytes > 8 {
780      return Err(InvalidIntegerLength(nbytes));
781    }
782    self.put_int_ne(n, nbytes);
783    Ok(())
784  }
785
786  /// Tries to write an unsigned integer only when it fits exactly in `nbytes`
787  /// bytes in big-endian byte order.
788  ///
789  /// Growable buffers reserve storage as needed; this error reports only an
790  /// invalid width or an unrepresentable value.
791  pub fn try_put_uint_checked(
792    &mut self,
793    n: u64,
794    nbytes: usize,
795  ) -> Result<(), TryPutIntegerCheckedError> {
796    checked_unsigned_range(n, nbytes)?;
797    self.put_uint(n, nbytes);
798    Ok(())
799  }
800
801  /// Tries to write an unsigned integer only when it fits exactly in `nbytes`
802  /// bytes in little-endian byte order.
803  ///
804  /// Growable buffers reserve storage as needed; this error reports only an
805  /// invalid width or an unrepresentable value.
806  pub fn try_put_uint_checked_le(
807    &mut self,
808    n: u64,
809    nbytes: usize,
810  ) -> Result<(), TryPutIntegerCheckedError> {
811    checked_unsigned_range(n, nbytes)?;
812    self.put_uint_le(n, nbytes);
813    Ok(())
814  }
815
816  /// Tries to write an unsigned integer only when it fits exactly in `nbytes`
817  /// bytes in native-endian byte order.
818  pub fn try_put_uint_checked_ne(
819    &mut self,
820    n: u64,
821    nbytes: usize,
822  ) -> Result<(), TryPutIntegerCheckedError> {
823    if cfg!(target_endian = "big") {
824      self.try_put_uint_checked(n, nbytes)
825    } else {
826      self.try_put_uint_checked_le(n, nbytes)
827    }
828  }
829
830  /// Tries to write a signed integer only when it fits exactly in `nbytes`
831  /// bytes in big-endian byte order.
832  ///
833  /// Growable buffers reserve storage as needed; this error reports only an
834  /// invalid width or an unrepresentable value.
835  pub fn try_put_int_checked(
836    &mut self,
837    n: i64,
838    nbytes: usize,
839  ) -> Result<(), TryPutIntegerCheckedError> {
840    checked_signed_range(n, nbytes)?;
841    self.put_int(n, nbytes);
842    Ok(())
843  }
844
845  /// Tries to write a signed integer only when it fits exactly in `nbytes`
846  /// bytes in little-endian byte order.
847  ///
848  /// Growable buffers reserve storage as needed; this error reports only an
849  /// invalid width or an unrepresentable value.
850  pub fn try_put_int_checked_le(
851    &mut self,
852    n: i64,
853    nbytes: usize,
854  ) -> Result<(), TryPutIntegerCheckedError> {
855    checked_signed_range(n, nbytes)?;
856    self.put_int_le(n, nbytes);
857    Ok(())
858  }
859
860  /// Tries to write a signed integer only when it fits exactly in `nbytes`
861  /// bytes in native-endian byte order.
862  pub fn try_put_int_checked_ne(
863    &mut self,
864    n: i64,
865    nbytes: usize,
866  ) -> Result<(), TryPutIntegerCheckedError> {
867    if cfg!(target_endian = "big") {
868      self.try_put_int_checked(n, nbytes)
869    } else {
870      self.try_put_int_checked_le(n, nbytes)
871    }
872  }
873
874  /// Absorbs a `BytesMut` that was previously split off.
875  ///
876  /// If the two heap-backed `BytesMut` objects were previously contiguous and not mutated
877  /// in a way that causes re-allocation i.e., if `other` was created by
878  /// calling `split_off` on this `BytesMut`, then this is an `O(1)` operation
879  /// that just decreases a reference count and sets a few indices.
880  /// Otherwise this method degenerates to
881  /// `self.extend_from_slice(other.as_ref())`.
882  ///
883  /// ## Examples
884  ///
885  /// ```
886  /// use smol_bytes::BytesMut;
887  ///
888  /// let mut buf = BytesMut::with_capacity(64);
889  /// buf.extend_from_slice(b"aaabbbcccddd");
890  ///
891  /// let split = buf.split_off(6);
892  /// assert_eq!(b"aaabbb", &buf[..]);
893  /// assert_eq!(b"cccddd", &split[..]);
894  ///
895  /// buf.unsplit(split);
896  /// assert_eq!(b"aaabbbcccddd", &buf[..]);
897  /// ```
898  pub fn unsplit(&mut self, other: Self) {
899    if self.is_empty() {
900      *self = other;
901      return;
902    }
903
904    match (&mut self.0, other.0) {
905      (Repr::Heap(b1), Repr::Heap(b2)) => {
906        b1.unsplit(b2);
907      }
908      (_, Repr::Inline(storage)) => self.extend_from_slice(storage.as_slice()),
909      (_, Repr::Heap(bytes_mut)) => self.extend_from_slice(bytes_mut.as_ref()),
910    }
911  }
912
913  #[inline]
914  pub(crate) fn freeze_with<S>(self) -> RawBytes<S>
915  where
916    RawBytes<S>: crate::strategy::ImmutableStorage,
917  {
918    match self.0 {
919      Repr::Inline(storage) => RawBytes::inline(storage),
920      Repr::Heap(b) => RawBytes::heap(b.freeze()),
921    }
922  }
923
924  /// Converts this mutable buffer into the default shared immutable [`Bytes`](crate::Bytes).
925  ///
926  /// Heap-backed values retain their allocation. [`freeze_compact`](Self::freeze_compact)
927  /// also transfers existing heap storage without copying, including a short current view;
928  /// its compact strategy applies to later shortening or view operations.
929  ///
930  /// ```
931  /// use smol_bytes::BytesMut;
932  ///
933  /// let bytes = BytesMut::from(&b"hello"[..]).freeze();
934  /// assert_eq!(bytes, b"hello"[..]);
935  /// ```
936  pub fn freeze(self) -> crate::Bytes {
937    self.freeze_with()
938  }
939
940  /// Converts `self` into an immutable [`shared::Bytes`](crate::shared::Bytes).
941  ///
942  /// The conversion is zero cost and is used to indicate that the slice
943  /// referenced by the handle will no longer be mutated. Once the conversion
944  /// is done, the handle can be cloned and shared across threads.
945  ///
946  /// ## Examples
947  ///
948  /// ```
949  /// use smol_bytes::{BytesMut, BufMut};
950  /// use std::thread;
951  ///
952  /// let mut b = BytesMut::with_capacity(64);
953  /// b.put(&b"hello world"[..]);
954  /// let b1 = b.freeze_shared();
955  /// let b2 = b1.clone();
956  ///
957  /// let th = thread::spawn(move || {
958  ///     assert_eq!(&b1[..], b"hello world");
959  /// });
960  ///
961  /// assert_eq!(&b2[..], b"hello world");
962  /// th.join().unwrap();
963  /// ```
964  pub fn freeze_shared(self) -> crate::shared::Bytes {
965    self.freeze_with()
966  }
967
968  /// Converts `self` into an immutable [`compact::Bytes`](crate::compact::Bytes).
969  ///
970  /// The conversion is zero cost and is used to indicate that the slice
971  /// referenced by the handle will no longer be mutated. Once the conversion
972  /// is done, the handle can be cloned and shared across threads.
973  ///
974  /// Existing heap storage is transferred without copying. In particular, a
975  /// short heap view is not immediately canonicalized; the compact strategy
976  /// applies to subsequent shortening or view operations.
977  ///
978  /// ## Examples
979  ///
980  /// ```
981  /// use smol_bytes::{BytesMut, BufMut};
982  /// use std::thread;
983  ///
984  /// let mut b = BytesMut::with_capacity(64);
985  /// b.put(&b"hello world"[..]);
986  /// let b1 = b.freeze_compact();
987  /// let b2 = b1.clone();
988  ///
989  /// let th = thread::spawn(move || {
990  ///     assert_eq!(&b1[..], b"hello world");
991  /// });
992  ///
993  /// assert_eq!(&b2[..], b"hello world");
994  /// th.join().unwrap();
995  /// ```
996  pub fn freeze_compact(self) -> crate::compact::Bytes {
997    self.freeze_with()
998  }
999
1000  /// Returns the remaining spare capacity of the buffer as a slice of [`MaybeUninit<u8>`].
1001  ///
1002  /// The returned slice can be used to fill the buffer with data (e.g. by reading from a file) before marking the data as initialized using the [`set_len`](Self::set_len) method.
1003  ///
1004  /// ## Example
1005  ///
1006  /// ```
1007  /// use smol_bytes::{BytesMut, INLINE_CAP};
1008  ///
1009  /// // Allocate buffer big enough for 10 bytes.
1010  /// let mut buf = BytesMut::with_capacity(10);
1011  ///
1012  /// // Fill in the first 3 elements.
1013  /// let uninit = buf.spare_capacity_mut();
1014  /// uninit[0].write(0);
1015  /// uninit[1].write(1);
1016  /// uninit[2].write(2);
1017  ///
1018  /// // Mark the first 3 bytes of the buffer as being initialized.
1019  /// unsafe {
1020  ///   buf.set_len(3);
1021  /// }
1022  ///
1023  /// assert_eq!(&buf[..], &[0, 1, 2]);
1024  /// ```
1025  pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<u8>] {
1026    match &mut self.0 {
1027      Repr::Inline(b) => b.spare_capacity_mut(),
1028      Repr::Heap(b) => b.spare_capacity_mut(),
1029    }
1030  }
1031
1032  /// Attempts to cheaply reclaim already allocated capacity for at least `additional` more
1033  /// bytes to be inserted into the given `BytesMut` and returns `true` if it succeeded.
1034  ///
1035  /// `try_reclaim` behaves exactly like `reserve`, except that it never allocates new storage
1036  /// and returns a `bool` indicating whether it was successful in doing so:
1037  ///
1038  /// `try_reclaim` returns false under these conditions:
1039  ///  - The spare capacity left is less than `additional` bytes AND
1040  ///  - The existing allocation cannot be reclaimed cheaply or it was less than
1041  ///    `additional` bytes in size
1042  ///
1043  /// Reclaiming the allocation cheaply is possible if the `BytesMut` has no outstanding
1044  /// references through other `BytesMut`s or `Bytes` which point to the same underlying
1045  /// storage.
1046  ///
1047  /// ## Examples
1048  ///
1049  /// ```
1050  /// use smol_bytes::BytesMut;
1051  ///
1052  /// let mut buf = BytesMut::with_capacity(64);
1053  /// assert_eq!(true, buf.try_reclaim(64));
1054  /// assert_eq!(64, buf.capacity());
1055  ///
1056  /// buf.extend_from_slice(b"abcd");
1057  /// let mut split = buf.split();
1058  /// assert_eq!(60, buf.capacity());
1059  /// assert_eq!(4, split.len());
1060  /// assert_eq!(false, split.try_reclaim(64));
1061  /// assert_eq!(false, buf.try_reclaim(64));
1062  /// // The split buffer is filled with "abcd"
1063  /// assert_eq!(false, split.try_reclaim(4));
1064  /// // buf is empty and has capacity for 60 bytes
1065  /// assert_eq!(true, buf.try_reclaim(60));
1066  ///
1067  /// drop(buf);
1068  /// assert_eq!(false, split.try_reclaim(64));
1069  ///
1070  /// split.clear();
1071  /// assert_eq!(4, split.capacity());
1072  /// assert_eq!(true, split.try_reclaim(64));
1073  /// assert_eq!(64, split.capacity());
1074  /// ```
1075  #[inline]
1076  #[must_use = "consider BytesMut::reserve if you need an infallible reservation"]
1077  pub fn try_reclaim(&mut self, additional: usize) -> bool {
1078    match &mut self.0 {
1079      Repr::Inline(b) => b.try_reclaim(additional),
1080      Repr::Heap(b) => b.try_reclaim(additional),
1081    }
1082  }
1083
1084  /// Sets the visible length of the buffer.
1085  ///
1086  /// This will explicitly set the size of the buffer without actually
1087  /// modifying the data, so it is up to the caller to ensure that the data
1088  /// has been initialized.
1089  ///
1090  /// ## Safety
1091  ///
1092  /// - `len` must not exceed [`capacity`](Self::capacity).
1093  /// - Every byte in the current view's `0..len` range must be initialized.
1094  ///
1095  /// ## Examples
1096  ///
1097  /// ```
1098  /// use smol_bytes::BytesMut;
1099  ///
1100  /// let mut b = BytesMut::from(&b"hello world"[..]);
1101  ///
1102  /// unsafe {
1103  ///     b.set_len(5);
1104  /// }
1105  ///
1106  /// assert_eq!(&b[..], b"hello");
1107  ///
1108  /// unsafe {
1109  ///     b.set_len(11);
1110  /// }
1111  ///
1112  /// assert_eq!(&b[..], b"hello world");
1113  /// ```
1114  #[allow(clippy::missing_safety_doc)]
1115  #[inline]
1116  pub unsafe fn set_len(&mut self, len: usize) {
1117    // SAFETY: both inner methods interpret `len` as a visible length. The
1118    // caller guarantees `len <= capacity()` and that every byte newly exposed
1119    // in the current view is initialized.
1120    unsafe {
1121      match &mut self.0 {
1122        Repr::Inline(b) => b.set_len(len),
1123        Repr::Heap(b) => b.set_len(len),
1124      }
1125    }
1126  }
1127
1128  /// Resizes the buffer so that `len` is equal to `new_len`.
1129  ///
1130  /// If `new_len` is greater than `len`, the buffer is extended by the
1131  /// difference with each additional byte set to `value`. If `new_len` is
1132  /// less than `len`, the buffer is simply truncated.
1133  ///
1134  /// ## Examples
1135  ///
1136  /// ```
1137  /// use smol_bytes::BytesMut;
1138  ///
1139  /// let mut buf = BytesMut::new();
1140  ///
1141  /// buf.resize(3, 0x1);
1142  /// assert_eq!(&buf[..], &[0x1, 0x1, 0x1]);
1143  ///
1144  /// buf.resize(2, 0x2);
1145  /// assert_eq!(&buf[..], &[0x1, 0x1]);
1146  ///
1147  /// buf.resize(4, 0x3);
1148  /// assert_eq!(&buf[..], &[0x1, 0x1, 0x3, 0x3]);
1149  /// ```
1150  pub fn resize(&mut self, new_len: usize, value: u8) {
1151    let current_len = self.len();
1152    if new_len < current_len {
1153      self.truncate(new_len);
1154      return;
1155    }
1156
1157    let additional = new_len - current_len;
1158    if additional == 0 {
1159      return;
1160    }
1161
1162    self.reserve(additional);
1163    match &mut self.0 {
1164      Repr::Inline(storage) => storage.put_bytes(value, additional),
1165      Repr::Heap(b) => b.resize(new_len, value),
1166    }
1167  }
1168
1169  /// Reserves capacity for at least `additional` more bytes to be inserted
1170  /// into the given `BytesMut`.
1171  ///
1172  /// More than `additional` bytes may be reserved in order to avoid frequent
1173  /// reallocations. A call to `reserve` may result in an allocation.
1174  ///
1175  /// Before allocating new buffer space, the function will attempt to reclaim
1176  /// space in the existing buffer. If the current handle references a view
1177  /// into a larger original buffer, and all other handles referencing part
1178  /// of the same original buffer have been dropped, then the current view
1179  /// can be copied/shifted to the front of the buffer and the handle can take
1180  /// ownership of the full buffer, provided that the full buffer is large
1181  /// enough to fit the requested additional capacity.
1182  ///
1183  /// This optimization will only happen if shifting the data from the current
1184  /// view to the front of the buffer is not too expensive in terms of the
1185  /// (amortized) time required. The precise condition is subject to change;
1186  /// as of now, the length of the data being shifted needs to be at least as
1187  /// large as the distance that it's shifted by. If the current view is empty
1188  /// and the original buffer is large enough to fit the requested additional
1189  /// capacity, then reallocations will never happen.
1190  ///
1191  /// ## Examples
1192  ///
1193  /// In the following example, a new buffer is allocated.
1194  ///
1195  /// ```
1196  /// use smol_bytes::BytesMut;
1197  ///
1198  /// let mut buf = BytesMut::from(&b"hello"[..]);
1199  /// buf.reserve(64);
1200  /// assert!(buf.capacity() >= 69);
1201  /// ```
1202  ///
1203  /// ## Panics
1204  ///
1205  /// Panics if the new capacity overflows `usize`.
1206  #[inline]
1207  pub fn reserve(&mut self, additional: usize) {
1208    let required = self
1209      .len()
1210      .checked_add(additional)
1211      .expect("capacity overflow");
1212
1213    match &mut self.0 {
1214      Repr::Inline(storage) => {
1215        if storage.try_reclaim(additional) {
1216          return;
1217        }
1218
1219        let mut new_buf = bytes::BytesMut::with_capacity(required);
1220        new_buf.extend_from_slice(storage.as_slice());
1221        self.0 = Repr::Heap(new_buf);
1222      }
1223      Repr::Heap(b) => b.reserve(additional),
1224    }
1225  }
1226
1227  /// Returns the number of bytes contained in this `BytesMut`.
1228  ///
1229  /// ## Example
1230  ///
1231  /// ```rust
1232  /// use smol_bytes::BytesMut;
1233  ///
1234  /// let bytes = BytesMut::new();
1235  /// assert_eq!(bytes.len(), 0);
1236  /// ```
1237  #[cfg_attr(not(coverage), inline(always))]
1238  pub fn len(&self) -> usize {
1239    match &self.0 {
1240      Repr::Inline(b) => b.len(),
1241      Repr::Heap(b) => b.len(),
1242    }
1243  }
1244
1245  /// Returns `true` if the BytesMut has a length of `0`.
1246  ///
1247  /// ## Example
1248  ///
1249  /// ```rust
1250  /// use smol_bytes::BytesMut;
1251  ///
1252  /// let bytes = BytesMut::new();
1253  /// assert!(bytes.is_empty());
1254  /// ```
1255  #[cfg_attr(not(coverage), inline(always))]
1256  pub fn is_empty(&self) -> bool {
1257    self.len() == 0
1258  }
1259
1260  /// Returns a slice of the buffer's contents.
1261  ///
1262  /// ## Example
1263  ///
1264  /// ```rust
1265  /// use smol_bytes::BytesMut;
1266  ///
1267  /// let buf = BytesMut::from(&b"hello"[..]);
1268  /// assert_eq!(buf.as_slice(), b"hello");
1269  /// ```
1270  #[cfg_attr(not(coverage), inline(always))]
1271  pub fn as_slice(&self) -> &[u8] {
1272    self
1273  }
1274
1275  /// Returns a mutable slice of the buffer's contents.
1276  ///
1277  /// ## Example
1278  ///
1279  /// ```rust
1280  /// use smol_bytes::BytesMut;
1281  ///
1282  /// let mut buf = BytesMut::from(&b"hello"[..]);
1283  /// buf.as_mut_slice()[0] = b'j';
1284  /// assert_eq!(buf.as_slice(), b"jello");
1285  /// ```
1286  #[cfg_attr(not(coverage), inline(always))]
1287  pub fn as_mut_slice(&mut self) -> &mut [u8] {
1288    self
1289  }
1290}
1291
1292impl Buf for BytesMut {
1293  #[cfg_attr(not(coverage), inline(always))]
1294  fn remaining(&self) -> usize {
1295    match &self.0 {
1296      Repr::Inline(b) => b.remaining(),
1297      Repr::Heap(b) => b.remaining(),
1298    }
1299  }
1300
1301  #[cfg_attr(not(coverage), inline(always))]
1302  fn chunk(&self) -> &[u8] {
1303    match &self.0 {
1304      Repr::Inline(b) => b.as_slice(),
1305      Repr::Heap(b) => b.chunk(),
1306    }
1307  }
1308
1309  #[cfg_attr(not(coverage), inline(always))]
1310  fn advance(&mut self, cnt: usize) {
1311    match &mut self.0 {
1312      Repr::Inline(b) => b.advance(cnt),
1313      Repr::Heap(b) => b.advance(cnt),
1314    }
1315  }
1316
1317  #[cfg_attr(not(coverage), inline(always))]
1318  fn copy_to_bytes(&mut self, len: usize) -> bytes::Bytes {
1319    self.split_to(len).freeze_shared().into()
1320  }
1321
1322  fn get_int(&mut self, nbytes: usize) -> i64 {
1323    crate::buffer::sign_extend(::bytes::Buf::get_uint(self, nbytes), nbytes)
1324  }
1325
1326  fn get_int_le(&mut self, nbytes: usize) -> i64 {
1327    crate::buffer::sign_extend(::bytes::Buf::get_uint_le(self, nbytes), nbytes)
1328  }
1329
1330  fn get_int_ne(&mut self, nbytes: usize) -> i64 {
1331    crate::buffer::sign_extend(::bytes::Buf::get_uint_ne(self, nbytes), nbytes)
1332  }
1333
1334  fn try_get_int(&mut self, nbytes: usize) -> Result<i64, bytes::TryGetError> {
1335    ::bytes::Buf::try_get_uint(self, nbytes).map(|value| crate::buffer::sign_extend(value, nbytes))
1336  }
1337
1338  fn try_get_int_le(&mut self, nbytes: usize) -> Result<i64, bytes::TryGetError> {
1339    ::bytes::Buf::try_get_uint_le(self, nbytes)
1340      .map(|value| crate::buffer::sign_extend(value, nbytes))
1341  }
1342
1343  fn try_get_int_ne(&mut self, nbytes: usize) -> Result<i64, bytes::TryGetError> {
1344    ::bytes::Buf::try_get_uint_ne(self, nbytes)
1345      .map(|value| crate::buffer::sign_extend(value, nbytes))
1346  }
1347}
1348
1349unsafe impl BufMut for BytesMut {
1350  #[cfg_attr(not(coverage), inline(always))]
1351  fn remaining_mut(&self) -> usize {
1352    usize::MAX - self.len()
1353  }
1354
1355  unsafe fn advance_mut(&mut self, cnt: usize) {
1356    // SAFETY: forwards to the inner buffer's `advance_mut`; the caller's
1357    // safety contract applies identically to the inner representation.
1358    unsafe {
1359      match &mut self.0 {
1360        Repr::Inline(b) => b.advance_mut(cnt),
1361        Repr::Heap(b) => b.advance_mut(cnt),
1362      }
1363    }
1364  }
1365
1366  fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
1367    let promote = match &mut self.0 {
1368      Repr::Inline(buffer) if buffer.remaining_mut() == 0 => !buffer.try_reclaim(1),
1369      _ => false,
1370    };
1371
1372    if promote {
1373      self.reserve(64);
1374    }
1375
1376    match &mut self.0 {
1377      Repr::Inline(b) => b.chunk_mut(),
1378      Repr::Heap(b) => b.chunk_mut(),
1379    }
1380  }
1381
1382  fn put_slice(&mut self, src: &[u8]) {
1383    self.extend_from_slice(src);
1384  }
1385
1386  fn put_bytes(&mut self, val: u8, cnt: usize) {
1387    self.reserve(cnt);
1388
1389    match &mut self.0 {
1390      Repr::Inline(b) => b.put_bytes(val, cnt),
1391      Repr::Heap(b) => b.put_bytes(val, cnt),
1392    }
1393  }
1394}
1395
1396#[derive(Clone)]
1397enum Repr {
1398  Inline(Buffer),
1399  Heap(bytes::BytesMut),
1400}