Skip to main content

vortex_buffer/
buffer_mut.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use core::mem::MaybeUninit;
5use std::any::type_name;
6use std::cmp::max;
7use std::fmt::Debug;
8use std::fmt::Formatter;
9use std::io::Write;
10use std::ops::Deref;
11use std::ops::DerefMut;
12
13use bytes::Buf;
14use bytes::BufMut;
15use bytes::BytesMut;
16use bytes::buf::UninitSlice;
17use itertools::Itertools;
18use vortex_error::VortexExpect;
19use vortex_error::vortex_panic;
20
21use crate::Alignment;
22use crate::Buffer;
23use crate::ByteBufferMut;
24use crate::debug::TruncatedDebug;
25use crate::trusted_len::TrustedLen;
26
27/// A mutable buffer that maintains a runtime-defined alignment through resizing operations.
28#[derive(PartialEq, Eq)]
29pub struct BufferMut<T> {
30    pub(crate) bytes: BytesMut,
31    pub(crate) length: usize,
32    pub(crate) alignment: Alignment,
33    pub(crate) _marker: std::marker::PhantomData<T>,
34}
35
36impl<T> BufferMut<T> {
37    /// Create a new `BufferMut` with the requested alignment and capacity.
38    pub fn with_capacity(capacity: usize) -> Self {
39        Self::with_capacity_aligned(capacity, Alignment::of::<T>())
40    }
41
42    /// Create a new `BufferMut` with the requested alignment and capacity.
43    ///
44    /// The allocation is over-aligned to [`Alignment::DEFAULT_ALIGNMENT`] when that is larger than
45    /// `alignment`. Use [`with_capacity_preferred_aligned`] to control the over-alignment.
46    ///
47    /// [`with_capacity_preferred_aligned`]: Self::with_capacity_preferred_aligned
48    pub fn with_capacity_aligned(capacity: usize, alignment: Alignment) -> Self {
49        Self::with_capacity_preferred_aligned(
50            capacity,
51            alignment,
52            Some(Alignment::DEFAULT_ALIGNMENT),
53        )
54    }
55
56    /// Create a new `BufferMut` with the requested alignment and capacity.
57    ///
58    /// The buffer reports `alignment`, but the underlying allocation is over-aligned to the larger
59    /// of `alignment` and `preferred_alignment`.
60    pub fn with_capacity_preferred_aligned(
61        capacity: usize,
62        alignment: Alignment,
63        preferred_alignment: Option<Alignment>,
64    ) -> Self {
65        let actual = max(
66            alignment,
67            preferred_alignment.unwrap_or(Alignment::of::<u8>()),
68        );
69
70        if !alignment.is_aligned_to(Alignment::of::<T>()) {
71            vortex_panic!(
72                "Alignment {} must align to the scalar type's alignment {}",
73                alignment,
74                align_of::<T>()
75            );
76        }
77
78        let mut bytes = BytesMut::with_capacity((capacity * size_of::<T>()) + *actual);
79        bytes.align_empty(actual);
80
81        Self {
82            bytes,
83            length: 0,
84            alignment,
85            _marker: Default::default(),
86        }
87    }
88
89    /// Create a new zeroed `BufferMut`.
90    pub fn zeroed(len: usize) -> Self {
91        Self::zeroed_aligned(len, Alignment::of::<T>())
92    }
93
94    /// Create a new zeroed `BufferMut` with the requested alignment.
95    ///
96    /// The allocation is over-aligned to [`Alignment::DEFAULT_ALIGNMENT`] when that is larger than
97    /// `alignment`. Use [`zeroed_preferred_aligned`] to control the over-alignment.
98    ///
99    /// [`zeroed_preferred_aligned`]: Self::zeroed_preferred_aligned
100    pub fn zeroed_aligned(len: usize, alignment: Alignment) -> Self {
101        Self::zeroed_preferred_aligned(len, alignment, Some(Alignment::DEFAULT_ALIGNMENT))
102    }
103
104    /// Create a new zeroed `BufferMut` with the requested alignment.
105    ///
106    /// The buffer reports `alignment`, but the underlying allocation is over-aligned to the larger
107    /// of `alignment` and `preferred_alignment`.
108    pub fn zeroed_preferred_aligned(
109        len: usize,
110        alignment: Alignment,
111        preferred_alignment: Option<Alignment>,
112    ) -> Self {
113        let preferred_alignment = preferred_alignment.unwrap_or(Alignment::of::<u8>());
114        let actual_alignment = max(preferred_alignment, alignment);
115        let mut bytes = BytesMut::zeroed((len * size_of::<T>()) + *actual_alignment);
116        bytes.advance(bytes.as_ptr().align_offset(*actual_alignment));
117        unsafe { bytes.set_len(len * size_of::<T>()) };
118        let actual_len = bytes.len().checked_div(size_of::<T>()).unwrap_or(0);
119        Self {
120            bytes,
121            length: actual_len,
122            alignment,
123            _marker: Default::default(),
124        }
125    }
126
127    /// Create a new empty `BufferMut` with the provided alignment.
128    pub fn empty() -> Self {
129        Self::empty_aligned(Alignment::of::<T>())
130    }
131
132    /// Create a new empty `BufferMut` with the provided alignment.
133    ///
134    /// The allocation is over-aligned to [`Alignment::DEFAULT_ALIGNMENT`] when that is larger than
135    /// `alignment`. Use [`empty_preferred_aligned`] to control the over-alignment.
136    ///
137    /// [`empty_preferred_aligned`]: Self::empty_preferred_aligned
138    pub fn empty_aligned(alignment: Alignment) -> Self {
139        Self::empty_preferred_aligned(alignment, Some(Alignment::DEFAULT_ALIGNMENT))
140    }
141
142    /// Create a new empty `BufferMut` with the provided alignment.
143    ///
144    /// The buffer reports `alignment`, but the underlying allocation is over-aligned to the larger
145    /// of `alignment` and `preferred_alignment`.
146    pub fn empty_preferred_aligned(
147        alignment: Alignment,
148        preferred_alignment: Option<Alignment>,
149    ) -> Self {
150        BufferMut::with_capacity_preferred_aligned(0, alignment, preferred_alignment)
151    }
152
153    /// Create a new full `BufferMut` with the given value.
154    pub fn full(item: T, len: usize) -> Self
155    where
156        T: Copy,
157    {
158        let mut buffer = BufferMut::<T>::with_capacity(len);
159        buffer.push_n(item, len);
160        buffer
161    }
162
163    /// Create a mutable scalar buffer by copying the contents of the slice.
164    pub fn copy_from(other: impl AsRef<[T]>) -> Self {
165        Self::copy_from_aligned(other, Alignment::of::<T>())
166    }
167
168    /// Create a mutable scalar buffer with the alignment by copying the contents of the slice.
169    ///
170    /// The allocation is over-aligned to [`Alignment::DEFAULT_ALIGNMENT`] when that is larger than
171    /// `alignment`. Use [`copy_from_preferred_aligned`] to control the over-alignment.
172    ///
173    /// [`copy_from_preferred_aligned`]: Self::copy_from_preferred_aligned
174    ///
175    /// ## Panics
176    ///
177    /// Panics when the requested alignment isn't itself aligned to type T.
178    pub fn copy_from_aligned(other: impl AsRef<[T]>, alignment: Alignment) -> Self {
179        Self::copy_from_preferred_aligned(other, alignment, Some(Alignment::DEFAULT_ALIGNMENT))
180    }
181
182    /// Create a mutable scalar buffer with the alignment by copying the contents of the slice.
183    ///
184    /// The buffer reports `alignment`, but the underlying allocation is over-aligned to the larger
185    /// of `alignment` and `preferred_alignment`.
186    ///
187    /// ## Panics
188    ///
189    /// Panics when the requested alignment isn't itself aligned to type T.
190    pub fn copy_from_preferred_aligned(
191        other: impl AsRef<[T]>,
192        alignment: Alignment,
193        preferred_alignment: Option<Alignment>,
194    ) -> Self {
195        if !alignment.is_aligned_to(Alignment::of::<T>()) {
196            vortex_panic!("Given alignment is not aligned to type T")
197        }
198        let other = other.as_ref();
199        let mut buffer =
200            Self::with_capacity_preferred_aligned(other.len(), alignment, preferred_alignment);
201        buffer.extend_from_slice(other);
202        debug_assert_eq!(buffer.alignment(), alignment);
203        buffer
204    }
205
206    /// Get the alignment of the buffer.
207    #[inline(always)]
208    pub fn alignment(&self) -> Alignment {
209        self.alignment
210    }
211
212    /// Returns the length of the buffer.
213    #[inline(always)]
214    pub fn len(&self) -> usize {
215        debug_assert_eq!(self.length, self.bytes.len() / size_of::<T>());
216        self.length
217    }
218
219    /// Returns whether the buffer is empty.
220    #[inline(always)]
221    pub fn is_empty(&self) -> bool {
222        self.length == 0
223    }
224
225    /// Returns the capacity of the buffer.
226    #[inline]
227    pub fn capacity(&self) -> usize {
228        self.bytes.capacity() / size_of::<T>()
229    }
230
231    /// Returns a slice over the buffer of elements of type T.
232    #[inline]
233    pub fn as_slice(&self) -> &[T] {
234        let raw_slice = self.bytes.as_ref();
235        // SAFETY: alignment of Buffer is checked on construction
236        unsafe { std::slice::from_raw_parts(raw_slice.as_ptr().cast(), self.length) }
237    }
238
239    /// Returns a slice over the buffer of elements of type T.
240    #[inline]
241    pub fn as_mut_slice(&mut self) -> &mut [T] {
242        let raw_slice = self.bytes.as_mut();
243        // SAFETY: alignment of Buffer is checked on construction
244        unsafe { std::slice::from_raw_parts_mut(raw_slice.as_mut_ptr().cast(), self.length) }
245    }
246
247    /// Clear the buffer, retaining any existing capacity.
248    #[inline]
249    pub fn clear(&mut self) {
250        unsafe { self.bytes.set_len(0) }
251        self.length = 0;
252    }
253
254    /// Shortens the buffer, keeping the first `len` bytes and dropping the
255    /// rest.
256    ///
257    /// If `len` is greater than the buffer's current length, this has no
258    /// effect.
259    ///
260    /// Existing underlying capacity is preserved.
261    #[inline]
262    pub fn truncate(&mut self, len: usize) {
263        if len <= self.len() {
264            // SAFETY: Shrinking the buffer cannot expose uninitialized bytes.
265            unsafe { self.set_len(len) };
266        }
267    }
268
269    /// Reserves capacity for at least `additional` more elements to be inserted in the buffer.
270    #[inline]
271    pub fn reserve(&mut self, additional: usize) {
272        let additional_bytes = additional * size_of::<T>();
273        if additional_bytes <= self.bytes.capacity() - self.bytes.len() {
274            // We can fit the additional bytes in the remaining capacity. Nothing to do.
275            return;
276        }
277
278        // Otherwise, reserve additional + alignment bytes in case we need to realign the buffer.
279        self.reserve_allocate(additional);
280    }
281
282    /// A separate function so we can inline the reserve call's fast path. According to `BytesMut`
283    /// this has significant performance implications.
284    fn reserve_allocate(&mut self, additional: usize) {
285        let new_capacity: usize = ((self.length + additional) * size_of::<T>()) + *self.alignment;
286        // Make sure we at least double in size each time we re-allocate to amortize the cost
287        let new_capacity = new_capacity.max(self.bytes.capacity() * 2);
288
289        let mut bytes = BytesMut::with_capacity(new_capacity);
290        bytes.align_empty(self.alignment);
291        bytes.extend_from_slice(&self.bytes);
292        self.bytes = bytes;
293    }
294
295    /// Returns the spare capacity of the buffer as a slice of `MaybeUninit<T>`.
296    /// Has identical semantics to [`Vec::spare_capacity_mut`].
297    ///
298    /// The returned slice can be used to fill the buffer with data (e.g. by
299    /// reading from a file) before marking the data as initialized using the
300    /// [`set_len`] method.
301    ///
302    /// Note that the returned slice may be larger than the capacity requested at
303    /// construction, since the underlying allocation can be rounded up (e.g. to
304    /// satisfy alignment requirements).
305    ///
306    /// [`set_len`]: BufferMut::set_len
307    /// [`Vec::spare_capacity_mut`]: Vec::spare_capacity_mut
308    ///
309    /// # Examples
310    ///
311    /// ```
312    /// use vortex_buffer::BufferMut;
313    ///
314    /// // Allocate vector big enough for 10 elements.
315    /// let mut b = BufferMut::<u64>::with_capacity(10);
316    ///
317    /// // Fill in the first 3 elements.
318    /// let uninit = b.spare_capacity_mut();
319    /// uninit[0].write(0);
320    /// uninit[1].write(1);
321    /// uninit[2].write(2);
322    ///
323    /// // Mark the first 3 elements of the vector as being initialized.
324    /// unsafe {
325    ///     b.set_len(3);
326    /// }
327    ///
328    /// assert_eq!(b.as_slice(), &[0u64, 1, 2]);
329    /// ```
330    #[inline]
331    pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
332        let dst = self.bytes.spare_capacity_mut().as_mut_ptr();
333        unsafe {
334            std::slice::from_raw_parts_mut(
335                dst as *mut MaybeUninit<T>,
336                self.capacity() - self.length,
337            )
338        }
339    }
340
341    /// Sets the length of the buffer.
342    ///
343    /// # Safety
344    ///
345    /// - `new_len` must be less than or equal to [`capacity()`].
346    /// - The elements at `old_len..new_len` must be initialized.
347    ///
348    /// [`capacity()`]: Self::capacity
349    #[inline]
350    pub unsafe fn set_len(&mut self, len: usize) {
351        debug_assert!(len <= self.capacity());
352        unsafe { self.bytes.set_len(len * size_of::<T>()) };
353        self.length = len;
354    }
355
356    /// Appends a scalar to the buffer.
357    #[inline]
358    pub fn push(&mut self, value: T) {
359        self.reserve(1);
360        unsafe { self.push_unchecked(value) }
361    }
362
363    /// Appends a scalar to the buffer without checking for sufficient capacity.
364    ///
365    /// ## Safety
366    ///
367    /// The caller must ensure there is sufficient capacity in the array.
368    #[inline]
369    pub unsafe fn push_unchecked(&mut self, item: T) {
370        // SAFETY: the caller ensures we have sufficient capacity
371        unsafe {
372            let dst: *mut T = self.bytes.spare_capacity_mut().as_mut_ptr().cast();
373            dst.write(item);
374            self.bytes.set_len(self.bytes.len() + size_of::<T>())
375        }
376        self.length += 1;
377    }
378
379    /// Appends n scalars to the buffer.
380    ///
381    /// This function is slightly more optimized than `extend(iter::repeat_n(item, b))`.
382    #[inline]
383    pub fn push_n(&mut self, item: T, n: usize)
384    where
385        T: Copy,
386    {
387        self.reserve(n);
388        unsafe { self.push_n_unchecked(item, n) }
389    }
390
391    /// Appends n scalars to the buffer.
392    ///
393    /// ## Safety
394    ///
395    /// The caller must ensure there is sufficient capacity in the array.
396    #[inline]
397    pub unsafe fn push_n_unchecked(&mut self, item: T, n: usize)
398    where
399        T: Copy,
400    {
401        let mut dst: *mut T = self.bytes.spare_capacity_mut().as_mut_ptr().cast();
402        // SAFETY: we checked the capacity in the reserve call
403        unsafe {
404            let end = dst.add(n);
405            while dst < end {
406                dst.write(item);
407                dst = dst.add(1);
408            }
409            self.bytes.set_len(self.bytes.len() + (n * size_of::<T>()));
410        }
411        self.length += n;
412    }
413
414    /// Appends a slice of type `T`, growing the internal buffer as needed.
415    ///
416    /// # Example:
417    ///
418    /// ```
419    /// # use vortex_buffer::BufferMut;
420    ///
421    /// let mut builder = BufferMut::<u16>::with_capacity(10);
422    /// builder.extend_from_slice(&[42, 44, 46]);
423    ///
424    /// assert_eq!(builder.len(), 3);
425    /// ```
426    #[inline]
427    pub fn extend_from_slice(&mut self, slice: &[T]) {
428        self.reserve(slice.len());
429        let raw_slice =
430            unsafe { std::slice::from_raw_parts(slice.as_ptr().cast(), size_of_val(slice)) };
431        self.bytes.extend_from_slice(raw_slice);
432        self.length += slice.len();
433    }
434
435    /// Splits the buffer into two at the given index.
436    ///
437    /// Afterward, self contains elements `[0, at)`, and the returned buffer contains elements
438    /// `[at, capacity)`. It’s guaranteed that the memory does not move, that is, the address of
439    /// self does not change, and the address of the returned slice is at bytes after that.
440    ///
441    /// This is an O(1) operation that just increases the reference count and sets a few indices.
442    ///
443    /// Panics if either half would have a length that is not a multiple of the alignment.
444    pub fn split_off(&mut self, at: usize) -> Self {
445        if at > self.capacity() {
446            vortex_panic!("Cannot split buffer of capacity {} at {}", self.len(), at);
447        }
448
449        let bytes_at = at * size_of::<T>();
450        if !self.alignment.is_offset_aligned(bytes_at) {
451            vortex_panic!(
452                "Cannot split buffer at {}, resulting alignment is not {}",
453                at,
454                self.alignment
455            );
456        }
457
458        let new_bytes = self.bytes.split_off(bytes_at);
459
460        // Adjust the lengths, given that length may be < at
461        let new_length = self.length.saturating_sub(at);
462        self.length = self.length.min(at);
463
464        BufferMut {
465            bytes: new_bytes,
466            length: new_length,
467            alignment: self.alignment,
468            _marker: Default::default(),
469        }
470    }
471
472    /// Absorbs a mutable buffer that was previously split off.
473    ///
474    /// If the two buffers were previously contiguous and not mutated in a way that causes
475    /// re-allocation i.e., if other was created by calling split_off on this buffer, then this is
476    /// an O(1) operation that just decreases a reference count and sets a few indices.
477    ///
478    /// Otherwise, this method degenerates to self.extend_from_slice(other.as_ref()).
479    pub fn unsplit(&mut self, other: Self) {
480        if self.alignment != other.alignment {
481            vortex_panic!(
482                "Cannot unsplit buffers with different alignments: {} and {}",
483                self.alignment,
484                other.alignment
485            );
486        }
487        self.bytes.unsplit(other.bytes);
488        self.length += other.length;
489    }
490
491    /// Return the [`ByteBufferMut`] for this [`BufferMut`].
492    pub fn into_byte_buffer(self) -> ByteBufferMut {
493        ByteBufferMut {
494            bytes: self.bytes,
495            length: self.length * size_of::<T>(),
496            alignment: self.alignment,
497            _marker: Default::default(),
498        }
499    }
500
501    /// Freeze the `BufferMut` into a `Buffer`.
502    pub fn freeze(self) -> Buffer<T> {
503        Buffer {
504            bytes: self.bytes.freeze(),
505            length: self.length,
506            alignment: self.alignment,
507            _marker: Default::default(),
508        }
509    }
510
511    /// Map each element of the buffer with a closure.
512    pub fn map_each_in_place<R, F>(self, mut f: F) -> BufferMut<R>
513    where
514        T: Copy,
515        F: FnMut(T) -> R,
516    {
517        assert_eq!(
518            size_of::<T>(),
519            size_of::<R>(),
520            "Size of T and R do not match"
521        );
522        // SAFETY: we have checked that `size_of::<T>` == `size_of::<R>`.
523        let mut buf: BufferMut<R> = unsafe { std::mem::transmute(self) };
524        buf.iter_mut()
525            .for_each(|item| *item = f(unsafe { std::mem::transmute_copy(item) }));
526        buf
527    }
528
529    /// Return a `BufferMut<T>` with the same data as this one with the given alignment.
530    ///
531    /// If the data is already properly aligned, this is a metadata-only operation.
532    ///
533    /// If the data is not aligned, we copy it into a new allocation.
534    pub fn aligned(self, alignment: Alignment) -> Self {
535        if self.as_ptr().align_offset(*alignment) == 0 {
536            Self {
537                bytes: self.bytes,
538                length: self.length,
539                alignment,
540                _marker: std::marker::PhantomData,
541            }
542        } else {
543            Self::copy_from_aligned(self, alignment)
544        }
545    }
546
547    /// Transmute a `Buffer<T>` into a `Buffer<U>`.
548    ///
549    /// # Safety
550    ///
551    /// The caller must ensure that all possible bit representations of type `T` are valid when
552    /// interpreted as type `U`.
553    /// See [`std::mem::transmute`] for more details.
554    ///
555    /// # Panics
556    ///
557    /// Panics if the type `U` does not have the same size and alignment as `T`.
558    pub unsafe fn transmute<U>(self) -> BufferMut<U> {
559        assert_eq!(size_of::<T>(), size_of::<U>(), "Buffer type size mismatch");
560        assert_eq!(
561            align_of::<T>(),
562            align_of::<U>(),
563            "Buffer type alignment mismatch"
564        );
565
566        BufferMut {
567            bytes: self.bytes,
568            length: self.length,
569            alignment: self.alignment,
570            _marker: std::marker::PhantomData,
571        }
572    }
573}
574
575impl<T> Clone for BufferMut<T> {
576    fn clone(&self) -> Self {
577        // NOTE(ngates): we cannot derive Clone since BytesMut copies on clone and the alignment
578        //  might be messed up.
579        let mut buffer = BufferMut::<T>::with_capacity_aligned(self.capacity(), self.alignment);
580        buffer.extend_from_slice(self.as_slice());
581        buffer
582    }
583}
584
585impl<T: Debug> Debug for BufferMut<T> {
586    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
587        f.debug_struct(&format!("BufferMut<{}>", type_name::<T>()))
588            .field("length", &self.length)
589            .field("alignment", &self.alignment)
590            .field("as_slice", &TruncatedDebug(self.as_slice()))
591            .finish()
592    }
593}
594
595impl<T> Default for BufferMut<T> {
596    fn default() -> Self {
597        Self::empty()
598    }
599}
600
601impl<T> Deref for BufferMut<T> {
602    type Target = [T];
603
604    #[inline]
605    fn deref(&self) -> &Self::Target {
606        self.as_slice()
607    }
608}
609
610impl<T> DerefMut for BufferMut<T> {
611    #[inline]
612    fn deref_mut(&mut self) -> &mut Self::Target {
613        self.as_mut_slice()
614    }
615}
616
617impl<T> AsRef<[T]> for BufferMut<T> {
618    #[inline]
619    fn as_ref(&self) -> &[T] {
620        self.as_slice()
621    }
622}
623
624impl<T> AsMut<[T]> for BufferMut<T> {
625    #[inline]
626    fn as_mut(&mut self) -> &mut [T] {
627        self.as_mut_slice()
628    }
629}
630
631impl<T> BufferMut<T> {
632    /// A helper method for the two [`Extend`] implementations.
633    ///
634    /// We use the lower bound hint on the iterator to manually write data, and then we continue to
635    /// push items normally past the lower bound.
636    fn extend_iter(&mut self, mut iter: impl Iterator<Item = T>) {
637        // Since we do not know the length of the iterator, we can only guess how much memory we
638        // need to reserve. Note that these hints may be inaccurate.
639        let (lower_bound, _) = iter.size_hint();
640
641        // We choose not to use the optional upper bound size hint to match the standard library.
642
643        self.reserve(lower_bound);
644
645        let unwritten = self.capacity() - self.len();
646
647        // We store `begin` in the case that the lower bound hint is incorrect.
648        let begin: *const T = self.bytes.spare_capacity_mut().as_mut_ptr().cast();
649        let mut dst: *mut T = begin.cast_mut();
650
651        // As a first step, we manually iterate the iterator up to the known capacity.
652        for _ in 0..unwritten {
653            let Some(item) = iter.next() else {
654                // The lower bound hint may be incorrect.
655                break;
656            };
657
658            // SAFETY: We have reserved enough capacity to hold this item, and `dst` is a pointer
659            // derived from a valid reference to byte data.
660            unsafe { dst.write(item) };
661
662            // Note: We used to have `dst.add(iteration).write(item)`, here. However this was much
663            // slower than just incrementing `dst`.
664            // SAFETY: The offsets fits in `isize`, and because we were able to reserve the memory
665            // we know that `add` will not overflow.
666            unsafe { dst = dst.add(1) };
667        }
668
669        // SAFETY: `dst` was derived from `begin`, which were both valid references to byte data,
670        // and since the only operation that `dst` has is `add`, we know that `dst >= begin`.
671        let items_written = unsafe { dst.offset_from_unsigned(begin) };
672        let length = self.len() + items_written;
673
674        // SAFETY: We have written valid items between the old length and the new length.
675        unsafe { self.set_len(length) };
676
677        // Finally, since the iterator will have arbitrarily more items to yield, we push the
678        // remaining items normally.
679        iter.for_each(|item| self.push(item));
680    }
681
682    /// Extends the `BufferMut` with an iterator with `TrustedLen`.
683    ///
684    /// The caller guarantees that the iterator will have a trusted upper bound, which allows the
685    /// implementation to reserve all of the memory needed up front.
686    pub fn extend_trusted<I: TrustedLen<Item = T>>(&mut self, iter: I) {
687        let (_, upper_bound) = iter.size_hint();
688        self.reserve(
689            upper_bound
690                .vortex_expect("`TrustedLen` iterator somehow didn't have valid upper bound"),
691        );
692
693        let begin: *const T = self.bytes.spare_capacity_mut().as_mut_ptr().cast();
694        let mut dst: *mut T = begin.cast_mut();
695
696        iter.for_each(|item| {
697            // SAFETY: We have reserved enough capacity to hold this item, and `dst` is a pointer
698            // derived from a valid reference to byte data.
699            unsafe { dst.write(item) };
700
701            // Note: We used to have `dst.add(iteration).write(item)`, here. However this was much
702            // slower than just incrementing `dst`.
703            // SAFETY: The offset fits in `isize`, and because we were able to reserve the memory
704            // we know that `add` will not overflow.
705            unsafe { dst = dst.add(1) };
706        });
707
708        // SAFETY: `dst` starts at `begin` and advances by one for each item, so both pointers refer
709        // to the same allocation and `dst` is at or after `begin`.
710        let items_written = unsafe { dst.offset_from_unsigned(begin) };
711        let length = self.len() + items_written;
712
713        // SAFETY: We have written valid items between the old length and the new length.
714        unsafe { self.set_len(length) };
715    }
716
717    /// Creates a `BufferMut` from an iterator with a trusted length.
718    ///
719    /// Internally, this calls [`extend_trusted()`](Self::extend_trusted).
720    pub fn from_trusted_len_iter<I>(iter: I) -> Self
721    where
722        I: TrustedLen<Item = T>,
723    {
724        let (_, upper_bound) = iter.size_hint();
725        let mut buffer = Self::with_capacity(
726            upper_bound
727                .vortex_expect("`TrustedLen` iterator somehow didn't have valid upper bound"),
728        );
729
730        buffer.extend_trusted(iter);
731        buffer
732    }
733
734    /// Like [`extend_trusted()`](Self::extend_trusted), but the iterator yields `Result<T, E>`
735    /// and the extension short-circuits on the first `Err`.
736    ///
737    /// On error, items written before the failure remain in the buffer.
738    pub fn try_extend_trusted<E, I>(&mut self, iter: I) -> Result<(), E>
739    where
740        I: TrustedLen<Item = Result<T, E>>,
741    {
742        iter.process_results(|values| self.extend_trusted(values))
743    }
744
745    /// Like [`from_trusted_len_iter()`](Self::from_trusted_len_iter), but the iterator yields
746    /// `Result<T, E>` and construction short-circuits on the first `Err`.
747    pub fn try_from_trusted_len_iter<E, I>(iter: I) -> Result<Self, E>
748    where
749        I: TrustedLen<Item = Result<T, E>>,
750    {
751        iter.process_results(|values| Self::from_trusted_len_iter(values))
752    }
753}
754
755impl<T> Extend<T> for BufferMut<T> {
756    #[inline]
757    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
758        self.extend_iter(iter.into_iter())
759    }
760}
761
762impl<'a, T> Extend<&'a T> for BufferMut<T>
763where
764    T: Copy + 'a,
765{
766    #[inline]
767    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
768        self.extend_iter(iter.into_iter().copied())
769    }
770}
771
772impl<T> FromIterator<T> for BufferMut<T> {
773    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
774        // We don't infer the capacity here and just let the first call to `extend` do it for us.
775        let mut buffer = Self::with_capacity(0);
776        buffer.extend(iter);
777        buffer
778    }
779}
780
781impl Buf for ByteBufferMut {
782    fn remaining(&self) -> usize {
783        self.len()
784    }
785
786    fn chunk(&self) -> &[u8] {
787        self.as_slice()
788    }
789
790    fn advance(&mut self, cnt: usize) {
791        if !self.alignment.is_offset_aligned(cnt) {
792            vortex_panic!(
793                "Cannot advance buffer by {} items, resulting alignment is not {}",
794                cnt,
795                self.alignment
796            );
797        }
798        self.bytes.advance(cnt);
799        self.length -= cnt;
800    }
801}
802
803/// As per the BufMut implementation, we must support internal resizing when
804/// asked to extend the buffer.
805/// See: <https://github.com/tokio-rs/bytes/issues/131>
806unsafe impl BufMut for ByteBufferMut {
807    #[inline]
808    fn remaining_mut(&self) -> usize {
809        usize::MAX - self.len()
810    }
811
812    #[inline]
813    unsafe fn advance_mut(&mut self, cnt: usize) {
814        if !self.alignment.is_offset_aligned(cnt) {
815            vortex_panic!(
816                "Cannot advance buffer by {} items, resulting alignment is not {}",
817                cnt,
818                self.alignment
819            );
820        }
821        unsafe { self.bytes.advance_mut(cnt) };
822        self.length -= cnt;
823    }
824
825    #[inline]
826    fn chunk_mut(&mut self) -> &mut UninitSlice {
827        self.bytes.chunk_mut()
828    }
829
830    fn put<T: Buf>(&mut self, mut src: T)
831    where
832        Self: Sized,
833    {
834        while src.has_remaining() {
835            let chunk = src.chunk();
836            self.extend_from_slice(chunk);
837            src.advance(chunk.len());
838        }
839    }
840
841    #[inline]
842    fn put_slice(&mut self, src: &[u8]) {
843        self.extend_from_slice(src);
844    }
845
846    #[inline]
847    fn put_bytes(&mut self, val: u8, cnt: usize) {
848        self.push_n(val, cnt)
849    }
850}
851
852/// Extension trait for [`BytesMut`] that provides functions for aligning the buffer.
853trait AlignedBytesMut {
854    /// Align an empty `BytesMut` to the specified alignment.
855    ///
856    /// ## Panics
857    ///
858    /// Panics if the buffer is not empty, or if there is not enough capacity to align the buffer.
859    fn align_empty(&mut self, alignment: Alignment);
860}
861
862impl AlignedBytesMut for BytesMut {
863    fn align_empty(&mut self, alignment: Alignment) {
864        // TODO(joe): this is slow fixme
865        if !self.is_empty() {
866            vortex_panic!("ByteBufferMut must be empty");
867        }
868
869        let padding = self.as_ptr().align_offset(*alignment);
870        self.capacity()
871            .checked_sub(padding)
872            .vortex_expect("Not enough capacity to align buffer");
873
874        // SAFETY: We know the buffer is empty, and we know we have enough capacity, so we can
875        // safely set the length to the padding and advance the buffer to the aligned offset.
876        unsafe { self.set_len(padding) };
877        self.advance(padding);
878    }
879}
880
881impl Write for ByteBufferMut {
882    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
883        self.extend_from_slice(buf);
884        Ok(buf.len())
885    }
886
887    fn flush(&mut self) -> std::io::Result<()> {
888        Ok(())
889    }
890}
891
892#[cfg(test)]
893mod test {
894    use bytes::Buf;
895    use bytes::BufMut;
896
897    use crate::Alignment;
898    use crate::BufferMut;
899    use crate::ByteBufferMut;
900    use crate::buffer_mut;
901
902    #[test]
903    fn capacity() {
904        let mut n = 57;
905        let mut buf = BufferMut::<i32>::with_capacity_aligned(n, Alignment::new(1024));
906        assert!(buf.capacity() >= 57);
907
908        while n > 0 {
909            buf.push(0);
910            assert!(buf.capacity() >= n);
911            n -= 1
912        }
913
914        assert_eq!(buf.alignment(), Alignment::new(1024));
915    }
916
917    #[test]
918    fn from_iter() {
919        let buf = BufferMut::from_iter([0, 10, 20, 30]);
920        assert_eq!(buf.as_slice(), &[0, 10, 20, 30]);
921    }
922
923    #[test]
924    fn try_from_trusted_len_iter_ok() {
925        let buf = BufferMut::<i32>::try_from_trusted_len_iter(
926            [0, 10, 20, 30].iter().map(|&v| Ok::<_, ()>(v)),
927        )
928        .unwrap();
929        assert_eq!(buf.as_slice(), &[0, 10, 20, 30]);
930    }
931
932    #[test]
933    fn try_from_trusted_len_iter_err() {
934        let result: Result<BufferMut<i32>, &'static str> = BufferMut::try_from_trusted_len_iter(
935            [0, 10, 20, 30]
936                .iter()
937                .map(|&v| if v == 20 { Err("bad") } else { Ok(v) }),
938        );
939        assert_eq!(result.err(), Some("bad"));
940    }
941
942    #[test]
943    fn try_extend_trusted_retains_values_before_error() {
944        let mut buf = BufferMut::from_iter([0, 10]);
945        let result = buf.try_extend_trusted([Ok(20), Err("bad"), Ok(30)].into_iter());
946
947        assert_eq!(result, Err("bad"));
948        assert_eq!(buf.as_slice(), &[0, 10, 20]);
949    }
950
951    #[test]
952    fn extend() {
953        let mut buf = BufferMut::empty();
954        buf.extend([0i32, 10, 20, 30]);
955        buf.extend([40, 50, 60]);
956        assert_eq!(buf.as_slice(), &[0, 10, 20, 30, 40, 50, 60]);
957    }
958
959    #[test]
960    fn push() {
961        let mut buf = BufferMut::empty();
962        buf.push(1);
963        buf.push(2);
964        buf.push(3);
965        assert_eq!(buf.as_slice(), &[1, 2, 3]);
966    }
967
968    #[test]
969    fn push_n() {
970        let mut buf = BufferMut::empty();
971        buf.push_n(0, 100);
972        assert_eq!(buf.as_slice(), &[0; 100]);
973    }
974
975    #[test]
976    fn as_mut() {
977        let mut buf = buffer_mut![0, 1, 2];
978        // Uses DerefMut
979        buf[1] = 0;
980        // Uses as_mut
981        buf.as_mut()[2] = 0;
982        assert_eq!(buf.as_slice(), &[0, 0, 0]);
983    }
984
985    #[test]
986    fn map_each() {
987        let buf = buffer_mut![0i32, 1, 2];
988        // Add one, and cast to an unsigned u32 in the same closure
989        let buf = buf.map_each_in_place(|i| (i + 1) as u32);
990        assert_eq!(buf.as_slice(), &[1u32, 2, 3]);
991    }
992
993    #[test]
994    fn bytes_buf() {
995        let mut buf = ByteBufferMut::copy_from("helloworld".as_bytes());
996        assert_eq!(buf.remaining(), 10);
997        assert_eq!(buf.chunk(), b"helloworld");
998
999        buf.advance(5);
1000        assert_eq!(buf.remaining(), 5);
1001        assert_eq!(buf.as_slice(), b"world");
1002        assert_eq!(buf.chunk(), b"world");
1003    }
1004
1005    #[test]
1006    fn bytes_buf_mut() {
1007        let mut buf = ByteBufferMut::copy_from("hello".as_bytes());
1008        assert_eq!(BufMut::remaining_mut(&buf), usize::MAX - 5);
1009
1010        buf.put_slice(b"world");
1011        assert_eq!(buf.as_slice(), b"helloworld");
1012    }
1013
1014    #[test]
1015    fn buffer_mut_zeroed() {
1016        const LEN: usize = 17;
1017
1018        let mut buf = BufferMut::<u32>::zeroed(LEN);
1019
1020        assert_eq!(buf.as_ptr().align_offset(*Alignment::of::<u32>()), 0);
1021        assert_eq!(buf.as_slice(), &[0; LEN]);
1022
1023        buf[3] = 7;
1024        assert_eq!(buf.as_slice()[3], 7);
1025    }
1026
1027    #[test]
1028    fn buffer_mut_zeroed_aligned() {
1029        const LEN: usize = 17;
1030        let alignment = Alignment::new(64);
1031
1032        let mut buf = BufferMut::<u32>::zeroed_aligned(LEN, alignment);
1033
1034        assert_eq!(buf.as_ptr().align_offset(*alignment), 0);
1035        assert_eq!(buf.as_slice(), &[0; LEN]);
1036
1037        buf[3] = 7;
1038        assert_eq!(buf.as_slice()[3], 7);
1039    }
1040}