Skip to main content

smol_bytes/
buffer.rs

1#[cfg(any(feature = "alloc", feature = "std"))]
2use core::borrow::Borrow;
3
4use core::{
5  mem::{MaybeUninit, transmute},
6  ops::RangeBounds,
7  ptr::{copy_nonoverlapping, write_bytes},
8  slice::from_raw_parts_mut,
9};
10
11use super::error::*;
12use crate::utf8_edit::{RawUtf8Storage, replace_bytes};
13
14mod cmp;
15mod fmt;
16mod from;
17mod io;
18mod iter;
19mod ops;
20
21#[cfg(any(feature = "alloc", feature = "std"))]
22pub(crate) use io::sign_extend;
23#[cfg(any(feature = "alloc", feature = "std"))]
24pub(crate) use io::{checked_signed_range, checked_unsigned_range};
25
26#[cfg(feature = "arbitrary")]
27mod arbitrary;
28#[cfg(feature = "borsh")]
29mod borsh;
30#[cfg(all(feature = "quickcheck", any(feature = "std", feature = "alloc")))]
31mod quickcheck;
32#[cfg(feature = "serde")]
33mod serde;
34
35#[cfg(feature = "pyo3")]
36mod python;
37
38#[cfg(feature = "wasm")]
39mod wasm;
40
41/// Number of bytes that can be stored inline.
42pub const INLINE_CAP: usize = InlineSize::MAX as usize;
43
44/// A type used internally to encode inline lengths.
45#[derive(Clone, Copy, Debug, PartialEq, Eq)]
46#[repr(u8)]
47pub(crate) enum InlineSize {
48  _V0 = 0,
49  _V1,
50  _V2,
51  _V3,
52  _V4,
53  _V5,
54  _V6,
55  _V7,
56  _V8,
57  _V9,
58  _V10,
59  _V11,
60  _V12,
61  _V13,
62  _V14,
63  _V15,
64  _V16,
65  _V17,
66  _V18,
67  _V19,
68  _V20,
69  _V21,
70  _V22,
71  _V23,
72  _V24,
73  _V25,
74  _V26,
75  _V27,
76  _V28,
77  _V29,
78  _V30,
79  _V31,
80  _V32,
81  _V33,
82  _V34,
83  _V35,
84  _V36,
85  _V37,
86  _V38,
87  _V39,
88  _V40,
89  _V41,
90  _V42,
91  _V43,
92  _V44,
93  _V45,
94  _V46,
95  _V47,
96  _V48,
97  _V49,
98  _V50,
99  _V51,
100  _V52,
101  _V53,
102  _V54,
103  _V55,
104  _V56,
105  _V57,
106  _V58,
107  _V59,
108  _V60,
109  _V61,
110  _V62,
111}
112
113impl InlineSize {
114  const MAX: u8 = InlineSize::_V62 as u8;
115
116  /// ## Safety
117  ///
118  /// `value` must be less than or equal to [`INLINE_CAP`].
119  #[cfg_attr(not(coverage), inline(always))]
120  pub(crate) const unsafe fn from_u8(value: u8) -> Self {
121    debug_assert!(value <= InlineSize::MAX);
122    // SAFETY: caller guarantees `value <= INLINE_CAP == InlineSize::MAX`,
123    // and every such value is a valid discriminant.
124    unsafe { transmute::<u8, InlineSize>(value) }
125  }
126
127  #[cfg_attr(not(coverage), inline(always))]
128  pub(crate) const fn to_u8(self) -> u8 {
129    self as u8
130  }
131
132  #[cfg_attr(not(coverage), inline(always))]
133  pub(crate) const fn to_usize(self) -> usize {
134    self as usize
135  }
136}
137
138#[doc = "A fixed-size buffer for inline storage."]
139#[doc = ""]
140#[doc = "This type can hold at most `62` bytes on stack without heap allocation."]
141#[cfg_attr(feature = "wasm", doc = "")]
142#[cfg_attr(feature = "wasm", doc = "@example")]
143#[cfg_attr(feature = "wasm", doc = "```typescript")]
144#[cfg_attr(feature = "wasm", doc = "import { Buffer } from 'smol-bytes';")]
145#[cfg_attr(
146  feature = "wasm",
147  doc = "const buf = Buffer.fromBytes(new Uint8Array([1, 2, 3]));"
148)]
149#[cfg_attr(feature = "wasm", doc = "console.log(buf.len()); // 3")]
150#[cfg_attr(feature = "wasm", doc = "```")]
151#[derive(Clone, Copy)]
152#[cfg_attr(feature = "pyo3", ::pyo3::prelude::pyclass)]
153#[cfg_attr(feature = "wasm", wasm_bindgen::prelude::wasm_bindgen)]
154pub struct Buffer {
155  // Invariant: 0 <= cur <= end <= INLINE_CAP, and buf[0..end] is initialized.
156  // The absolute write cursor. Public lengths are always `end - cur`.
157  end: InlineSize,
158  // The read cursor
159  cur: InlineSize,
160  buf: [MaybeUninit<u8>; INLINE_CAP],
161}
162
163impl Default for Buffer {
164  #[cfg_attr(not(coverage), inline(always))]
165  fn default() -> Self {
166    Self::new()
167  }
168}
169
170impl Buffer {
171  /// Creates a new, empty `Buffer`.
172  ///
173  /// ## Examples
174  ///
175  /// ```
176  /// use smol_bytes::Buffer;
177  ///
178  /// let buf = Buffer::new();
179  /// ```
180  #[cfg_attr(not(coverage), inline(always))]
181  pub const fn new() -> Self {
182    Self {
183      end: InlineSize::_V0,
184      cur: InlineSize::_V0,
185      buf: [const { MaybeUninit::uninit() }; INLINE_CAP],
186    }
187  }
188
189  /// Creates a new `Buffer` with the specified length, filled with zeroes.
190  ///
191  /// ## Safety
192  /// - `len` must be less than or equal to [`INLINE_CAP`].
193  #[cfg(any(feature = "alloc", feature = "std"))]
194  #[cfg_attr(not(coverage), inline(always))]
195  pub(crate) const unsafe fn zeroed(len: usize) -> Self {
196    let mut storage = [const { MaybeUninit::uninit() }; INLINE_CAP];
197    // SAFETY: caller guarantees `len <= INLINE_CAP`, so writing `len`
198    // zero bytes stays within the storage array.
199    unsafe {
200      core::ptr::write_bytes(storage.as_mut_ptr(), 0, len);
201    }
202    Self {
203      cur: InlineSize::_V0,
204      // SAFETY: len is guaranteed to be less than or equal to INLINE_CAP
205      end: unsafe { InlineSize::from_u8(len as u8) },
206      buf: storage,
207    }
208  }
209
210  /// Creates a new `Buffer` from the given array and length.
211  ///
212  /// ## Safety
213  /// - `len` must be less than or equal to [`INLINE_CAP`].
214  #[cfg_attr(not(coverage), inline(always))]
215  #[allow(unused)]
216  pub(crate) const unsafe fn from_array(buf: [u8; INLINE_CAP], len: usize) -> Self {
217    Self {
218      cur: InlineSize::_V0,
219      // SAFETY: len is guaranteed to be less than or equal to INLINE_CAP
220      end: unsafe { InlineSize::from_u8(len as u8) },
221      // SAFETY: all bytes are initialized
222      buf: unsafe { transmute::<[u8; INLINE_CAP], [MaybeUninit<u8>; INLINE_CAP]>(buf) },
223    }
224  }
225
226  /// Creates a new `Buffer` by copying from the given slice.
227  ///
228  /// ## Safety
229  /// - the length of `src` must be less than or equal to [`INLINE_CAP`].
230  #[cfg_attr(not(coverage), inline(always))]
231  pub const unsafe fn copy_from_slice(src: &[u8]) -> Self {
232    let len = src.len();
233    let mut storage = [const { MaybeUninit::uninit() }; INLINE_CAP];
234
235    // SAFETY: caller guarantees `len <= INLINE_CAP`, matching the size
236    // of `storage`; `src` and `storage` do not overlap.
237    unsafe {
238      copy_nonoverlapping(src.as_ptr(), storage.as_mut_ptr() as _, len);
239    }
240
241    Self {
242      // SAFETY: caller guarantees that `len` is less than or equal to `INLINE_CAP`.
243      end: unsafe { InlineSize::from_u8(len as u8) },
244      cur: InlineSize::_V0,
245      buf: storage,
246    }
247  }
248
249  /// Returns the number of bytes between the current position and the end of
250  /// the buffer.
251  ///
252  /// This value is equal to the length of the slice returned
253  /// by [`as_slice()`](Self::as_slice).
254  ///
255  /// # Examples
256  ///
257  /// ```
258  /// use smol_bytes::Buffer;
259  ///
260  /// let mut buf = Buffer::try_from(*b"hello world").unwrap();
261  ///
262  /// assert_eq!(buf.remaining(), 11);
263  ///
264  /// buf.get_u8();
265  ///
266  /// assert_eq!(buf.remaining(), 10);
267  /// ```
268  ///
269  /// # Implementer notes
270  ///
271  /// Implementations of `remaining` should ensure that the return value does
272  /// not change unless a call is made to `advance` or any other function that
273  /// is documented to change the `Buf`'s current position.
274  #[cfg_attr(not(coverage), inline(always))]
275  pub const fn remaining(&self) -> usize {
276    self.end.to_usize() - self.cur.to_usize()
277  }
278
279  /// Returns the number of visible bytes contained in this `Buffer`.
280  ///
281  /// ## Example
282  ///
283  /// ```rust
284  /// use smol_bytes::Buffer;
285  ///
286  /// let bytes = Buffer::new();
287  /// assert_eq!(bytes.len(), 0);
288  /// ```
289  #[cfg_attr(not(coverage), inline(always))]
290  pub const fn len(&self) -> usize {
291    self.remaining()
292  }
293
294  /// Returns `true` if the `Buffer` has no visible bytes.
295  ///
296  /// ## Example
297  ///
298  /// ```rust
299  /// use smol_bytes::BytesMut;
300  ///
301  /// let bytes = BytesMut::new();
302  /// assert!(bytes.is_empty());
303  /// ```
304  #[cfg_attr(not(coverage), inline(always))]
305  pub const fn is_empty(&self) -> bool {
306    self.len() == 0
307  }
308
309  /// Returns the number of bytes that can be written from the current
310  /// position until the end of the buffer is reached.
311  ///
312  /// This value is equal to the length of the slice returned
313  /// by `chunk_mut()`.
314  ///
315  /// ## Examples
316  ///
317  /// ```
318  /// use smol_bytes::{Buffer, BufMut};
319  ///
320  /// let mut dst = Buffer::new();
321  ///
322  /// let original_remaining = dst.remaining_mut();
323  /// dst.put(&b"hello"[..]);
324  ///
325  /// assert_eq!(original_remaining - 5, dst.remaining_mut());
326  /// ```
327  #[cfg_attr(not(coverage), inline(always))]
328  pub const fn remaining_mut(&self) -> usize {
329    INLINE_CAP - self.end.to_usize()
330  }
331
332  /// Reclaims consumed prefix space when doing so provides `additional`
333  /// bytes of writable tail without allocating.
334  ///
335  /// Returns `false` without changing the buffer when `additional` cannot
336  /// fit after reclaiming the consumed prefix.
337  ///
338  /// # Examples
339  ///
340  /// ```
341  /// use smol_bytes::{Buffer, INLINE_CAP};
342  ///
343  /// let mut buffer = Buffer::from(*b"abcd");
344  /// buffer.advance(2);
345  /// assert!(!buffer.try_reclaim(usize::MAX));
346  /// assert_eq!(buffer.as_slice(), b"cd");
347  /// assert_eq!(buffer.capacity(), INLINE_CAP - 2);
348  /// assert!(buffer.try_reclaim(60));
349  /// assert_eq!(buffer.as_slice(), b"cd");
350  /// assert_eq!(buffer.capacity(), INLINE_CAP);
351  /// ```
352  #[cfg_attr(not(coverage), inline(always))]
353  pub fn try_reclaim(&mut self, additional: usize) -> bool {
354    if additional <= self.remaining_mut() {
355      return true;
356    }
357
358    let len = self.len();
359    if additional > INLINE_CAP - len {
360      return false;
361    }
362
363    let cur = self.cur.to_usize();
364    if cur != 0 {
365      // `copy_within` is overlap-safe; the invariant keeps `cur..end` within
366      // the initialized prefix and its length is exactly `len`.
367      self.buf.copy_within(cur..self.end.to_usize(), 0);
368    }
369
370    self.cur = InlineSize::_V0;
371    // SAFETY: `len <= INLINE_CAP`, so it is a valid `InlineSize`; the copy
372    // above established that `buf[..len]` is initialized.
373    self.end = unsafe { InlineSize::from_u8(len as u8) };
374    true
375  }
376
377  /// Sets the visible length of the buffer.
378  ///
379  /// This will explicitly set the size of the buffer without actually
380  /// modifying the data, so it is up to the caller to ensure that the data
381  /// has been initialized.
382  ///
383  /// ## Safety
384  ///
385  /// - `len` must not exceed [`capacity`](Self::capacity).
386  /// - Every byte in the current view's `0..len` range must be initialized.
387  ///
388  /// ## Examples
389  ///
390  /// ```
391  /// use smol_bytes::Buffer;
392  ///
393  /// let mut b = Buffer::try_from(&b"hello world"[..]).unwrap();
394  ///
395  /// unsafe {
396  ///     b.set_len(5);
397  /// }
398  ///
399  /// assert_eq!(&b[..], b"hello");
400  ///
401  /// unsafe {
402  ///     b.set_len(11);
403  /// }
404  ///
405  /// assert_eq!(&b[..], b"hello world");
406  /// ```
407  #[allow(clippy::missing_safety_doc)]
408  #[cfg_attr(not(coverage), inline(always))]
409  pub const unsafe fn set_len(&mut self, len: usize) {
410    debug_assert!(len <= self.capacity(), "set_len out of bounds");
411    let end = self.cur.to_usize() + len;
412    // SAFETY: the caller guarantees `len <= self.capacity()`, so
413    // `cur + len <= INLINE_CAP` and is a valid `InlineSize` discriminant.
414    self.end = unsafe { InlineSize::from_u8(end as u8) };
415  }
416
417  /// Advance the internal cursor of the `Buffer`
418  ///
419  /// The next call to `as_slice()` will return a slice starting `cnt` bytes
420  /// further into the underlying buffer.
421  ///
422  /// ## Examples
423  ///
424  /// ```
425  /// use smol_bytes::{Buffer, INLINE_CAP};
426  ///
427  /// let mut buf = Buffer::try_from(&b"hello world"[..]).unwrap();
428  ///
429  /// assert_eq!(buf.as_slice(), &b"hello world"[..]);
430  ///
431  /// buf.advance(6);
432  ///
433  /// assert_eq!(buf.as_slice(), &b"world"[..]);
434  ///
435  /// // advancing will also reduce capacity
436  /// assert_eq!(buf.capacity(), INLINE_CAP - 6);
437  /// ```
438  ///
439  /// ## Panics
440  ///
441  /// This function panics if `cnt > self.remaining()`.
442  #[cfg_attr(not(coverage), inline(always))]
443  pub fn advance(&mut self, requested: usize) {
444    if let Err(err) = self.try_advance(requested) {
445      panic_advance(err.available, err.requested)
446    }
447  }
448
449  /// Tries to advance the internal cursor of the `Buffer`.
450  ///
451  /// Returns `Err(OutOfBounds)` if `requested` exceeds the remaining length.
452  #[cfg_attr(not(coverage), inline(always))]
453  pub fn try_advance(&mut self, requested: usize) -> Result<(), OutOfBounds> {
454    if requested == 0 {
455      return Ok(());
456    }
457
458    let available = self.remaining();
459    if available < requested {
460      return Err(OutOfBounds::new(requested, available));
461    }
462    // SAFETY: `requested <= remaining == end - cur`, so the new cursor is
463    // at most `end` and therefore at most `INLINE_CAP`.
464    self.cur = unsafe { InlineSize::from_u8(self.cur.to_u8() + requested as u8) };
465    Ok(())
466  }
467
468  /// Advance the internal write cursor of the `Buffer`
469  ///
470  /// The next call to [`spare_capacity_mut`](Self::spare_capacity_mut) will return a slice starting `cnt` bytes
471  /// further into the underlying buffer.
472  ///
473  /// ## Safety
474  ///
475  /// The caller must ensure that the next `cnt` bytes of `chunk` are
476  /// initialized.
477  ///
478  /// ## Examples
479  ///
480  /// ```
481  /// use smol_bytes::Buffer;
482  ///
483  /// let mut buf = Buffer::new();
484  ///
485  /// // Write some data
486  /// unsafe {
487  ///   let tmp = buf.spare_capacity_mut();
488  ///   core::ptr::copy(b"he".as_ptr(), tmp.as_mut_ptr() as _, 2);
489  ///   buf.advance_mut(2);
490  /// }
491  ///
492  /// // write more bytes
493  /// unsafe {
494  ///   let tmp = buf.spare_capacity_mut();
495  ///   core::ptr::copy(b"llo".as_ptr(), tmp.as_mut_ptr() as _, 3);
496  ///   buf.advance_mut(3);
497  /// }
498  ///
499  /// assert_eq!(5, buf.len());
500  /// assert_eq!(buf, "hello".as_bytes());
501  /// ```
502  ///
503  /// ## Panics
504  ///
505  /// This function panic if `requested > self.remaining_mut()`.
506  pub unsafe fn advance_mut(&mut self, requested: usize) {
507    let available = self.remaining_mut();
508    if requested > available {
509      panic_advance(available, requested)
510    }
511
512    // SAFETY: `requested <= remaining_mut == INLINE_CAP - end`, so the new
513    // absolute end is a valid `InlineSize` and the caller initialized the
514    // bytes being exposed, as required by `advance_mut`.
515    self.end = unsafe { InlineSize::from_u8(self.end.to_u8() + requested as u8) };
516  }
517
518  /// Shortens the buffer, keeping the first len bytes and dropping the rest.
519  ///
520  /// If len is greater than the buffer’s current length, this has no effect.
521  ///
522  /// Existing underlying capacity is preserved.
523  ///
524  /// ## Example
525  ///
526  /// ```rust
527  /// use smol_bytes::Buffer;
528  ///
529  /// let mut bytes = Buffer::try_from(&b"hello world"[..]).unwrap();
530  ///
531  /// bytes.truncate(5);
532  /// assert_eq!(bytes.as_mut_slice(), b"hello");
533  /// ```
534  #[cfg_attr(not(coverage), inline(always))]
535  pub const fn truncate(&mut self, new_len: usize) {
536    if new_len >= self.len() {
537      return;
538    }
539
540    let new_end = self.cur.to_usize() + new_len;
541    // SAFETY: `new_len < self.len() == end - cur`, so `new_end < end` and
542    // remains a valid `InlineSize`. No bytes are moved or newly exposed.
543    self.end = unsafe { InlineSize::from_u8(new_end as u8) };
544  }
545
546  /// Splits the buffer into two at the given index.
547  ///
548  /// Afterwards `self` contains elements `[0, at)`, and the returned `Buffer`
549  /// contains elements `[at, len)`.
550  ///
551  /// This operation copies the tail into a new `Buffer`.
552  ///
553  /// ## Example
554  ///
555  /// ```rust
556  /// use smol_bytes::Buffer;
557  ///
558  /// let mut a = Buffer::try_from(&b"hello world"[..]).unwrap();
559  /// let b = a.split_off(5);
560  /// assert_eq!(a.as_slice(), b"hello");
561  /// assert_eq!(b.as_slice(), b" world");
562  /// ```
563  ///
564  /// ## Panics
565  ///
566  /// Panics if `at > len`.
567  #[must_use = "consider Buffer::truncate if you don't need the other half"]
568  pub fn split_off(&mut self, at: usize) -> Self {
569    self
570      .try_split_off(at)
571      .unwrap_or_else(|_| panic!("split_off out of bounds: {} > {}", at, self.remaining()))
572  }
573
574  /// Splits the buffer into two at the given index.
575  ///
576  /// Afterwards `self` contains elements `[at, len)`, and the returned `Buffer`
577  /// contains elements `[0, at)`.
578  ///
579  /// This operation copies the head into a new `Buffer`.
580  ///
581  /// ## Example
582  ///
583  /// ```rust
584  /// use smol_bytes::Buffer;
585  ///
586  /// let mut a = Buffer::try_from(&b"hello world"[..]).unwrap();
587  /// let b = a.split_to(5);
588  /// assert_eq!(b.as_slice(), b"hello");
589  /// assert_eq!(a.as_slice(), b" world");
590  /// ```
591  ///
592  /// ## Panics
593  ///
594  /// Panics if `at > len`.
595  #[must_use = "consider Buffer::advance if you don't need the other half"]
596  pub fn split_to(&mut self, at: usize) -> Self {
597    self
598      .try_split_to(at)
599      .unwrap_or_else(|_| panic!("split_to out of bounds: {} > {}", at, self.remaining()))
600  }
601
602  /// Tries to split the buffer into two at the given index.
603  ///
604  /// Afterwards `self` contains elements `[0, at)`, and the returned `Buffer`
605  /// contains elements `[at, len)`.
606  ///
607  /// Returns `Err(OutOfBounds)` if `at > remaining()`.
608  ///
609  /// ## Example
610  ///
611  /// ```rust
612  /// use smol_bytes::Buffer;
613  ///
614  /// let mut a = Buffer::try_from(&b"hello world"[..]).unwrap();
615  /// let b = a.try_split_off(5).unwrap();
616  /// assert_eq!(a.as_slice(), b"hello");
617  /// assert_eq!(b.as_slice(), b" world");
618  /// ```
619  #[must_use = "consider Buffer::truncate if you don't need the other half"]
620  pub const fn try_split_off(&mut self, at: usize) -> Result<Self, OutOfBounds> {
621    let len = self.remaining();
622    if at > len {
623      return Err(OutOfBounds::new(at, len));
624    }
625
626    let tail_len = len - at;
627    // SAFETY: `at <= len` proves the source range `at..len` is initialized;
628    // `tail_len <= INLINE_CAP` keeps the destination in `new_buf`, and the
629    // distinct buffers cannot overlap.
630    let tail = unsafe {
631      let mut new_buf = Self::new();
632      if tail_len > 0 {
633        let src = self.as_slice().as_ptr().add(at);
634        copy_nonoverlapping(src, new_buf.buf.as_mut_ptr() as *mut u8, tail_len);
635        new_buf.end = InlineSize::from_u8(tail_len as u8);
636      }
637      new_buf
638    };
639
640    self.truncate(at);
641    Ok(tail)
642  }
643
644  /// Tries to split the buffer into two at the given index.
645  ///
646  /// Afterwards `self` contains elements `[at, len)`, and the returned `Buffer`
647  /// contains elements `[0, at)`.
648  ///
649  /// Returns `Err(OutOfBounds)` if `at > remaining()`.
650  ///
651  /// ## Example
652  ///
653  /// ```rust
654  /// use smol_bytes::Buffer;
655  ///
656  /// let mut a = Buffer::try_from(&b"hello world"[..]).unwrap();
657  /// let b = a.try_split_to(5).unwrap();
658  /// assert_eq!(b.as_slice(), b"hello");
659  /// assert_eq!(a.as_slice(), b" world");
660  /// ```
661  #[must_use = "consider Buffer::advance if you don't need the other half"]
662  pub const fn try_split_to(&mut self, at: usize) -> Result<Self, OutOfBounds> {
663    let len = self.remaining();
664    if at > len {
665      return Err(OutOfBounds::new(at, len));
666    }
667
668    // SAFETY: `at <= len <= INLINE_CAP` proves the source prefix is
669    // initialized and the destination fits; the distinct buffers cannot
670    // overlap.
671    let head = unsafe {
672      let mut new_buf = Self::new();
673      if at > 0 {
674        let src = self.as_slice().as_ptr();
675        copy_nonoverlapping(src, new_buf.buf.as_mut_ptr() as *mut u8, at);
676        new_buf.end = InlineSize::from_u8(at as u8);
677      }
678      new_buf
679    };
680
681    // SAFETY: `at <= remaining == end - cur`, so the new cursor is at most
682    // `end` and remains a valid `InlineSize`.
683    self.cur = unsafe { InlineSize::from_u8(self.cur.to_u8() + at as u8) };
684    Ok(head)
685  }
686
687  /// Creates a new buffer containing a copy of the specified range.
688  ///
689  /// ## Example
690  ///
691  /// ```rust
692  /// use smol_bytes::Buffer;
693  ///
694  /// let buf = Buffer::try_from(&b"hello world"[..]).unwrap();
695  /// let slice = buf.slice(0..5);
696  /// assert_eq!(slice.as_slice(), b"hello");
697  /// ```
698  ///
699  /// ## Panics
700  ///
701  /// Panics if the range is out of bounds.
702  pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
703    self.try_slice(range).unwrap_or_else(|e| panic!("{e}"))
704  }
705
706  /// Tries to create a new buffer containing a copy of the specified range.
707  ///
708  /// Returns `Err(OutOfBounds)` if the range is out of bounds or the slice is too large.
709  ///
710  /// ## Example
711  ///
712  /// ```rust
713  /// use smol_bytes::Buffer;
714  ///
715  /// let buf = Buffer::try_from(&b"hello world"[..]).unwrap();
716  /// let slice = buf.try_slice(0..5).unwrap();
717  /// assert_eq!(slice.as_slice(), b"hello");
718  /// ```
719  pub fn try_slice(&self, range: impl RangeBounds<usize>) -> Result<Self, RangeOutOfBounds> {
720    let len = self.len();
721    let (begin, end) = normalize_range(range, len)?;
722
723    if begin == end {
724      return Ok(Self::new());
725    }
726
727    // SAFETY: `normalize_range` proves `begin <= end <= self.len()`, so the
728    // subslice is initialized and its length is at most `INLINE_CAP`.
729    Ok(unsafe { Self::copy_from_slice(&self.as_slice()[begin..end]) })
730  }
731
732  /// Replaces a range of visible bytes with `replacement`.
733  ///
734  /// # Panics
735  ///
736  /// Panics if the range is invalid or the replacement cannot fit in the
737  /// remaining tail capacity.
738  pub fn replace_range(&mut self, range: impl RangeBounds<usize>, replacement: &[u8]) {
739    self
740      .try_replace_range(range, replacement)
741      .unwrap_or_else(|error| panic!("replace_range failed: {error}"));
742  }
743
744  /// Tries to replace a range of visible bytes with `replacement`.
745  ///
746  /// The range is normalized before capacity is checked. On error this buffer
747  /// is unchanged; consumed prefix storage is not reclaimed implicitly.
748  pub fn try_replace_range(
749    &mut self,
750    range: impl RangeBounds<usize>,
751    replacement: &[u8],
752  ) -> Result<(), ByteEditError> {
753    let old_len = self.len();
754    let (start, end) = normalize_range(range, old_len)?;
755    let removed = end - start;
756    let growth = replacement.len().saturating_sub(removed);
757    let available = self.remaining_mut();
758    if growth > available {
759      return Err(
760        TryPutError {
761          requested: growth,
762          available,
763        }
764        .into(),
765      );
766    }
767
768    let mut storage = RawUtf8Storage::fixed(self);
769    replace_bytes(&mut storage, start, end, replacement);
770    Ok(())
771  }
772
773  /// Appends a copy of the specified visible byte range.
774  ///
775  /// # Panics
776  ///
777  /// Panics if the range is invalid or its bytes do not fit in the remaining
778  /// tail capacity.
779  pub fn extend_from_within(&mut self, range: impl RangeBounds<usize>) {
780    self
781      .try_extend_from_within(range)
782      .unwrap_or_else(|error| panic!("extend_from_within failed: {error}"));
783  }
784
785  /// Tries to append a copy of the specified visible byte range.
786  ///
787  /// The range is normalized before capacity is checked. On error this buffer
788  /// is unchanged; consumed prefix storage is not reclaimed implicitly.
789  pub fn try_extend_from_within(
790    &mut self,
791    range: impl RangeBounds<usize>,
792  ) -> Result<(), ByteEditError> {
793    let old_len = self.len();
794    let (start, end) = normalize_range(range, old_len)?;
795    let count = end - start;
796    let new_len = old_len.checked_add(count).expect("buffer length overflow");
797    let available = self.remaining_mut();
798    if count > available {
799      return Err(
800        TryPutError {
801          requested: count,
802          available,
803        }
804        .into(),
805      );
806    }
807
808    if count == 0 {
809      return Ok(());
810    }
811
812    self.resize(new_len, 0);
813    self.as_mut_slice().copy_within(start..end, old_len);
814    Ok(())
815  }
816
817  /// Resizes the buffer to the specified length, filling with `value` if expanding.
818  ///
819  /// ## Example
820  ///
821  /// ```rust
822  /// use smol_bytes::Buffer;
823  ///
824  /// let mut buf = Buffer::try_from(&b"hello"[..]).unwrap();
825  /// buf.resize(8, b'x');
826  /// assert_eq!(buf.as_slice(), b"helloxxx");
827  ///
828  /// buf.resize(3, 0);
829  /// assert_eq!(buf.as_slice(), b"hel");
830  /// ```
831  ///
832  /// ## Panics
833  ///
834  /// Panics if the new length exceeds capacity.
835  pub fn resize(&mut self, new_len: usize, value: u8) {
836    let current_len = self.remaining();
837
838    if new_len == current_len {
839      return;
840    }
841
842    if new_len < current_len {
843      self.truncate(new_len);
844      return;
845    }
846
847    // Expanding
848    let additional = new_len - current_len;
849    assert!(
850      self.remaining_mut() >= additional,
851      "resize exceeds capacity: {} + {} > {}",
852      current_len,
853      additional,
854      self.capacity()
855    );
856
857    self.put_bytes(value, additional);
858  }
859
860  /// Tries to resize the buffer to the specified length, filling with `value`
861  /// if expanding.
862  ///
863  /// Returns `Err(OutOfBounds)` if the new length exceeds capacity.
864  ///
865  /// ## Example
866  ///
867  /// ```rust
868  /// use smol_bytes::Buffer;
869  ///
870  /// let mut buf = Buffer::try_from(&b"hello"[..]).unwrap();
871  /// assert!(buf.try_resize(8, b'x').is_ok());
872  /// assert_eq!(buf.as_slice(), b"helloxxx");
873  ///
874  /// assert!(buf.try_resize(3, 0).is_ok());
875  /// assert_eq!(buf.as_slice(), b"hel");
876  /// ```
877  pub const fn try_resize(&mut self, new_len: usize, value: u8) -> Result<(), OutOfBounds> {
878    let current_len = self.remaining();
879
880    if new_len == current_len {
881      return Ok(());
882    }
883
884    if new_len < current_len {
885      self.truncate(new_len);
886      return Ok(());
887    }
888
889    // Expanding
890    let additional = new_len - current_len;
891    if self.remaining_mut() < additional {
892      return Err(OutOfBounds::new(new_len, self.capacity()));
893    }
894
895    match self.try_put_bytes(value, additional) {
896      Ok(()) => Ok(()),
897      Err(_) => {
898        // The identical capacity check above makes this branch unreachable;
899        // retain a defensive error instead of relying on unchecked state.
900        Err(OutOfBounds::new(new_len, self.capacity()))
901      }
902    }
903  }
904
905  /// Clears the buffer, removing all data. Existing capacity is preserved.
906  ///
907  /// ## Example
908  ///
909  /// ```rust
910  /// use smol_bytes::Buffer;
911  ///
912  /// let mut bytes = Buffer::try_from(&b"hello world"[..]).unwrap();
913  /// bytes.clear();
914  /// assert_eq!(bytes.len(), 0);
915  /// ```
916  #[cfg_attr(not(coverage), inline(always))]
917  pub const fn clear(&mut self) {
918    self.end = InlineSize::_V0;
919    self.cur = InlineSize::_V0;
920  }
921
922  /// Returns the remaining spare capacity of the buffer as a slice of [`MaybeUninit<u8>`].
923  ///
924  /// 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.
925  ///
926  /// ## Example
927  ///
928  /// ```
929  /// use smol_bytes::{Buffer, INLINE_CAP};
930  ///
931  /// let mut buf = Buffer::new();
932  ///
933  /// // Fill in the first 3 elements.
934  /// let uninit = buf.spare_capacity_mut();
935  /// uninit[0].write(0);
936  /// uninit[1].write(1);
937  /// uninit[2].write(2);
938  ///
939  /// // Mark the first 3 bytes of the buffer as being initialized.
940  /// unsafe {
941  ///   buf.set_len(3);
942  /// }
943  ///
944  /// assert_eq!(buf.as_slice(), &[0, 1, 2]);
945  /// ```
946  #[cfg_attr(not(coverage), inline(always))]
947  pub const fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<u8>] {
948    let end = self.end.to_usize();
949    // SAFETY: the invariant guarantees `end <= INLINE_CAP`; `buf.add(end)`
950    // starts the uninitialized tail and the returned length stays in `buf`.
951    unsafe { from_raw_parts_mut(self.buf.as_mut_ptr().add(end), INLINE_CAP - end) }
952  }
953
954  /// Returns the capacity of the buffer.
955  ///
956  /// The capacity is not always equal to [`INLINE_CAP`], as the [`advance`](Self::advance) method
957  /// may move the underlying cursor forward, reducing the available capacity.
958  #[cfg_attr(not(coverage), inline(always))]
959  pub const fn capacity(&self) -> usize {
960    INLINE_CAP - self.cur.to_usize()
961  }
962
963  /// Returns the initialized portion of the buffer as a slice.
964  ///
965  /// This will include all bytes from the start of the buffer up to the current length.
966  #[cfg_attr(not(coverage), inline(always))]
967  pub const fn as_slice(&self) -> &[u8] {
968    let ptr = self.buf.as_ptr() as *const u8;
969    let remaining = self.remaining();
970    // SAFETY: the invariant guarantees `buf[..end]` is initialized and
971    // `cur + remaining == end <= INLINE_CAP`.
972    unsafe { core::slice::from_raw_parts(ptr.add(self.cur.to_usize()), remaining) }
973  }
974
975  /// Returns the mutable initialized portion of the buffer as a mutable slice.
976  ///
977  /// This will include all bytes from the start of the buffer up to the current length.
978  #[cfg_attr(not(coverage), inline(always))]
979  pub const fn as_mut_slice(&mut self) -> &mut [u8] {
980    let ptr = self.buf.as_mut_ptr() as *mut u8;
981    let remaining = Self::remaining(self);
982    // SAFETY: the invariant guarantees `buf[..end]` is initialized and this
983    // exclusive borrow covers exactly `cur..end` within the backing array.
984    unsafe { core::slice::from_raw_parts_mut(ptr.add(self.cur.to_usize()), remaining) }
985  }
986
987  /// Transfer bytes into `self` from `src` and advance the cursor by the
988  /// number of bytes written.
989  ///
990  /// `self` must have enough remaining capacity to contain all of `src`.
991  ///
992  /// ```
993  /// use smol_bytes::{Buffer, INLINE_CAP};
994  ///
995  /// let mut dst = Buffer::new();
996  ///
997  /// {
998  ///     dst.put_slice(b"hello");
999  ///     assert_eq!(INLINE_CAP - 5, dst.remaining_mut());
1000  /// }
1001  ///
1002  /// assert_eq!(dst, "hello");
1003  /// ```
1004  #[inline]
1005  pub fn put_slice(&mut self, src: &[u8]) {
1006    self
1007      .try_put_slice(src)
1008      .unwrap_or_else(|e| panic_advance(e.available, e.requested))
1009  }
1010
1011  /// Try to transfer bytes into `self` from `src` and advance the cursor by the
1012  /// number of bytes written.
1013  ///
1014  /// `self` must have enough remaining capacity to contain all of `src`.
1015  ///
1016  /// ```
1017  /// use smol_bytes::{Buffer, INLINE_CAP};
1018  ///
1019  /// let mut dst = Buffer::new();
1020  ///
1021  /// {
1022  ///     dst.try_put_slice(b"hello").unwrap();
1023  ///     assert_eq!(INLINE_CAP - 5, dst.remaining_mut());
1024  /// }
1025  ///
1026  /// assert_eq!("hello", &dst);
1027  /// ```
1028  #[inline]
1029  pub const fn try_put_slice(&mut self, src: &[u8]) -> Result<(), TryPutError> {
1030    let available = self.remaining_mut();
1031    let requested = src.len();
1032
1033    if requested > available {
1034      return Err(TryPutError {
1035        requested,
1036        available,
1037      });
1038    }
1039
1040    let slen = self.end.to_usize();
1041    // SAFETY: `requested <= remaining_mut` proves `slen + requested <=
1042    // INLINE_CAP`; `src` is initialized and cannot overlap this exclusive
1043    // buffer borrow.
1044    unsafe {
1045      copy_nonoverlapping(
1046        src.as_ptr(),
1047        self.buf.as_mut_ptr().add(slen) as _,
1048        requested,
1049      );
1050    }
1051    // SAFETY: the capacity check above proves the new absolute end is at most
1052    // `INLINE_CAP`, and the copy initialized every newly exposed byte.
1053    self.end = unsafe { InlineSize::from_u8(slen as u8 + requested as u8) };
1054    Ok(())
1055  }
1056
1057  /// Put `cnt` bytes `val` into `self`.
1058  ///
1059  /// Logically equivalent to calling `self.put_u8(val)` `cnt` times, but may work faster.
1060  ///
1061  /// `self` must have at least `cnt` remaining capacity.
1062  ///
1063  /// ```
1064  /// use smol_bytes::{Buffer, INLINE_CAP};
1065  ///
1066  /// let mut dst = Buffer::new();
1067  ///
1068  /// {
1069  ///     dst.put_bytes(b'a', 4);
1070  ///     assert_eq!(INLINE_CAP - 4, dst.remaining_mut());
1071  /// }
1072  ///
1073  /// assert_eq!("aaaa", &dst);
1074  /// ```
1075  ///
1076  /// ## Panics
1077  ///
1078  /// This function panics if there is not enough remaining capacity in
1079  /// `self`.
1080  #[inline]
1081  pub fn put_bytes(&mut self, val: u8, cnt: usize) {
1082    self
1083      .try_put_bytes(val, cnt)
1084      .unwrap_or_else(|e| panic_advance(e.available, e.requested))
1085  }
1086
1087  /// Try to put `cnt` bytes `val` into `self`.
1088  ///
1089  /// Logically equivalent to calling `self.put_u8(val)` `cnt` times, but may work faster.
1090  ///
1091  /// `self` must have at least `cnt` remaining capacity.
1092  ///
1093  /// ```
1094  /// use smol_bytes::{Buffer, INLINE_CAP};
1095  ///
1096  /// let mut dst = Buffer::new();
1097  ///
1098  /// {
1099  ///     dst.try_put_bytes(b'a', 4).unwrap();
1100  ///     assert_eq!(INLINE_CAP - 4, dst.remaining_mut());
1101  /// }
1102  ///
1103  /// assert_eq!("aaaa".as_bytes(), &dst);
1104  /// ```
1105  #[inline]
1106  pub const fn try_put_bytes(&mut self, val: u8, cnt: usize) -> Result<(), TryPutError> {
1107    if cnt == 0 {
1108      return Ok(());
1109    }
1110
1111    let available = self.remaining_mut();
1112    if available < cnt {
1113      return Err(TryPutError {
1114        requested: cnt,
1115        available,
1116      });
1117    }
1118
1119    // SAFETY: `cnt <= remaining_mut` proves `end + cnt <= INLINE_CAP`; the
1120    // write initializes exactly the bytes that the new end exposes.
1121    unsafe {
1122      write_bytes(self.buf.as_mut_ptr().add(self.end.to_usize()), val, cnt);
1123    }
1124    // SAFETY: the capacity check above proves the new absolute end is a valid
1125    // `InlineSize`, and `write_bytes` initialized the extended region.
1126    self.end = unsafe { InlineSize::from_u8(self.end.to_u8() + cnt as u8) };
1127    Ok(())
1128  }
1129
1130  /// Put `cnt` bytes `val` into `self`.
1131  ///
1132  /// Logically equivalent to calling `self.put_u8(val)` `cnt` times, but may work faster.
1133  ///
1134  /// `self` must have at least `cnt` remaining capacity.
1135  ///
1136  /// ```
1137  /// use smol_bytes::{Buffer, INLINE_CAP};
1138  ///
1139  /// let mut dst = Buffer::new();
1140  ///
1141  /// {
1142  ///     dst.put_u8(b'a');
1143  ///     assert_eq!(INLINE_CAP - 1, dst.remaining_mut());
1144  /// }
1145  ///
1146  /// assert_eq!("a", &dst);
1147  /// ```
1148  ///
1149  /// ## Panics
1150  ///
1151  /// This function panics if there is not enough remaining capacity in
1152  /// `self`.
1153  #[inline]
1154  pub fn put_u8(&mut self, val: u8) {
1155    self
1156      .try_put_u8(val)
1157      .unwrap_or_else(|e| panic_advance(e.available, e.requested))
1158  }
1159
1160  /// Try to put `cnt` bytes `val` into `self`.
1161  ///
1162  /// Logically equivalent to calling `self.put_u8(val)` `cnt` times, but may work faster.
1163  ///
1164  /// `self` must have at least `cnt` remaining capacity.
1165  ///
1166  /// ```
1167  /// use smol_bytes::{Buffer, INLINE_CAP};
1168  ///
1169  /// let mut dst = Buffer::new();
1170  ///
1171  /// {
1172  ///     dst.try_put_u8(b'a').unwrap();
1173  ///     assert_eq!(INLINE_CAP - 1, dst.remaining_mut());
1174  /// }
1175  ///
1176  /// assert_eq!("a".as_bytes(), &dst);
1177  /// ```
1178  ///
1179  /// ## Panics
1180  ///
1181  /// This function panics if there is not enough remaining capacity in
1182  /// `self`.
1183  #[inline]
1184  pub const fn try_put_u8(&mut self, val: u8) -> Result<(), TryPutError> {
1185    let available = self.remaining_mut();
1186    if available < 1 {
1187      return Err(TryPutError {
1188        requested: 1,
1189        available,
1190      });
1191    }
1192
1193    self.buf[self.end.to_usize()].write(val);
1194    // SAFETY: `remaining_mut >= 1` proves `end + 1 <= INLINE_CAP`, and the
1195    // preceding write initialized the byte being exposed.
1196    self.end = unsafe { InlineSize::from_u8(self.end.to_u8() + 1) };
1197    Ok(())
1198  }
1199}
1200
1201#[cfg(any(feature = "alloc", feature = "std"))]
1202const _: () = {
1203  use bytes::{Buf, BufMut, buf::UninitSlice};
1204
1205  use crate::macros::forward_buf_mut;
1206
1207  impl Buf for Buffer {
1208    #[cfg_attr(not(coverage), inline(always))]
1209    fn remaining(&self) -> usize {
1210      Self::remaining(self)
1211    }
1212
1213    #[cfg_attr(not(coverage), inline(always))]
1214    fn chunk(&self) -> &[u8] {
1215      self.borrow()
1216    }
1217
1218    #[cfg_attr(not(coverage), inline(always))]
1219    fn advance(&mut self, cnt: usize) {
1220      Self::advance(self, cnt);
1221    }
1222
1223    fn get_int(&mut self, nbytes: usize) -> i64 {
1224      sign_extend(::bytes::Buf::get_uint(self, nbytes), nbytes)
1225    }
1226
1227    fn get_int_le(&mut self, nbytes: usize) -> i64 {
1228      sign_extend(::bytes::Buf::get_uint_le(self, nbytes), nbytes)
1229    }
1230
1231    fn get_int_ne(&mut self, nbytes: usize) -> i64 {
1232      sign_extend(::bytes::Buf::get_uint_ne(self, nbytes), nbytes)
1233    }
1234
1235    fn try_get_int(&mut self, nbytes: usize) -> Result<i64, bytes::TryGetError> {
1236      ::bytes::Buf::try_get_uint(self, nbytes).map(|value| sign_extend(value, nbytes))
1237    }
1238
1239    fn try_get_int_le(&mut self, nbytes: usize) -> Result<i64, bytes::TryGetError> {
1240      ::bytes::Buf::try_get_uint_le(self, nbytes).map(|value| sign_extend(value, nbytes))
1241    }
1242
1243    fn try_get_int_ne(&mut self, nbytes: usize) -> Result<i64, bytes::TryGetError> {
1244      ::bytes::Buf::try_get_uint_ne(self, nbytes).map(|value| sign_extend(value, nbytes))
1245    }
1246  }
1247
1248  #[cfg(any(feature = "alloc", feature = "std"))]
1249  unsafe impl BufMut for Buffer {
1250    #[cfg_attr(not(coverage), inline(always))]
1251    fn remaining_mut(&self) -> usize {
1252      Self::remaining_mut(self)
1253    }
1254
1255    #[cfg_attr(not(coverage), inline(always))]
1256    unsafe fn advance_mut(&mut self, cnt: usize) {
1257      // SAFETY: forwards to the inherent `Buffer::advance_mut` which has
1258      // the same safety contract as the trait method.
1259      unsafe { Self::advance_mut(self, cnt) };
1260    }
1261
1262    #[cfg_attr(not(coverage), inline(always))]
1263    fn chunk_mut(&mut self) -> &mut UninitSlice {
1264      let end = self.end.to_usize();
1265      if end >= INLINE_CAP {
1266        return UninitSlice::new(&mut []);
1267      }
1268      UninitSlice::uninit(&mut self.buf[end..])
1269    }
1270
1271    #[cfg_attr(not(coverage), inline(always))]
1272    fn put_slice(&mut self, src: &[u8]) {
1273      Self::put_slice(self, src);
1274    }
1275
1276    #[cfg_attr(not(coverage), inline(always))]
1277    fn put_bytes(&mut self, val: u8, requested: usize) {
1278      Self::put_bytes(self, val, requested);
1279    }
1280
1281    forward_buf_mut! {
1282      i16,
1283      i32,
1284      i64,
1285      i128,
1286      u16,
1287      u32,
1288      u64,
1289      u128,
1290      f32,
1291      f64,
1292    }
1293  }
1294};
1295
1296/// Panic with a nice error message.
1297#[cold]
1298fn panic_advance(available: usize, requested: usize) -> ! {
1299  panic!("advance out of bounds: the len is {available} but advancing by {requested}",);
1300}
1301
1302#[cold]
1303fn panic_does_not_fit(size: usize, nbytes: usize) -> ! {
1304  panic!(
1305    "size too large: the integer type can fit {} bytes, but nbytes is {}",
1306    size, nbytes
1307  );
1308}
1309
1310const _: () = {
1311  const fn _assert<T: Send + Sync>() {}
1312  _assert::<Buffer>();
1313};