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