Skip to main content

arrow_buffer/buffer/
mutable.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::alloc::Layout;
19use std::mem;
20use std::ptr::NonNull;
21
22use crate::alloc::{ALIGNMENT, Deallocation};
23use crate::{
24    bytes::Bytes,
25    native::{ArrowNativeType, ToByteSlice},
26    util::bit_util,
27};
28
29#[cfg(feature = "pool")]
30use crate::pool::{MemoryPool, TrackedReservation};
31
32use super::Buffer;
33
34/// Error returned by fallible [`MutableBuffer`] operations.
35#[derive(Debug, Clone, PartialEq, Eq)]
36pub enum MutableBufferError {
37    /// Arithmetic overflow when computing the required buffer length or capacity.
38    LengthOverflow,
39    /// The requested capacity cannot be represented as a valid allocation layout.
40    LayoutError,
41    /// An allocation failed due to insufficient memory.
42    AllocationError(Layout),
43}
44
45impl std::fmt::Display for MutableBufferError {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        match self {
48            Self::LengthOverflow => write!(f, "buffer length overflow"),
49            Self::LayoutError => write!(f, "invalid allocation layout for requested capacity"),
50            Self::AllocationError(layout) => {
51                write!(f, "failed to allocate memory for layout {layout:?}")
52            }
53        }
54    }
55}
56
57impl std::error::Error for MutableBufferError {}
58
59/// A [`MutableBuffer`] is a wrapper over memory regions, used to build
60/// [`Buffer`]s out of items or slices of items.
61///
62/// [`Buffer`]s created from [`MutableBuffer`] (via `into`) are guaranteed to be
63/// aligned along cache lines and in multiples of 64 bytes.
64///
65/// Use [MutableBuffer::push] to insert an item, [MutableBuffer::extend_from_slice]
66/// to insert many items, and `into` to convert it to [`Buffer`]. For typed data,
67/// it is often more efficient to use [`Vec`] and convert it to [`Buffer`] rather
68/// than using [`MutableBuffer`] (see examples below).
69///
70/// # See Also
71/// * For a safe, strongly typed API consider using [`Vec`] and [`ScalarBuffer`](crate::ScalarBuffer)
72/// * To apply bitwise operations, see [`apply_bitwise_binary_op`] and [`apply_bitwise_unary_op`]
73///
74/// [`apply_bitwise_binary_op`]: crate::bit_util::apply_bitwise_binary_op
75/// [`apply_bitwise_unary_op`]: crate::bit_util::apply_bitwise_unary_op
76///
77/// # Example: Creating a [`Buffer`] from a [`MutableBuffer`]
78/// ```
79/// # use arrow_buffer::buffer::{Buffer, MutableBuffer};
80/// let mut buffer = MutableBuffer::new(0);
81/// buffer.push(256u32);
82/// buffer.extend_from_slice(&[1u32]);
83/// let buffer = Buffer::from(buffer);
84/// assert_eq!(buffer.as_slice(), &[0u8, 1, 0, 0, 1, 0, 0, 0])
85/// ```
86///
87/// The same can be achieved more efficiently by using a `Vec<u32>`
88/// ```
89/// # use arrow_buffer::buffer::Buffer;
90/// let mut vec = Vec::new();
91/// vec.push(256u32);
92/// vec.extend_from_slice(&[1u32]);
93/// let buffer = Buffer::from(vec);
94/// assert_eq!(buffer.as_slice(), &[0u8, 1, 0, 0, 1, 0, 0, 0]);
95/// ```
96///
97/// # Example: Creating a [`MutableBuffer`] from a `Vec<T>`
98/// ```
99/// # use arrow_buffer::buffer::MutableBuffer;
100/// let vec = vec![1u32, 2, 3];
101/// let mutable_buffer = MutableBuffer::from(vec); // reuses the allocation from vec
102/// assert_eq!(mutable_buffer.len(), 12); // 3 * 4 bytes
103/// ```
104///
105/// # Example: Creating a [`MutableBuffer`] from a [`Buffer`]
106/// ```
107/// # use arrow_buffer::buffer::{Buffer, MutableBuffer};
108/// let buffer: Buffer = Buffer::from(&[1u8, 2, 3, 4][..]);
109/// // Only possible to convert a Buffer into a MutableBuffer if uniquely owned
110/// // (i.e., there are no other references to it).
111/// let mut mutable_buffer = match buffer.into_mutable() {
112///    Ok(mutable) => mutable,
113///    Err(orig_buffer) => {
114///      panic!("buffer was not uniquely owned");
115///    }
116/// };
117/// mutable_buffer.push(5u8);
118/// let buffer = Buffer::from(mutable_buffer);
119/// assert_eq!(buffer.as_slice(), &[1u8, 2, 3, 4, 5])
120/// ```
121#[derive(Debug)]
122pub struct MutableBuffer {
123    // dangling iff capacity = 0
124    data: NonNull<u8>,
125    // invariant: len <= capacity
126    len: usize,
127    layout: Layout,
128
129    /// Memory reservation for tracking memory usage
130    #[cfg(feature = "pool")]
131    reservation: TrackedReservation,
132}
133
134impl MutableBuffer {
135    /// Allocate a new [MutableBuffer] with initial capacity to be at least `capacity`.
136    ///
137    /// See [`MutableBuffer::with_capacity`].
138    ///
139    /// # Panics
140    ///
141    /// See [`MutableBuffer::with_capacity`].
142    #[inline]
143    pub fn new(capacity: usize) -> Self {
144        Self::try_with_capacity(capacity).unwrap_or_else(|e| panic!("{e}"))
145    }
146
147    /// Allocate a new [MutableBuffer] with initial capacity to be at least `capacity`.
148    ///
149    /// # Panics
150    ///
151    /// If `capacity`, when rounded up to the nearest multiple of [`ALIGNMENT`], is greater
152    /// then `isize::MAX`, then this function will panic.
153    #[inline]
154    pub fn with_capacity(capacity: usize) -> Self {
155        Self::try_with_capacity(capacity).unwrap_or_else(|e| panic!("{e}"))
156    }
157
158    /// Fallible version of [`MutableBuffer::with_capacity`].
159    #[inline]
160    pub fn try_with_capacity(capacity: usize) -> Result<Self, MutableBufferError> {
161        let capacity = capacity
162            .checked_next_multiple_of(64)
163            .ok_or(MutableBufferError::LayoutError)?;
164        let layout = Layout::from_size_align(capacity, ALIGNMENT)
165            .map_err(|_| MutableBufferError::LayoutError)?;
166        let data = match layout.size() {
167            0 => dangling_ptr(),
168            _ => {
169                // Safety: Verified size != 0
170                let raw_ptr = unsafe { std::alloc::alloc(layout) };
171                match NonNull::new(raw_ptr) {
172                    Some(ptr) => ptr,
173                    None => return Err(MutableBufferError::AllocationError(layout)),
174                }
175            }
176        };
177        Ok(Self {
178            data,
179            len: 0,
180            layout,
181            #[cfg(feature = "pool")]
182            reservation: TrackedReservation::default(),
183        })
184    }
185
186    /// Allocates a new [MutableBuffer] with `len` and capacity to be at least `len` where
187    /// all bytes are guaranteed to be `0u8`.
188    /// # Example
189    /// ```
190    /// # use arrow_buffer::buffer::{Buffer, MutableBuffer};
191    /// let mut buffer = MutableBuffer::from_len_zeroed(127);
192    /// assert_eq!(buffer.len(), 127);
193    /// assert!(buffer.capacity() >= 127);
194    /// let data = buffer.as_slice_mut();
195    /// assert_eq!(data[126], 0u8);
196    /// ```
197    ///
198    /// # Panics
199    ///
200    /// Panics if `len` is too large to construct a valid allocation [`Layout`]
201    pub fn from_len_zeroed(len: usize) -> Self {
202        Self::try_from_len_zeroed(len).unwrap_or_else(|e| panic!("{e}"))
203    }
204
205    /// Fallible version of [`MutableBuffer::from_len_zeroed`].
206    pub fn try_from_len_zeroed(len: usize) -> Result<Self, MutableBufferError> {
207        let layout =
208            Layout::from_size_align(len, ALIGNMENT).map_err(|_| MutableBufferError::LayoutError)?;
209        let data = match layout.size() {
210            0 => dangling_ptr(),
211            _ => {
212                // Safety: Verified size != 0
213                let raw_ptr = unsafe { std::alloc::alloc_zeroed(layout) };
214                match NonNull::new(raw_ptr) {
215                    Some(ptr) => ptr,
216                    None => return Err(MutableBufferError::AllocationError(layout)),
217                }
218            }
219        };
220        Ok(Self {
221            data,
222            len,
223            layout,
224            #[cfg(feature = "pool")]
225            reservation: TrackedReservation::default(),
226        })
227    }
228
229    /// Allocates a new [MutableBuffer] from given `Bytes`.
230    pub(crate) fn from_bytes(bytes: Bytes) -> Result<Self, Bytes> {
231        let layout = match bytes.deallocation() {
232            Deallocation::Standard(layout) => *layout,
233            Deallocation::Custom(..) => return Err(bytes),
234        };
235
236        let len = bytes.len();
237        let data = bytes.ptr();
238        #[cfg(feature = "pool")]
239        let reservation = bytes.reservation.take();
240
241        mem::forget(bytes);
242
243        Ok(Self {
244            data,
245            len,
246            layout,
247            #[cfg(feature = "pool")]
248            reservation,
249        })
250    }
251
252    /// creates a new [MutableBuffer] with capacity and length capable of holding `len` bits.
253    /// This is useful to create a buffer for packed bitmaps.
254    ///
255    /// # Panics
256    ///
257    /// See [`MutableBuffer::from_len_zeroed`].
258    pub fn new_null(len: usize) -> Self {
259        let num_bytes = bit_util::ceil(len, 8);
260        MutableBuffer::from_len_zeroed(num_bytes)
261    }
262
263    /// Set the bits in the range of `[0, end)` to 0 (if `val` is false), or 1 (if `val`
264    /// is true). Also extend the length of this buffer to be `end`.
265    ///
266    /// This is useful when one wants to clear (or set) the bits and then manipulate
267    /// the buffer directly (e.g., modifying the buffer by holding a mutable reference
268    /// from `data_mut()`).
269    ///
270    /// # Panics
271    ///
272    /// Panics if `end` exceeds the buffer capacity.
273    pub fn with_bitset(mut self, end: usize, val: bool) -> Self {
274        assert!(end <= self.layout.size());
275        let v = if val { 255 } else { 0 };
276        unsafe {
277            std::ptr::write_bytes(self.data.as_ptr(), v, end);
278            self.len = end;
279        }
280        self
281    }
282
283    /// Ensure that `count` bytes from `start` contain zero bits
284    ///
285    /// This is used to initialize the bits in a buffer, however, it has no impact on the
286    /// `len` of the buffer and so can be used to initialize the memory region from
287    /// `len` to `capacity`.
288    ///
289    /// # Panics
290    ///
291    /// Panics if the byte range `start..start + count` exceeds the buffer capacity.
292    pub fn set_null_bits(&mut self, start: usize, count: usize) {
293        assert!(
294            start.saturating_add(count) <= self.layout.size(),
295            "range start index {start} and count {count} out of bounds for \
296            buffer of length {}",
297            self.layout.size(),
298        );
299
300        // Safety: `self.data[start..][..count]` is in-bounds and well-aligned for `u8`
301        unsafe {
302            std::ptr::write_bytes(self.data.as_ptr().add(start), 0, count);
303        }
304    }
305
306    /// Fallible version of [`MutableBuffer::reserve`].
307    #[inline]
308    pub fn try_reserve(&mut self, additional: usize) -> Result<(), MutableBufferError> {
309        let required_cap = self
310            .len
311            .checked_add(additional)
312            .ok_or(MutableBufferError::LengthOverflow)?;
313        if required_cap > self.layout.size() {
314            let new_capacity = required_cap
315                .checked_next_multiple_of(64)
316                .ok_or(MutableBufferError::LayoutError)?;
317            let new_capacity = std::cmp::max(new_capacity, self.layout.size().saturating_mul(2));
318            self.try_reallocate(new_capacity)?;
319        }
320        Ok(())
321    }
322    /// Ensures that this buffer has at least `self.len + additional` bytes. This re-allocates iff
323    /// `self.len + additional > capacity`.
324    /// # Example
325    /// ```
326    /// # use arrow_buffer::buffer::{Buffer, MutableBuffer};
327    /// let mut buffer = MutableBuffer::new(0);
328    /// buffer.reserve(253); // allocates for the first time
329    /// (0..253u8).for_each(|i| buffer.push(i)); // no reallocation
330    /// let buffer: Buffer = buffer.into();
331    /// assert_eq!(buffer.len(), 253);
332    /// ```
333    ///
334    /// # Panics
335    ///
336    /// Panics if `self.len + additional` overflows `usize`, or if the required capacity is too
337    /// large to round up to the next 64-byte boundary and construct a valid allocation layout.
338    // For performance reasons, this must be inlined so that the `if` is executed inside the caller, and not as an extra call that just
339    // exits.
340    #[inline(always)]
341    pub fn reserve(&mut self, additional: usize) {
342        self.try_reserve(additional)
343            .unwrap_or_else(|e| panic!("{e}"))
344    }
345
346    /// Fallible version of [`MutableBuffer::repeat_slice_n_times`].
347    pub fn try_repeat_slice_n_times<T: ArrowNativeType>(
348        &mut self,
349        slice_to_repeat: &[T],
350        repeat_count: usize,
351    ) -> Result<(), MutableBufferError> {
352        if repeat_count == 0 || slice_to_repeat.is_empty() {
353            return Ok(());
354        }
355        let bytes_per_copy = size_of_val(slice_to_repeat);
356        let total_bytes = repeat_count
357            .checked_mul(bytes_per_copy)
358            .ok_or(MutableBufferError::LengthOverflow)?;
359        self.len
360            .checked_add(total_bytes)
361            .ok_or(MutableBufferError::LengthOverflow)?;
362
363        // Ensure capacity
364        self.try_reserve(total_bytes)?;
365
366        // Save the length before we do all the copies to know where to start from
367        let length_before = self.len;
368
369        // Copy the initial slice once so we can use doubling strategy on it
370        self.try_extend_from_slice(slice_to_repeat)?;
371
372        // Number of times the slice was repeated
373        let mut already_repeated = 1usize;
374
375        // We will use doubling strategy to fill the buffer in log(repeat_count) steps
376        while already_repeated < repeat_count {
377            // How many slices can we copy in this iteration
378            // (either double what we have, or just the remaining ones)
379            let to_copy = already_repeated.min(repeat_count - already_repeated);
380            let byte_count = to_copy * bytes_per_copy;
381            unsafe {
382                // Get to the start of the data before we started copying anything
383                let src = self.data.as_ptr().add(length_before).cast_const();
384                // Go to the current location to copy to (end of current data)
385                let dst = self.data.as_ptr().add(self.len);
386                // SAFETY: the pointers are not overlapping as there is `byte_count` or less between them
387                std::ptr::copy_nonoverlapping(src, dst, byte_count);
388            }
389            // Advance the length by the amount of data we just copied (doubled)
390            self.len += byte_count;
391            already_repeated += to_copy;
392        }
393        Ok(())
394    }
395    /// Adding to this mutable buffer `slice_to_repeat` repeated `repeat_count` times.
396    ///
397    /// # Example
398    ///
399    /// ## Repeat the same string bytes multiple times
400    /// ```
401    /// # use arrow_buffer::buffer::MutableBuffer;
402    /// let mut buffer = MutableBuffer::new(0);
403    /// let bytes_to_repeat = b"ab";
404    /// buffer.repeat_slice_n_times(bytes_to_repeat, 3);
405    /// assert_eq!(buffer.as_slice(), b"ababab");
406    /// ```
407    ///
408    /// # Panics
409    ///
410    /// Panics if the repeated slice byte length overflows `usize`, if the resulting buffer
411    /// length overflows `usize`, or if reserving the required capacity fails for the same
412    /// reasons as [`MutableBuffer::reserve`].
413    pub fn repeat_slice_n_times<T: ArrowNativeType>(
414        &mut self,
415        slice_to_repeat: &[T],
416        repeat_count: usize,
417    ) {
418        self.try_repeat_slice_n_times(slice_to_repeat, repeat_count)
419            .unwrap_or_else(|e| panic!("{e}"))
420    }
421
422    #[cold]
423    fn try_reallocate(&mut self, capacity: usize) -> Result<(), MutableBufferError> {
424        let new_layout = Layout::from_size_align(capacity, self.layout.align())
425            .map_err(|_| MutableBufferError::LayoutError)?;
426
427        if new_layout.size() == 0 {
428            if self.layout.size() != 0 {
429                // Safety: data was allocated with layout
430                unsafe { std::alloc::dealloc(self.as_mut_ptr(), self.layout) };
431                self.layout = new_layout;
432            }
433            return Ok(());
434        }
435
436        let data = match self.layout.size() {
437            // Safety: new_layout is not empty
438            0 => unsafe { std::alloc::alloc(new_layout) },
439            // Safety: verified new layout is valid and not empty
440            _ => unsafe { std::alloc::realloc(self.as_mut_ptr(), self.layout, capacity) },
441        };
442        self.data = match NonNull::new(data) {
443            Some(ptr) => ptr,
444            None => return Err(MutableBufferError::AllocationError(new_layout)),
445        };
446        self.layout = new_layout;
447        #[cfg(feature = "pool")]
448        self.reservation.resize(self.layout.size());
449        Ok(())
450    }
451    /// Truncates this buffer to `len` bytes
452    ///
453    /// If `len` is greater than the buffer's current length, this has no effect
454    #[inline(always)]
455    pub fn truncate(&mut self, len: usize) {
456        if len > self.len {
457            return;
458        }
459        self.len = len;
460        #[cfg(feature = "pool")]
461        self.reservation.resize(self.len);
462    }
463
464    /// Fallible version of [`MutableBuffer::resize`].
465    #[inline]
466    pub fn try_resize(&mut self, new_len: usize, value: u8) -> Result<(), MutableBufferError> {
467        if new_len > self.len {
468            let diff = new_len - self.len;
469            self.try_reserve(diff)?;
470            // Safety: try_reserve ensured capacity >= new_len.
471            // write the value
472            unsafe { self.data.as_ptr().add(self.len).write_bytes(value, diff) };
473        }
474        // this truncates the buffer when new_len < self.len
475        self.len = new_len;
476        #[cfg(feature = "pool")]
477        self.reservation.resize(self.len);
478        Ok(())
479    }
480    /// Resizes the buffer, either truncating its contents (with no change in capacity), or
481    /// growing it (potentially reallocating it) and writing `value` in the newly available bytes.
482    /// # Example
483    /// ```
484    /// # use arrow_buffer::buffer::{Buffer, MutableBuffer};
485    /// let mut buffer = MutableBuffer::new(0);
486    /// buffer.resize(253, 2); // allocates for the first time
487    /// assert_eq!(buffer.as_slice()[252], 2u8);
488    /// ```
489    ///
490    /// # Panics
491    ///
492    /// Panics if growing the buffer requires reserving a capacity that fails for the same
493    /// reasons as [`MutableBuffer::reserve`].
494    // For performance reasons, this must be inlined so that the `if` is executed inside the caller, and not as an extra call that just
495    // exits.
496    #[inline(always)]
497    pub fn resize(&mut self, new_len: usize, value: u8) {
498        self.try_resize(new_len, value)
499            .unwrap_or_else(|e| panic!("{e}"))
500    }
501
502    /// Fallible version of [`MutableBuffer::shrink_to_fit`].
503    pub fn try_shrink_to_fit(&mut self) -> Result<(), MutableBufferError> {
504        let new_capacity = self
505            .len
506            .checked_next_multiple_of(64)
507            .ok_or(MutableBufferError::LayoutError)?;
508        if new_capacity < self.layout.size() {
509            self.try_reallocate(new_capacity)?;
510        }
511        Ok(())
512    }
513    /// Shrinks the capacity of the buffer as much as possible.
514    /// The new capacity will aligned to the nearest 64 bit alignment.
515    ///
516    /// # Example
517    /// ```
518    /// # use arrow_buffer::buffer::{Buffer, MutableBuffer};
519    /// // 2 cache lines
520    /// let mut buffer = MutableBuffer::new(128);
521    /// assert_eq!(buffer.capacity(), 128);
522    /// buffer.push(1);
523    /// buffer.push(2);
524    ///
525    /// buffer.shrink_to_fit();
526    /// assert!(buffer.capacity() >= 64 && buffer.capacity() < 128);
527    /// ```
528    ///
529    /// # Panics
530    ///
531    /// Panics if the current length is too large to round up to the next 64-byte boundary and
532    /// construct a valid allocation layout.
533    pub fn shrink_to_fit(&mut self) {
534        self.try_shrink_to_fit().unwrap_or_else(|e| panic!("{e}"))
535    }
536
537    /// Returns whether this buffer is empty or not.
538    #[inline]
539    pub const fn is_empty(&self) -> bool {
540        self.len == 0
541    }
542
543    /// Returns the length (the number of bytes written) in this buffer.
544    /// The invariant `buffer.len() <= buffer.capacity()` is always upheld.
545    #[inline]
546    pub const fn len(&self) -> usize {
547        self.len
548    }
549
550    /// Returns the total capacity in this buffer, in bytes.
551    ///
552    /// The invariant `buffer.len() <= buffer.capacity()` is always upheld.
553    #[inline]
554    pub const fn capacity(&self) -> usize {
555        self.layout.size()
556    }
557
558    /// Clear all existing data from this buffer.
559    pub fn clear(&mut self) {
560        self.len = 0;
561        #[cfg(feature = "pool")]
562        self.reservation.resize(self.len);
563    }
564
565    /// Returns the data stored in this buffer as a slice.
566    pub fn as_slice(&self) -> &[u8] {
567        self
568    }
569
570    /// Returns the data stored in this buffer as a mutable slice.
571    pub fn as_slice_mut(&mut self) -> &mut [u8] {
572        self
573    }
574
575    /// Returns a raw pointer to this buffer's internal memory
576    /// This pointer is guaranteed to be aligned along cache-lines.
577    #[inline]
578    pub const fn as_ptr(&self) -> *const u8 {
579        self.data.as_ptr()
580    }
581
582    /// Returns a mutable raw pointer to this buffer's internal memory
583    /// This pointer is guaranteed to be aligned along cache-lines.
584    #[inline]
585    pub fn as_mut_ptr(&mut self) -> *mut u8 {
586        self.data.as_ptr()
587    }
588
589    #[inline]
590    pub(super) fn into_buffer(self) -> Buffer {
591        let bytes = unsafe { Bytes::new(self.data, self.len, Deallocation::Standard(self.layout)) };
592        #[cfg(feature = "pool")]
593        bytes.reservation.replace(self.reservation.take());
594        std::mem::forget(self);
595        Buffer::from(bytes)
596    }
597
598    /// View this buffer as a mutable slice of a specific type.
599    ///
600    /// # Panics
601    ///
602    /// This function panics if the underlying buffer is not aligned correctly for type `T`, or
603    /// if its length is not a multiple of `size_of::<T>()`.
604    pub fn typed_data_mut<T: ArrowNativeType>(&mut self) -> &mut [T] {
605        // SAFETY
606        // ArrowNativeType is trivially transmutable, is sealed to prevent potentially incorrect
607        // implementation outside this crate, and this method checks alignment
608        let (prefix, offsets, suffix) = unsafe { self.as_slice_mut().align_to_mut::<T>() };
609        assert!(prefix.is_empty() && suffix.is_empty());
610        offsets
611    }
612
613    /// View buffer as a immutable slice of a specific type.
614    ///
615    /// # Panics
616    ///
617    /// This function panics if the underlying buffer is not aligned correctly for type `T`, or
618    /// if its length is not a multiple of `size_of::<T>()`.
619    pub fn typed_data<T: ArrowNativeType>(&self) -> &[T] {
620        // SAFETY
621        // ArrowNativeType is trivially transmutable, is sealed to prevent potentially incorrect
622        // implementation outside this crate, and this method checks alignment
623        let (prefix, offsets, suffix) = unsafe { self.as_slice().align_to::<T>() };
624        assert!(prefix.is_empty() && suffix.is_empty());
625        offsets
626    }
627
628    /// Fallible version of [`MutableBuffer::extend_from_slice`].
629    #[inline]
630    pub fn try_extend_from_slice<T: ArrowNativeType>(
631        &mut self,
632        items: &[T],
633    ) -> Result<(), MutableBufferError> {
634        let additional = mem::size_of_val(items);
635        self.try_reserve(additional)?;
636        unsafe {
637            // this assumes that `[ToByteSlice]` can be copied directly
638            // without calling `to_byte_slice` for each element,
639            // which is correct for all ArrowNativeType implementations.
640            let src = items.as_ptr().cast::<u8>();
641            let dst = self.data.as_ptr().add(self.len);
642            std::ptr::copy_nonoverlapping(src, dst, additional);
643        }
644        self.len += additional;
645        Ok(())
646    }
647    /// Extends this buffer from a slice of items that can be represented in bytes, increasing its capacity if needed.
648    /// # Example
649    /// ```
650    /// # use arrow_buffer::buffer::MutableBuffer;
651    /// let mut buffer = MutableBuffer::new(0);
652    /// buffer.extend_from_slice(&[2u32, 0]);
653    /// assert_eq!(buffer.len(), 8) // u32 has 4 bytes
654    /// ```
655    ///
656    /// # Panics
657    ///
658    /// Panics if extending the buffer requires reserving a capacity that fails for the same
659    /// reasons as [`MutableBuffer::reserve`].
660    #[inline]
661    pub fn extend_from_slice<T: ArrowNativeType>(&mut self, items: &[T]) {
662        self.try_extend_from_slice(items)
663            .unwrap_or_else(|e| panic!("{e}"))
664    }
665
666    /// Extends the buffer with a new item, increasing its capacity if needed.
667    /// # Example
668    /// ```
669    /// # use arrow_buffer::buffer::MutableBuffer;
670    /// let mut buffer = MutableBuffer::new(0);
671    /// buffer.push(256u32);
672    /// assert_eq!(buffer.len(), 4) // u32 has 4 bytes
673    /// ```
674    ///
675    /// # Panics
676    ///
677    /// Panics if extending the buffer requires reserving a capacity that fails for the same
678    /// reasons as [`MutableBuffer::reserve`].
679    #[inline]
680    pub fn push<T: ToByteSlice>(&mut self, item: T) {
681        let additional = std::mem::size_of::<T>();
682        self.reserve(additional);
683        unsafe {
684            let src = item.to_byte_slice().as_ptr();
685            let dst = self.data.as_ptr().add(self.len);
686            std::ptr::copy_nonoverlapping(src, dst, additional);
687        }
688        self.len += additional;
689    }
690
691    /// Extends the buffer with a new item, without checking for sufficient capacity
692    /// # Safety
693    /// Caller must ensure that the capacity()-len()>=`size_of<T>`()
694    #[inline]
695    pub unsafe fn push_unchecked<T: ToByteSlice>(&mut self, item: T) {
696        let additional = std::mem::size_of::<T>();
697        let src = item.to_byte_slice().as_ptr();
698        let dst = unsafe { self.data.as_ptr().add(self.len) };
699        unsafe { std::ptr::copy_nonoverlapping(src, dst, additional) };
700        self.len += additional;
701    }
702
703    /// Fallible version of [`MutableBuffer::extend_zeros`].
704    #[inline]
705    pub fn try_extend_zeros(&mut self, additional: usize) -> Result<(), MutableBufferError> {
706        let new_len = self
707            .len
708            .checked_add(additional)
709            .ok_or(MutableBufferError::LengthOverflow)?;
710        self.try_resize(new_len, 0)
711    }
712    /// Extends the buffer by `additional` bytes equal to `0u8`, incrementing its capacity if needed.
713    ///
714    /// # Panics
715    ///
716    /// Panics if `self.len + additional` overflows `usize`, or if growing the buffer requires
717    /// reserving a capacity that fails for the same reasons as [`MutableBuffer::reserve`].
718    #[inline]
719    pub fn extend_zeros(&mut self, additional: usize) {
720        self.try_extend_zeros(additional)
721            .unwrap_or_else(|e| panic!("{e}"))
722    }
723
724    /// # Safety
725    /// The caller must ensure that the buffer was properly initialized up to `len`.
726    ///
727    /// # Panics
728    ///
729    /// Panics if `len` exceeds the buffer capacity.
730    #[inline]
731    pub unsafe fn set_len(&mut self, len: usize) {
732        assert!(len <= self.capacity());
733        self.len = len;
734    }
735
736    /// Invokes `f` with values `0..len` collecting the boolean results into a new `MutableBuffer`
737    ///
738    /// This is similar to `from_trusted_len_iter_bool`, however, can be significantly faster
739    /// as it eliminates the conditional `Iterator::next`
740    ///
741    /// # Panics
742    ///
743    /// Panics if the backing storage for `len` bits cannot be allocated. Use
744    /// [`MutableBuffer::try_collect_bool`] for a fallible version.
745    #[inline]
746    pub fn collect_bool<F: FnMut(usize) -> bool>(len: usize, f: F) -> Self {
747        Self::try_collect_bool(len, f).unwrap_or_else(|e| panic!("{e}"))
748    }
749
750    /// Fallible version of [`MutableBuffer::collect_bool`].
751    ///
752    /// `len` is a bit count, so the reservation is `ceil(len / 64)` u64 slots. This function
753    /// returns an error if that much memory cannot be reserved up front.
754    #[inline]
755    pub fn try_collect_bool<F: FnMut(usize) -> bool>(
756        len: usize,
757        mut f: F,
758    ) -> Result<Self, MutableBufferError> {
759        let words = bit_util::ceil(len, 64);
760        let layout = Layout::array::<u64>(words).map_err(|_| MutableBufferError::LayoutError)?;
761        let mut buffer: Vec<u64> = Vec::new();
762        buffer
763            .try_reserve(words)
764            .map_err(|_| MutableBufferError::AllocationError(layout))?;
765
766        let chunks = len / 64;
767        let remainder = len % 64;
768        buffer.extend((0..chunks).map(|chunk| {
769            let mut packed = 0;
770            for bit_idx in 0..64 {
771                let i = bit_idx + chunk * 64;
772                packed |= (f(i) as u64) << bit_idx;
773            }
774
775            packed
776        }));
777
778        if remainder != 0 {
779            let mut packed = 0;
780            for bit_idx in 0..remainder {
781                let i = bit_idx + chunks * 64;
782                packed |= (f(i) as u64) << bit_idx;
783            }
784
785            buffer.push(packed)
786        }
787
788        let mut buffer: MutableBuffer = buffer.into();
789        buffer.truncate(bit_util::ceil(len, 8));
790        Ok(buffer)
791    }
792
793    /// Extends this buffer with boolean values.
794    ///
795    /// This requires `iter` to report an exact size via `size_hint`.
796    /// `offset` indicates the starting offset in bits in this buffer to begin writing to
797    /// and must be less than or equal to the current length of this buffer.
798    /// All bits not written to (but readable due to byte alignment) will be zeroed out.
799    ///
800    /// # Panics
801    ///
802    /// Panics if `iter` does not report an exact size via `size_hint`, or if it yields fewer
803    /// items than reported, or if extending the buffer requires reserving a capacity that fails
804    /// for the same reasons as [`MutableBuffer::reserve`].
805    ///
806    /// # Safety
807    /// Callers must ensure that `iter` reports an exact size via `size_hint`
808    /// and that `I::next()` does not panic, or `set_len` will leave the buffer
809    /// in an inconsistent state, exposing uninitialized/stale bytes as though
810    /// they were valid.
811    #[inline]
812    pub unsafe fn extend_bool_trusted_len<I: Iterator<Item = bool>>(
813        &mut self,
814        mut iter: I,
815        offset: usize,
816    ) {
817        let (lower, upper) = iter.size_hint();
818        let len = upper.expect("Iterator must have exact size_hint");
819        assert_eq!(lower, len, "Iterator must have exact size_hint");
820        debug_assert!(
821            offset <= self.len * 8,
822            "offset must be <= buffer length in bits"
823        );
824
825        if len == 0 {
826            return;
827        }
828
829        let start_len = offset;
830        let end_bit = start_len + len;
831
832        // SAFETY: we will initialize all newly exposed bytes before they are read
833        let new_len_bytes = bit_util::ceil(end_bit, 8);
834        if new_len_bytes > self.len {
835            self.reserve(new_len_bytes - self.len);
836            // SAFETY: caller will initialize all newly exposed bytes before they are read
837            unsafe { self.set_len(new_len_bytes) };
838        }
839
840        let slice = self.as_slice_mut();
841
842        let mut bit_idx = start_len;
843
844        // ---- Unaligned prefix: advance to the next 64-bit boundary ----
845        let misalignment = bit_idx & 63;
846        let prefix_bits = if misalignment == 0 {
847            0
848        } else {
849            (64 - misalignment).min(end_bit - bit_idx)
850        };
851
852        if prefix_bits != 0 {
853            let byte_start = bit_idx / 8;
854            let byte_end = bit_util::ceil(bit_idx + prefix_bits, 8);
855            let bit_offset = bit_idx % 8;
856
857            // Clear any newly-visible bits in the existing partial byte
858            if bit_offset != 0 {
859                let keep_mask = (1u8 << bit_offset).wrapping_sub(1);
860                slice[byte_start] &= keep_mask;
861            }
862
863            // Zero any new bytes we will partially fill in this prefix
864            let zero_from = if bit_offset == 0 {
865                byte_start
866            } else {
867                byte_start + 1
868            };
869            if byte_end > zero_from {
870                slice[zero_from..byte_end].fill(0);
871            }
872
873            for _ in 0..prefix_bits {
874                let v = iter.next().unwrap();
875                if v {
876                    let byte_idx = bit_idx / 8;
877                    let bit = bit_idx % 8;
878                    slice[byte_idx] |= 1 << bit;
879                }
880                bit_idx += 1;
881            }
882        }
883
884        if bit_idx < end_bit {
885            // ---- Aligned middle: write u64 chunks ----
886            debug_assert_eq!(bit_idx & 63, 0);
887            let remaining_bits = end_bit - bit_idx;
888            let chunks = remaining_bits / 64;
889
890            let words_start = bit_idx / 8;
891            let words_end = words_start + chunks * 8;
892            for dst in slice[words_start..words_end].as_chunks_mut::<8>().0 {
893                let mut packed: u64 = 0;
894                for i in 0..64 {
895                    packed |= (iter.next().unwrap() as u64) << i;
896                }
897                dst.copy_from_slice(&packed.to_le_bytes());
898                bit_idx += 64;
899            }
900
901            // ---- Unaligned suffix: remaining < 64 bits ----
902            let suffix_bits = end_bit - bit_idx;
903            if suffix_bits != 0 {
904                debug_assert_eq!(bit_idx % 8, 0);
905                let byte_start = bit_idx / 8;
906                let byte_end = bit_util::ceil(end_bit, 8);
907                slice[byte_start..byte_end].fill(0);
908
909                for _ in 0..suffix_bits {
910                    let v = iter.next().unwrap();
911                    if v {
912                        let byte_idx = bit_idx / 8;
913                        let bit = bit_idx % 8;
914                        slice[byte_idx] |= 1 << bit;
915                    }
916                    bit_idx += 1;
917                }
918            }
919        }
920
921        // Clear any unused bits in the last byte
922        let remainder = end_bit % 8;
923        if remainder != 0 {
924            let mask = (1u8 << remainder).wrapping_sub(1);
925            slice[bit_util::ceil(end_bit, 8) - 1] &= mask;
926        }
927
928        debug_assert_eq!(bit_idx, end_bit);
929    }
930
931    /// Register this [`MutableBuffer`] with the provided [`MemoryPool`]
932    ///
933    /// This claims the memory used by this buffer in the pool, allowing for
934    /// accurate accounting of memory usage. Any prior reservation will be
935    /// released so this works well when the buffer is being shared among
936    /// multiple arrays.
937    #[cfg(feature = "pool")]
938    pub fn claim(&self, pool: &dyn MemoryPool) {
939        self.reservation.claim(pool, self.capacity());
940    }
941}
942
943/// Creates a non-null pointer with alignment of [`ALIGNMENT`]
944///
945/// This is similar to [`NonNull::dangling`]
946#[inline]
947pub(crate) fn dangling_ptr() -> NonNull<u8> {
948    // SAFETY: ALIGNMENT is a non-zero usize which is then cast
949    // to a *mut u8. Therefore, `ptr` is not null and the conditions for
950    // calling new_unchecked() are respected.
951    #[cfg(miri)]
952    {
953        // Since miri implies a nightly rust version we can use the unstable strict_provenance feature
954        unsafe { NonNull::new_unchecked(std::ptr::without_provenance_mut(ALIGNMENT)) }
955    }
956    #[cfg(not(miri))]
957    {
958        unsafe { NonNull::new_unchecked(ALIGNMENT as *mut u8) }
959    }
960}
961
962impl<A: ArrowNativeType> Extend<A> for MutableBuffer {
963    #[inline]
964    fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
965        let iterator = iter.into_iter();
966        self.extend_from_iter(iterator)
967    }
968}
969
970impl<T: ArrowNativeType> From<Vec<T>> for MutableBuffer {
971    fn from(mut value: Vec<T>) -> Self {
972        // Safety
973        // Vec::as_mut_ptr guaranteed to not be null and ArrowNativeType are trivially transmutable
974        let data = unsafe { NonNull::new_unchecked(value.as_mut_ptr().cast()) };
975        let len = value.len() * mem::size_of::<T>();
976        // Safety
977        // Vec guaranteed to have a valid layout matching that of `Layout::array`
978        // This is based on `RawVec::current_memory`
979        let layout = unsafe { Layout::array::<T>(value.capacity()).unwrap_unchecked() };
980        mem::forget(value);
981        Self {
982            data,
983            len,
984            layout,
985            #[cfg(feature = "pool")]
986            reservation: TrackedReservation::default(),
987        }
988    }
989}
990
991impl MutableBuffer {
992    #[inline]
993    pub(super) fn extend_from_iter<T: ArrowNativeType, I: Iterator<Item = T>>(
994        &mut self,
995        mut iterator: I,
996    ) {
997        let item_size = std::mem::size_of::<T>();
998        let (lower, _) = iterator.size_hint();
999        let additional = lower * item_size;
1000        self.reserve(additional);
1001
1002        // this is necessary because of https://github.com/rust-lang/rust/issues/32155
1003        let mut len = SetLenOnDrop::new(&mut self.len);
1004        let mut dst = unsafe { self.data.as_ptr().add(len.local_len) };
1005        let capacity = self.layout.size();
1006
1007        while len.local_len + item_size <= capacity {
1008            if let Some(item) = iterator.next() {
1009                unsafe {
1010                    let src = item.to_byte_slice().as_ptr();
1011                    std::ptr::copy_nonoverlapping(src, dst, item_size);
1012                    dst = dst.add(item_size);
1013                }
1014                len.local_len += item_size;
1015            } else {
1016                break;
1017            }
1018        }
1019        drop(len);
1020
1021        iterator.for_each(|item| self.push(item));
1022    }
1023
1024    /// Creates a [`MutableBuffer`] from an [`Iterator`] with a trusted (upper) length.
1025    /// Prefer this to `collect` whenever possible, as it is faster ~60% faster.
1026    /// # Example
1027    /// ```
1028    /// # use arrow_buffer::buffer::MutableBuffer;
1029    /// let v = vec![1u32];
1030    /// let iter = v.iter().map(|x| x * 2);
1031    /// let buffer = unsafe { MutableBuffer::from_trusted_len_iter(iter) };
1032    /// assert_eq!(buffer.len(), 4) // u32 has 4 bytes
1033    /// ```
1034    ///
1035    /// # Panics
1036    ///
1037    /// Panics if the iterator does not report an upper bound via `size_hint`, or if the
1038    /// reported length does not match the number of items produced, or if allocating the
1039    /// required buffer fails for the same reasons as [`MutableBuffer::new`].
1040    ///
1041    /// # Safety
1042    /// This method assumes that the iterator's size is correct and is undefined behavior
1043    /// to use it on an iterator that reports an incorrect length.
1044    // This implementation is required for two reasons:
1045    // 1. there is no trait `TrustedLen` in stable rust and therefore
1046    //    we can't specialize `extend` for `TrustedLen` like `Vec` does.
1047    // 2. `from_trusted_len_iter` is faster.
1048    #[inline]
1049    pub unsafe fn from_trusted_len_iter<T: ArrowNativeType, I: Iterator<Item = T>>(
1050        iterator: I,
1051    ) -> Self {
1052        let item_size = std::mem::size_of::<T>();
1053        let (_, upper) = iterator.size_hint();
1054        let upper = upper.expect("from_trusted_len_iter requires an upper limit");
1055        let len = upper * item_size;
1056
1057        let mut buffer = MutableBuffer::new(len);
1058
1059        let mut dst = buffer.data.as_ptr();
1060        for item in iterator {
1061            // note how there is no reserve here (compared with `extend_from_iter`)
1062            let src = item.to_byte_slice().as_ptr();
1063            unsafe { std::ptr::copy_nonoverlapping(src, dst, item_size) };
1064            dst = unsafe { dst.add(item_size) };
1065        }
1066        assert_eq!(
1067            unsafe { dst.offset_from(buffer.data.as_ptr()) } as usize,
1068            len,
1069            "Trusted iterator length was not accurately reported"
1070        );
1071        buffer.len = len;
1072        buffer
1073    }
1074
1075    /// Creates a [`MutableBuffer`] from a boolean [`Iterator`] with a trusted (upper) length.
1076    /// # use arrow_buffer::buffer::MutableBuffer;
1077    /// # Example
1078    /// ```
1079    /// # use arrow_buffer::buffer::MutableBuffer;
1080    /// let v = vec![false, true, false];
1081    /// let iter = v.iter().map(|x| *x || true);
1082    /// let buffer = unsafe { MutableBuffer::from_trusted_len_iter_bool(iter) };
1083    /// assert_eq!(buffer.len(), 1) // 3 booleans have 1 byte
1084    /// ```
1085    ///
1086    /// # Panics
1087    ///
1088    /// Panics if the iterator does not report an upper bound via `size_hint`, or if it yields
1089    /// fewer items than reported.
1090    ///
1091    /// # Safety
1092    /// This method assumes that the iterator's size is correct and is undefined behavior
1093    /// to use it on an iterator that reports an incorrect length.
1094    // This implementation is required for two reasons:
1095    // 1. there is no trait `TrustedLen` in stable rust and therefore
1096    //    we can't specialize `extend` for `TrustedLen` like `Vec` does.
1097    // 2. `from_trusted_len_iter_bool` is faster.
1098    #[inline]
1099    pub unsafe fn from_trusted_len_iter_bool<I: Iterator<Item = bool>>(mut iterator: I) -> Self {
1100        let (_, upper) = iterator.size_hint();
1101        let len = upper.expect("from_trusted_len_iter requires an upper limit");
1102
1103        Self::collect_bool(len, |_| iterator.next().unwrap())
1104    }
1105
1106    /// Creates a [`MutableBuffer`] from an [`Iterator`] with a trusted (upper) length or errors
1107    /// if any of the items of the iterator is an error.
1108    /// Prefer this to `collect` whenever possible, as it is faster ~60% faster.
1109    ///
1110    /// # Errors
1111    ///
1112    /// Returns the first error yielded by the iterator.
1113    ///
1114    /// # Panics
1115    ///
1116    /// Note that unlike the [`Err`] cases, these panics are violations of the safety contract
1117    /// below, and are only checks that happen to be cheap enough to keep:
1118    ///
1119    /// Panics if the iterator does not report an upper bound via `size_hint`, or if the
1120    /// reported length does not match the number of items produced before an error-free finish,
1121    /// or if allocating the required buffer fails for the same reasons as
1122    /// [`MutableBuffer::new`].
1123    ///
1124    /// # Safety
1125    /// This method assumes that the iterator's size is correct and is undefined behavior
1126    /// to use it on an iterator that reports an incorrect length.
1127    #[inline]
1128    pub unsafe fn try_from_trusted_len_iter<
1129        E,
1130        T: ArrowNativeType,
1131        I: Iterator<Item = Result<T, E>>,
1132    >(
1133        iterator: I,
1134    ) -> Result<Self, E> {
1135        let item_size = std::mem::size_of::<T>();
1136        let (_, upper) = iterator.size_hint();
1137        let upper = upper.expect("try_from_trusted_len_iter requires an upper limit");
1138        let len = upper * item_size;
1139
1140        let mut buffer = MutableBuffer::new(len);
1141
1142        let mut dst = buffer.data.as_ptr();
1143        for item in iterator {
1144            let item = item?;
1145            // note how there is no reserve here (compared with `extend_from_iter`)
1146            let src = item.to_byte_slice().as_ptr();
1147            unsafe { std::ptr::copy_nonoverlapping(src, dst, item_size) };
1148            dst = unsafe { dst.add(item_size) };
1149        }
1150        // try_from_trusted_len_iter is instantiated a lot, so we extract part of it into a less
1151        // generic method to reduce compile time
1152        unsafe fn finalize_buffer(dst: *mut u8, buffer: &mut MutableBuffer, len: usize) {
1153            unsafe {
1154                assert_eq!(
1155                    dst.offset_from(buffer.data.as_ptr()) as usize,
1156                    len,
1157                    "Trusted iterator length was not accurately reported"
1158                );
1159                buffer.len = len;
1160            }
1161        }
1162        unsafe { finalize_buffer(dst, &mut buffer, len) };
1163        Ok(buffer)
1164    }
1165}
1166
1167impl Default for MutableBuffer {
1168    fn default() -> Self {
1169        Self::with_capacity(0)
1170    }
1171}
1172
1173impl std::ops::Deref for MutableBuffer {
1174    type Target = [u8];
1175
1176    fn deref(&self) -> &[u8] {
1177        unsafe { std::slice::from_raw_parts(self.as_ptr(), self.len) }
1178    }
1179}
1180
1181impl std::ops::DerefMut for MutableBuffer {
1182    fn deref_mut(&mut self) -> &mut [u8] {
1183        unsafe { std::slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
1184    }
1185}
1186
1187impl AsRef<[u8]> for &MutableBuffer {
1188    fn as_ref(&self) -> &[u8] {
1189        self.as_slice()
1190    }
1191}
1192
1193impl Drop for MutableBuffer {
1194    fn drop(&mut self) {
1195        if self.layout.size() != 0 {
1196            // Safety: data was allocated with standard allocator with given layout
1197            unsafe { std::alloc::dealloc(self.data.as_ptr().cast(), self.layout) };
1198        }
1199    }
1200}
1201
1202impl PartialEq for MutableBuffer {
1203    fn eq(&self, other: &MutableBuffer) -> bool {
1204        if self.len != other.len {
1205            return false;
1206        }
1207        if self.layout != other.layout {
1208            return false;
1209        }
1210        self.as_slice() == other.as_slice()
1211    }
1212}
1213
1214unsafe impl Sync for MutableBuffer {}
1215unsafe impl Send for MutableBuffer {}
1216
1217struct SetLenOnDrop<'a> {
1218    len: &'a mut usize,
1219    local_len: usize,
1220}
1221
1222impl<'a> SetLenOnDrop<'a> {
1223    #[inline]
1224    fn new(len: &'a mut usize) -> Self {
1225        SetLenOnDrop {
1226            local_len: *len,
1227            len,
1228        }
1229    }
1230}
1231
1232impl Drop for SetLenOnDrop<'_> {
1233    #[inline]
1234    fn drop(&mut self) {
1235        *self.len = self.local_len;
1236    }
1237}
1238
1239/// Creating a `MutableBuffer` instance by setting bits according to the boolean values
1240impl std::iter::FromIterator<bool> for MutableBuffer {
1241    fn from_iter<I>(iter: I) -> Self
1242    where
1243        I: IntoIterator<Item = bool>,
1244    {
1245        let mut iterator = iter.into_iter();
1246        let mut result = {
1247            let byte_capacity: usize = iterator.size_hint().0.saturating_add(7) / 8;
1248            MutableBuffer::new(byte_capacity)
1249        };
1250
1251        loop {
1252            let mut exhausted = false;
1253            let mut byte_accum: u8 = 0;
1254            let mut mask: u8 = 1;
1255
1256            //collect (up to) 8 bits into a byte
1257            while mask != 0 {
1258                if let Some(value) = iterator.next() {
1259                    byte_accum |= match value {
1260                        true => mask,
1261                        false => 0,
1262                    };
1263                    mask <<= 1;
1264                } else {
1265                    exhausted = true;
1266                    break;
1267                }
1268            }
1269
1270            // break if the iterator was exhausted before it provided a bool for this byte
1271            if exhausted && mask == 1 {
1272                break;
1273            }
1274
1275            //ensure we have capacity to write the byte
1276            if result.len() == result.capacity() {
1277                //no capacity for new byte, allocate 1 byte more (plus however many more the iterator advertises)
1278                let additional_byte_capacity = 1usize.saturating_add(
1279                    iterator.size_hint().0.saturating_add(7) / 8, //convert bit count to byte count, rounding up
1280                );
1281                result.reserve(additional_byte_capacity)
1282            }
1283
1284            // Soundness: capacity was allocated above
1285            unsafe { result.push_unchecked(byte_accum) };
1286            if exhausted {
1287                break;
1288            }
1289        }
1290        result
1291    }
1292}
1293
1294impl<T: ArrowNativeType> std::iter::FromIterator<T> for MutableBuffer {
1295    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1296        let mut buffer = Self::default();
1297        buffer.extend_from_iter(iter.into_iter());
1298        buffer
1299    }
1300}
1301
1302#[cfg(test)]
1303mod tests {
1304    use super::*;
1305
1306    #[test]
1307    fn test_mutable_new() {
1308        let buf = MutableBuffer::new(63);
1309        assert_eq!(64, buf.capacity());
1310        assert_eq!(0, buf.len());
1311        assert!(buf.is_empty());
1312    }
1313
1314    #[test]
1315    fn test_mutable_default() {
1316        let buf = MutableBuffer::default();
1317        assert_eq!(0, buf.capacity());
1318        assert_eq!(0, buf.len());
1319        assert!(buf.is_empty());
1320
1321        let mut buf = MutableBuffer::default();
1322        buf.extend_from_slice(b"hello");
1323        assert_eq!(5, buf.len());
1324        assert_eq!(b"hello", buf.as_slice());
1325    }
1326
1327    #[test]
1328    fn test_mutable_extend_from_slice() {
1329        let mut buf = MutableBuffer::new(100);
1330        buf.extend_from_slice(b"hello");
1331        assert_eq!(5, buf.len());
1332        assert_eq!(b"hello", buf.as_slice());
1333
1334        buf.extend_from_slice(b" world");
1335        assert_eq!(11, buf.len());
1336        assert_eq!(b"hello world", buf.as_slice());
1337
1338        buf.clear();
1339        assert_eq!(0, buf.len());
1340        buf.extend_from_slice(b"hello arrow");
1341        assert_eq!(11, buf.len());
1342        assert_eq!(b"hello arrow", buf.as_slice());
1343    }
1344
1345    #[test]
1346    fn mutable_extend_from_iter() {
1347        let mut buf = MutableBuffer::new(0);
1348        buf.extend(vec![1u32, 2]);
1349        assert_eq!(8, buf.len());
1350        assert_eq!(&[1u8, 0, 0, 0, 2, 0, 0, 0], buf.as_slice());
1351
1352        buf.extend(vec![3u32, 4]);
1353        assert_eq!(16, buf.len());
1354        assert_eq!(
1355            &[1u8, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0],
1356            buf.as_slice()
1357        );
1358    }
1359
1360    #[test]
1361    fn mutable_extend_from_iter_unaligned_u64() {
1362        let mut buf = MutableBuffer::new(16);
1363        buf.push(1_u8);
1364        buf.extend([1_u64]);
1365        assert_eq!(9, buf.len());
1366        assert_eq!(&[1u8, 1u8, 0, 0, 0, 0, 0, 0, 0], buf.as_slice());
1367    }
1368
1369    #[test]
1370    fn mutable_extend_from_slice_unaligned_u64() {
1371        let mut buf = MutableBuffer::new(16);
1372        buf.extend_from_slice(&[1_u8]);
1373        buf.extend_from_slice(&[1_u64]);
1374        assert_eq!(9, buf.len());
1375        assert_eq!(&[1u8, 1u8, 0, 0, 0, 0, 0, 0, 0], buf.as_slice());
1376    }
1377
1378    #[test]
1379    fn mutable_push_unaligned_u64() {
1380        let mut buf = MutableBuffer::new(16);
1381        buf.push(1_u8);
1382        buf.push(1_u64);
1383        assert_eq!(9, buf.len());
1384        assert_eq!(&[1u8, 1u8, 0, 0, 0, 0, 0, 0, 0], buf.as_slice());
1385    }
1386
1387    #[test]
1388    fn mutable_push_unchecked_unaligned_u64() {
1389        let mut buf = MutableBuffer::new(16);
1390        unsafe {
1391            buf.push_unchecked(1_u8);
1392            buf.push_unchecked(1_u64);
1393        }
1394        assert_eq!(9, buf.len());
1395        assert_eq!(&[1u8, 1u8, 0, 0, 0, 0, 0, 0, 0], buf.as_slice());
1396    }
1397
1398    #[test]
1399    fn test_from_trusted_len_iter() {
1400        let iter = vec![1u32, 2].into_iter();
1401        let buf = unsafe { MutableBuffer::from_trusted_len_iter(iter) };
1402        assert_eq!(8, buf.len());
1403        assert_eq!(&[1u8, 0, 0, 0, 2, 0, 0, 0], buf.as_slice());
1404    }
1405
1406    #[test]
1407    fn test_mutable_reserve() {
1408        let mut buf = MutableBuffer::new(1);
1409        assert_eq!(64, buf.capacity());
1410
1411        // Reserving a smaller capacity should have no effect.
1412        buf.reserve(10);
1413        assert_eq!(64, buf.capacity());
1414
1415        buf.reserve(80);
1416        assert_eq!(128, buf.capacity());
1417
1418        buf.reserve(129);
1419        assert_eq!(256, buf.capacity());
1420    }
1421
1422    #[test]
1423    fn test_mutable_resize() {
1424        let mut buf = MutableBuffer::new(1);
1425        assert_eq!(64, buf.capacity());
1426        assert_eq!(0, buf.len());
1427
1428        buf.resize(20, 0);
1429        assert_eq!(64, buf.capacity());
1430        assert_eq!(20, buf.len());
1431
1432        buf.resize(10, 0);
1433        assert_eq!(64, buf.capacity());
1434        assert_eq!(10, buf.len());
1435
1436        buf.resize(100, 0);
1437        assert_eq!(128, buf.capacity());
1438        assert_eq!(100, buf.len());
1439
1440        buf.resize(30, 0);
1441        assert_eq!(128, buf.capacity());
1442        assert_eq!(30, buf.len());
1443
1444        buf.resize(0, 0);
1445        assert_eq!(128, buf.capacity());
1446        assert_eq!(0, buf.len());
1447    }
1448
1449    #[test]
1450    fn test_mutable_into() {
1451        let mut buf = MutableBuffer::new(1);
1452        buf.extend_from_slice(b"aaaa bbbb cccc dddd");
1453        assert_eq!(19, buf.len());
1454        assert_eq!(64, buf.capacity());
1455        assert_eq!(b"aaaa bbbb cccc dddd", buf.as_slice());
1456
1457        let immutable_buf: Buffer = buf.into();
1458        assert_eq!(19, immutable_buf.len());
1459        assert_eq!(64, immutable_buf.capacity());
1460        assert_eq!(b"aaaa bbbb cccc dddd", immutable_buf.as_slice());
1461    }
1462
1463    #[test]
1464    fn test_mutable_equal() {
1465        let mut buf = MutableBuffer::new(1);
1466        let mut buf2 = MutableBuffer::new(1);
1467
1468        buf.extend_from_slice(&[0xaa]);
1469        buf2.extend_from_slice(&[0xaa, 0xbb]);
1470        assert_ne!(buf, buf2);
1471
1472        buf.extend_from_slice(&[0xbb]);
1473        assert_eq!(buf, buf2);
1474
1475        buf2.reserve(65);
1476        assert_ne!(buf, buf2);
1477    }
1478
1479    #[test]
1480    fn test_mutable_shrink_to_fit() {
1481        let mut buffer = MutableBuffer::new(128);
1482        assert_eq!(buffer.capacity(), 128);
1483        buffer.push(1);
1484        buffer.push(2);
1485
1486        buffer.shrink_to_fit();
1487        assert!(buffer.capacity() >= 64 && buffer.capacity() < 128);
1488    }
1489
1490    #[test]
1491    fn test_mutable_set_null_bits() {
1492        let mut buffer = MutableBuffer::new(8).with_bitset(8, true);
1493
1494        for i in 0..=buffer.capacity() {
1495            buffer.set_null_bits(i, 0);
1496            assert_eq!(buffer[..8], [255; 8][..]);
1497        }
1498
1499        buffer.set_null_bits(1, 4);
1500        assert_eq!(buffer[..8], [255, 0, 0, 0, 0, 255, 255, 255][..]);
1501    }
1502
1503    #[test]
1504    #[should_panic = "out of bounds for buffer of length"]
1505    fn test_mutable_set_null_bits_oob() {
1506        let mut buffer = MutableBuffer::new(64);
1507        buffer.set_null_bits(1, buffer.capacity());
1508    }
1509
1510    #[test]
1511    #[should_panic = "out of bounds for buffer of length"]
1512    fn test_mutable_set_null_bits_oob_by_overflow() {
1513        let mut buffer = MutableBuffer::new(0);
1514        buffer.set_null_bits(1, usize::MAX);
1515    }
1516
1517    #[test]
1518    fn from_iter() {
1519        let buffer = [1u16, 2, 3, 4].into_iter().collect::<MutableBuffer>();
1520        assert_eq!(buffer.len(), 4 * mem::size_of::<u16>());
1521        assert_eq!(buffer.as_slice(), &[1, 0, 2, 0, 3, 0, 4, 0]);
1522    }
1523
1524    #[test]
1525    #[should_panic(expected = "invalid allocation layout for requested capacity")]
1526    fn test_with_capacity_panics_above_max_capacity() {
1527        let max_capacity = isize::MAX as usize - (isize::MAX as usize % ALIGNMENT);
1528        let _ = MutableBuffer::with_capacity(max_capacity + 1);
1529    }
1530
1531    #[cfg(feature = "pool")]
1532    mod pool_tests {
1533        use super::*;
1534        use crate::pool::{MemoryPool, TrackingMemoryPool};
1535
1536        #[test]
1537        fn test_reallocate_with_pool() {
1538            let pool = TrackingMemoryPool::default();
1539            let mut buffer = MutableBuffer::with_capacity(100);
1540            buffer.claim(&pool);
1541
1542            // Initial capacity should be 128 (multiple of 64)
1543            assert_eq!(buffer.capacity(), 128);
1544            assert_eq!(pool.used(), 128);
1545
1546            // Reallocate to a larger size
1547            buffer.try_reallocate(200).unwrap();
1548
1549            // The capacity is exactly the requested size, not rounded up
1550            assert_eq!(buffer.capacity(), 200);
1551            assert_eq!(pool.used(), 200);
1552
1553            // Reallocate to a smaller size
1554            buffer.try_reallocate(50).unwrap();
1555
1556            // The capacity is exactly the requested size, not rounded up
1557            assert_eq!(buffer.capacity(), 50);
1558            assert_eq!(pool.used(), 50);
1559        }
1560
1561        #[test]
1562        fn test_truncate_with_pool() {
1563            let pool = TrackingMemoryPool::default();
1564            let mut buffer = MutableBuffer::with_capacity(100);
1565
1566            // Fill buffer with some data
1567            buffer.resize(80, 1);
1568            assert_eq!(buffer.len(), 80);
1569
1570            buffer.claim(&pool);
1571            assert_eq!(pool.used(), 128);
1572
1573            // Truncate buffer
1574            buffer.truncate(40);
1575            assert_eq!(buffer.len(), 40);
1576            assert_eq!(pool.used(), 40);
1577
1578            // Truncate to zero
1579            buffer.clear();
1580            assert_eq!(buffer.len(), 0);
1581            assert_eq!(pool.used(), 0);
1582        }
1583
1584        #[test]
1585        fn test_resize_with_pool() {
1586            let pool = TrackingMemoryPool::default();
1587            let mut buffer = MutableBuffer::with_capacity(100);
1588            buffer.claim(&pool);
1589
1590            // Initial state
1591            assert_eq!(buffer.len(), 0);
1592            assert_eq!(pool.used(), 128);
1593
1594            // Resize to increase length
1595            buffer.resize(50, 1);
1596            assert_eq!(buffer.len(), 50);
1597            assert_eq!(pool.used(), 50);
1598
1599            // Resize to increase length beyond capacity
1600            buffer.resize(150, 1);
1601            assert_eq!(buffer.len(), 150);
1602            assert_eq!(buffer.capacity(), 256);
1603            assert_eq!(pool.used(), 150);
1604
1605            // Resize to decrease length
1606            buffer.resize(30, 1);
1607            assert_eq!(buffer.len(), 30);
1608            assert_eq!(pool.used(), 30);
1609        }
1610
1611        #[test]
1612        fn test_buffer_lifecycle_with_pool() {
1613            let pool = TrackingMemoryPool::default();
1614
1615            // Create a buffer with memory reservation
1616            let mut mutable = MutableBuffer::with_capacity(100);
1617            mutable.resize(80, 1);
1618            mutable.claim(&pool);
1619
1620            // Memory reservation is based on capacity when using claim()
1621            assert_eq!(pool.used(), 128);
1622
1623            // Convert to immutable Buffer
1624            let buffer = mutable.into_buffer();
1625
1626            // Memory reservation should be preserved
1627            assert_eq!(pool.used(), 128);
1628
1629            // Drop the buffer and the reservation should be released
1630            drop(buffer);
1631            assert_eq!(pool.used(), 0);
1632        }
1633    }
1634
1635    fn create_expected_repeated_slice<T: ArrowNativeType>(
1636        slice_to_repeat: &[T],
1637        repeat_count: usize,
1638    ) -> Buffer {
1639        let mut expected = MutableBuffer::new(size_of_val(slice_to_repeat) * repeat_count);
1640        for _ in 0..repeat_count {
1641            // Not using push_slice_repeated as this is the function under test
1642            expected.extend_from_slice(slice_to_repeat);
1643        }
1644        expected.into()
1645    }
1646
1647    // Helper to test a specific repeat count with various slice sizes
1648    fn test_repeat_count<T: ArrowNativeType + PartialEq + std::fmt::Debug>(
1649        repeat_count: usize,
1650        test_data: &[T],
1651    ) {
1652        let mut buffer = MutableBuffer::new(0);
1653        buffer.repeat_slice_n_times(test_data, repeat_count);
1654
1655        let expected = create_expected_repeated_slice(test_data, repeat_count);
1656        let result: Buffer = buffer.into();
1657
1658        assert_eq!(
1659            result,
1660            expected,
1661            "Failed for repeat_count={}, slice_len={}",
1662            repeat_count,
1663            test_data.len()
1664        );
1665    }
1666
1667    #[test]
1668    fn test_repeat_slice_count_edge_cases() {
1669        // Empty slice
1670        test_repeat_count(100, &[] as &[i32]);
1671
1672        // Zero repeats
1673        test_repeat_count(0, &[1i32, 2, 3]);
1674    }
1675
1676    #[test]
1677    #[should_panic(expected = "buffer length overflow")]
1678    fn test_repeat_slice_count_multiply_overflow() {
1679        let mut buffer = MutableBuffer::new(0);
1680        buffer.repeat_slice_n_times(&[0_u64], usize::MAX / mem::size_of::<u64>() + 1);
1681    }
1682
1683    #[test]
1684    #[should_panic(expected = "buffer length overflow")]
1685    fn test_repeat_slice_count_len_overflow() {
1686        let mut buffer = MutableBuffer::new(0);
1687        buffer.push(0_u8);
1688        buffer.repeat_slice_n_times(&[0_u8], usize::MAX);
1689    }
1690
1691    #[test]
1692    fn test_small_repeats_counts() {
1693        // test any special implementation for small repeat counts
1694        let data = &[1u8, 2, 3, 4, 5];
1695
1696        for _ in 1..=10 {
1697            test_repeat_count(2, data);
1698        }
1699    }
1700
1701    #[test]
1702    fn test_different_size_of_i32_repeat_slice() {
1703        let data: &[i32] = &[1, 2, 3];
1704        let data_with_single_item: &[i32] = &[42];
1705
1706        for data in &[data, data_with_single_item] {
1707            for item in 1..=9 {
1708                let base_repeat_count = 2_usize.pow(item);
1709                test_repeat_count(base_repeat_count - 1, data);
1710                test_repeat_count(base_repeat_count, data);
1711                test_repeat_count(base_repeat_count + 1, data);
1712            }
1713        }
1714    }
1715
1716    #[test]
1717    fn test_different_size_of_u8_repeat_slice() {
1718        let data: &[u8] = &[1, 2, 3];
1719        let data_with_single_item: &[u8] = &[10];
1720
1721        for data in &[data, data_with_single_item] {
1722            for item in 1..=9 {
1723                let base_repeat_count = 2_usize.pow(item);
1724                test_repeat_count(base_repeat_count - 1, data);
1725                test_repeat_count(base_repeat_count, data);
1726                test_repeat_count(base_repeat_count + 1, data);
1727            }
1728        }
1729    }
1730
1731    #[test]
1732    fn test_different_size_of_u16_repeat_slice() {
1733        let data: &[u16] = &[1, 2, 3];
1734        let data_with_single_item: &[u16] = &[10];
1735
1736        for data in &[data, data_with_single_item] {
1737            for item in 1..=9 {
1738                let base_repeat_count = 2_usize.pow(item);
1739                test_repeat_count(base_repeat_count - 1, data);
1740                test_repeat_count(base_repeat_count, data);
1741                test_repeat_count(base_repeat_count + 1, data);
1742            }
1743        }
1744    }
1745
1746    #[test]
1747    fn test_various_slice_lengths() {
1748        // Test different slice lengths with same repeat pattern
1749        let repeat_count = 37; // Arbitrary non-power-of-2
1750
1751        // Single element
1752        test_repeat_count(repeat_count, &[42i32]);
1753
1754        // Small slices
1755        test_repeat_count(repeat_count, &[1i32, 2]);
1756        test_repeat_count(repeat_count, &[1i32, 2, 3]);
1757        test_repeat_count(repeat_count, &[1i32, 2, 3, 4]);
1758        test_repeat_count(repeat_count, &[1i32, 2, 3, 4, 5]);
1759
1760        // Larger slices
1761        let data_10: Vec<i32> = (0..10).collect();
1762        test_repeat_count(repeat_count, &data_10);
1763
1764        let data_100: Vec<i32> = (0..100).collect();
1765        test_repeat_count(repeat_count, &data_100);
1766
1767        let data_1000: Vec<i32> = (0..1000).collect();
1768        test_repeat_count(repeat_count, &data_1000);
1769    }
1770
1771    #[test]
1772    #[should_panic(expected = "invalid allocation layout for requested capacity")]
1773    fn test_mutable_new_capacity_overflow() {
1774        // Tests overflow during initial allocation
1775        let _ = MutableBuffer::new(usize::MAX - 10);
1776    }
1777
1778    #[test]
1779    #[should_panic(expected = "buffer length overflow")]
1780    fn test_mutable_reserve_overflow() {
1781        // Tests overflow during growth (checked_add)
1782        let mut buf = MutableBuffer::new(1);
1783        buf.push(1u8);
1784        buf.reserve(usize::MAX);
1785    }
1786}