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}