Skip to main content

arrow_buffer/buffer/
immutable.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5use std::alloc::Layout;
6use std::fmt::Debug;
7use std::ptr::NonNull;
8use std::sync::Arc;
9
10use crate::BufferBuilder;
11use crate::alloc::{Allocation, Deallocation};
12use crate::util::bit_chunk_iterator::{BitChunks, UnalignedBitChunk};
13use crate::{SliceOutOfBoundsError, bit_util, bytes::Bytes, native::ArrowNativeType};
14
15#[cfg(feature = "pool")]
16use crate::pool::MemoryPool;
17
18use super::{MutableBuffer, ScalarBuffer};
19
20/// A contiguous memory region that can be shared with other buffers and across
21/// thread boundaries that stores Arrow data.
22///
23/// `Buffer`s can be sliced and cloned without copying the underlying data and can
24/// be created from memory allocated by non-Rust sources such as C/C++.
25///
26/// # Example: Create a `Buffer` from a `Vec` (without copying)
27/// ```
28/// # use arrow_buffer::Buffer;
29/// let vec: Vec<u32> = vec![1, 2, 3];
30/// let buffer = Buffer::from(vec);
31/// ```
32///
33/// # Example: Convert a `Buffer` to a `Vec` (without copying)
34///
35/// Use [`Self::into_vec`] to convert a `Buffer` back into a `Vec` if there are
36/// no other references and the types are aligned correctly.
37/// ```
38/// # use arrow_buffer::Buffer;
39/// # let vec: Vec<u32> = vec![1, 2, 3];
40/// # let buffer = Buffer::from(vec);
41/// // convert the buffer back into a Vec of u32
42/// // note this will fail if the buffer is shared or not aligned correctly
43/// let vec: Vec<u32> = buffer.into_vec().unwrap();
44/// ```
45///
46/// # Example: Create a `Buffer` from a [`bytes::Bytes`] (without copying)
47///
48/// [`bytes::Bytes`] is a common type in the Rust ecosystem for shared memory
49/// regions. You can create a buffer from a `Bytes` instance using the `From`
50/// implementation, also without copying.
51///
52/// ```
53/// # use arrow_buffer::Buffer;
54/// let bytes = bytes::Bytes::from("hello");
55/// let buffer = Buffer::from(bytes);
56///```
57///
58/// # Example: Create a [`bytes::Bytes`] from a `Buffer` (without copying)
59///
60/// [`bytes::Bytes::from_owner`] can also wrap a `Buffer` again without copying.
61/// This made generically available via a `From` implementation.
62///
63/// ```
64/// # use arrow_buffer::Buffer;
65/// # let bytes = bytes::Bytes::from("hello");
66/// # let buffer = Buffer::from(bytes);
67/// let bytes = bytes::Bytes::from(buffer);
68///```
69#[derive(Clone, Debug)]
70pub struct Buffer {
71    /// the internal byte buffer.
72    data: Arc<Bytes>,
73
74    /// Pointer into `data` valid
75    ///
76    /// We store a pointer instead of an offset to avoid pointer arithmetic
77    /// which causes LLVM to fail to vectorise code correctly
78    ptr: *const u8,
79
80    /// Byte length of the buffer.
81    ///
82    /// Must be less than or equal to `data.len()`
83    length: usize,
84}
85
86impl Default for Buffer {
87    #[inline]
88    fn default() -> Self {
89        MutableBuffer::default().into()
90    }
91}
92
93impl PartialEq for Buffer {
94    fn eq(&self, other: &Self) -> bool {
95        self.as_slice().eq(other.as_slice())
96    }
97}
98
99impl Eq for Buffer {}
100
101unsafe impl Send for Buffer where Bytes: Send {}
102unsafe impl Sync for Buffer where Bytes: Sync {}
103
104impl Buffer {
105    /// Returns the offset, in bytes, of `Self::ptr` to `Self::data`
106    ///
107    /// self.ptr and self.data can be different after slicing or advancing the buffer.
108    pub fn ptr_offset(&self) -> usize {
109        // Safety: `ptr` is always in bounds of `data`.
110        unsafe { self.ptr.offset_from(self.data.ptr().as_ptr()) as usize }
111    }
112
113    /// Returns the pointer to the start of the buffer without the offset.
114    pub fn data_ptr(&self) -> NonNull<u8> {
115        self.data.ptr()
116    }
117
118    /// Returns the number of strong references to the buffer.
119    ///
120    /// This method is safe but if the buffer is shared across multiple threads
121    /// the underlying value could change between calling this method and using
122    /// the result.
123    pub fn strong_count(&self) -> usize {
124        Arc::strong_count(&self.data)
125    }
126
127    /// Create a [`Buffer`] from the provided [`Vec`] without copying
128    #[inline]
129    pub fn from_vec<T: ArrowNativeType>(vec: Vec<T>) -> Self {
130        MutableBuffer::from(vec).into()
131    }
132
133    /// Initializes a [Buffer] from a slice of items.
134    pub fn from_slice_ref<U: ArrowNativeType, T: AsRef<[U]>>(items: T) -> Self {
135        let slice = items.as_ref();
136        let capacity = std::mem::size_of_val(slice);
137        let mut buffer = MutableBuffer::with_capacity(capacity);
138        buffer.extend_from_slice(slice);
139        buffer.into()
140    }
141
142    /// Creates a buffer from an existing memory region.
143    ///
144    /// Ownership of the memory is tracked via reference counting
145    /// and the memory will be freed using the `drop` method of
146    /// [crate::alloc::Allocation] when the reference count reaches zero.
147    ///
148    /// # Arguments
149    ///
150    /// * `ptr` - Pointer to raw parts
151    /// * `len` - Length of raw parts in **bytes**
152    /// * `owner` - A [crate::alloc::Allocation] which is responsible for freeing that data
153    ///
154    /// # Safety
155    ///
156    /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` bytes
157    pub unsafe fn from_custom_allocation(
158        ptr: NonNull<u8>,
159        len: usize,
160        owner: Arc<dyn Allocation>,
161    ) -> Self {
162        unsafe { Buffer::build_with_arguments(ptr, len, Deallocation::Custom(owner, len)) }
163    }
164
165    /// Auxiliary method to create a new Buffer
166    unsafe fn build_with_arguments(
167        ptr: NonNull<u8>,
168        len: usize,
169        deallocation: Deallocation,
170    ) -> Self {
171        let bytes = unsafe { Bytes::new(ptr, len, deallocation) };
172        let ptr = bytes.as_ptr();
173        Buffer {
174            ptr,
175            data: Arc::new(bytes),
176            length: len,
177        }
178    }
179
180    /// Returns the number of bytes in the buffer
181    #[inline]
182    pub fn len(&self) -> usize {
183        self.length
184    }
185
186    /// Returns the capacity of this buffer.
187    /// For externally owned buffers, this returns zero
188    #[inline]
189    pub fn capacity(&self) -> usize {
190        self.data.capacity()
191    }
192
193    /// Tries to shrink the capacity of the buffer as much as possible, freeing unused memory.
194    ///
195    /// If the buffer is shared, this is a no-op.
196    ///
197    /// If the memory was allocated with a custom allocator, this is a no-op.
198    ///
199    /// If the capacity is already less than or equal to the desired capacity, this is a no-op.
200    ///
201    /// The memory region will be reallocated using `std::alloc::realloc`.
202    pub fn shrink_to_fit(&mut self) {
203        let offset = self.ptr_offset();
204        let is_empty = self.is_empty();
205        let desired_capacity = if is_empty {
206            0
207        } else {
208            // For realloc to work, we cannot free the elements before the offset
209            offset + self.len()
210        };
211        if desired_capacity < self.capacity()
212            && let Some(bytes) = Arc::get_mut(&mut self.data)
213        {
214            bytes
215                .try_realloc(desired_capacity, |base| {
216                    self.ptr = if is_empty {
217                        base.as_ptr()
218                    } else {
219                        // SAFETY: we kept all elements leading up to the offset
220                        unsafe { base.as_ptr().add(offset) }
221                    };
222                })
223                .ok(); // Failure to reallocate is fine; we just failed to free up memory.
224        }
225    }
226
227    /// Returns true if the buffer is empty.
228    #[inline]
229    pub fn is_empty(&self) -> bool {
230        self.length == 0
231    }
232
233    /// Returns the byte slice stored in this buffer
234    pub fn as_slice(&self) -> &[u8] {
235        unsafe { std::slice::from_raw_parts(self.ptr, self.length) }
236    }
237
238    pub(crate) fn deallocation(&self) -> &Deallocation {
239        self.data.deallocation()
240    }
241
242    /// Returns a new [Buffer] that is a slice of this buffer starting at `offset`.
243    ///
244    /// This function is `O(1)` and does not copy any data, allowing the
245    /// same memory region to be shared between buffers.
246    ///
247    /// # Panics
248    ///
249    /// Panics iff `offset` is larger than `len`.
250    pub fn slice(&self, offset: usize) -> Self {
251        let mut s = self.clone();
252        s.advance(offset);
253        s
254    }
255
256    /// Increases the offset of this buffer by `offset`
257    ///
258    /// # Panics
259    ///
260    /// Panics iff `offset` is larger than `len`.
261    #[inline]
262    pub fn advance(&mut self, offset: usize) {
263        assert!(
264            offset <= self.length,
265            "the offset of the new Buffer cannot exceed the existing length: offset={} length={}",
266            offset,
267            self.length
268        );
269        self.length -= offset;
270        // Safety:
271        // This cannot overflow as
272        // `self.offset + self.length < self.data.len()`
273        // `offset < self.length`
274        self.ptr = unsafe { self.ptr.add(offset) };
275    }
276
277    /// Returns a new [Buffer] that is a slice of this buffer starting at `offset`,
278    /// with `length` bytes.
279    ///
280    /// This function is `O(1)` and does not copy any data, allowing the same
281    /// memory region to be shared between buffers.
282    ///
283    /// # Panics
284    /// Panics iff `(offset + length)` is larger than the existing length.
285    pub fn slice_with_length(&self, offset: usize, length: usize) -> Self {
286        self.try_slice_with_length(offset, length)
287            .unwrap_or_else(|e| panic!("{e}"))
288    }
289
290    /// Returns a new [Buffer] that is a slice of this buffer starting at `offset`,
291    /// with `length` bytes, or an error if `(offset + length)` is larger than the
292    /// existing length.
293    ///
294    /// This is the non-panicking version of [`Self::slice_with_length`].
295    pub fn try_slice_with_length(
296        &self,
297        offset: usize,
298        length: usize,
299    ) -> Result<Self, SliceOutOfBoundsError> {
300        if offset.saturating_add(length) > self.length {
301            return Err(SliceOutOfBoundsError::new(offset, length, self.length));
302        }
303        // Safety:
304        // offset + length <= self.length
305        let ptr = unsafe { self.ptr.add(offset) };
306        Ok(Self {
307            data: self.data.clone(),
308            ptr,
309            length,
310        })
311    }
312
313    /// Returns a pointer to the start of this buffer.
314    ///
315    /// Note that this should be used cautiously, and the returned pointer should not be
316    /// stored anywhere, to avoid dangling pointers.
317    #[inline]
318    pub fn as_ptr(&self) -> *const u8 {
319        self.ptr
320    }
321
322    /// View buffer as a slice of a specific type.
323    ///
324    /// # Panics
325    ///
326    /// This function panics if the underlying buffer is not aligned
327    /// correctly for type `T`.
328    pub fn typed_data<T: ArrowNativeType>(&self) -> &[T] {
329        // SAFETY
330        // ArrowNativeType is trivially transmutable, is sealed to prevent potentially incorrect
331        // implementation outside this crate, and this method checks alignment
332        let (prefix, offsets, suffix) = unsafe { self.as_slice().align_to::<T>() };
333        assert!(prefix.is_empty() && suffix.is_empty());
334        offsets
335    }
336
337    /// Returns a slice of this buffer starting at a certain bit offset.
338    /// If the offset is byte-aligned the returned buffer is a shallow clone,
339    /// otherwise a new buffer is allocated and filled with a copy of the bits in the range.
340    ///
341    /// # Panics
342    ///
343    /// Panics if `offset + len` is larger than the length of this buffer in bits
344    pub fn bit_slice(&self, offset: usize, len: usize) -> Self {
345        if offset.is_multiple_of(8) {
346            return self.slice_with_length(offset / 8, bit_util::ceil(len, 8));
347        }
348
349        let chunks = self.bit_chunks(offset, len);
350
351        let buffer: Vec<u64> = if chunks.remainder_len() > 0 {
352            chunks.iter().chain(Some(chunks.remainder_bits())).collect()
353        } else {
354            chunks.iter().collect()
355        };
356        let mut buffer = Buffer::from_vec(buffer);
357        // Update length to be byte-aligned
358        buffer.length = bit_util::ceil(len, 8);
359        buffer
360    }
361
362    /// Returns a `BitChunks` instance which can be used to iterate over this buffers bits
363    /// in larger chunks and starting at arbitrary bit offsets.
364    /// Note that both `offset` and `length` are measured in bits.
365    pub fn bit_chunks(&self, offset: usize, len: usize) -> BitChunks<'_> {
366        BitChunks::new(self.as_slice(), offset, len)
367    }
368
369    /// Returns the number of 1-bits in this buffer, starting from `offset` with `length` bits
370    /// inspected. Note that both `offset` and `length` are measured in bits.
371    pub fn count_set_bits_offset(&self, offset: usize, len: usize) -> usize {
372        UnalignedBitChunk::new(self.as_slice(), offset, len).count_ones()
373    }
374
375    /// Returns `MutableBuffer` for mutating the buffer if this buffer is not shared or sliced.
376    /// Returns `Err` if this is shared or the [`Self::ptr_offset`] is greater than 0 or its allocation is from an external source or
377    /// it is not allocated with alignment [`ALIGNMENT`]
378    ///
379    /// # Example: Creating a [`MutableBuffer`] from a [`Buffer`]
380    /// ```
381    /// # use arrow_buffer::buffer::{Buffer, MutableBuffer};
382    /// let buffer: Buffer = Buffer::from(&[1u8, 2, 3, 4][..]);
383    /// // Only possible to convert a Buffer into a MutableBuffer if uniquely owned
384    /// // (i.e., there are no other references to it).
385    /// let mut mutable_buffer = match buffer.into_mutable() {
386    ///    Ok(mutable) => mutable,
387    ///    Err(orig_buffer) => {
388    ///      panic!("buffer was not uniquely owned");
389    ///    }
390    /// };
391    /// mutable_buffer.push(5u8);
392    /// let buffer = Buffer::from(mutable_buffer);
393    /// assert_eq!(buffer.as_slice(), &[1u8, 2, 3, 4, 5])
394    /// ```
395    ///
396    /// [`ALIGNMENT`]: crate::alloc::ALIGNMENT
397    pub fn into_mutable(self) -> Result<MutableBuffer, Self> {
398        let ptr = self.ptr;
399        let length = self.length;
400
401        // Disallow converting when the offset is not 0 because we can't start a mutable from offset
402        let res = if self.ptr_offset() > 0 {
403            Err(self.data)
404        } else {
405            Arc::try_unwrap(self.data)
406        };
407
408        res.and_then(|bytes| {
409            // The pointer of underlying buffer should not be offset.
410            assert_eq!(ptr, bytes.ptr().as_ptr());
411            MutableBuffer::from_bytes(bytes).map_err(Arc::new)
412        })
413        .map_err(|bytes| Buffer {
414            data: bytes,
415            ptr,
416            length,
417        })
418        .map(|mut mutable| {
419            // We need to update the length since in case we are converting sliced buffer we need to return MutableBuffer with the same length
420            // SAFETY: this is safe as the length is coming from valid Buffer (this) and it is guaranteed to be less than the underlying data buffer
421            unsafe { mutable.set_len(length) };
422            mutable
423        })
424    }
425
426    /// Converts self into a `Vec`, if possible.
427    ///
428    /// This can be used to reuse / mutate the underlying data.
429    ///
430    /// With the `pool` feature enabled, a successful conversion releases the buffer's
431    /// memory reservation. The returned `Vec` is not tracked by the memory pool.
432    ///
433    /// # Errors
434    ///
435    /// Returns `Err(self)` if
436    /// 1. The buffer does not have the same [`Layout`] as the destination Vec
437    /// 2. The buffer contains a non-zero offset
438    /// 3. The buffer is shared
439    pub fn into_vec<T: ArrowNativeType>(self) -> Result<Vec<T>, Self> {
440        let layout = match self.data.deallocation() {
441            Deallocation::Standard(l) => l,
442            Deallocation::Custom(..) => return Err(self),
443        };
444
445        if self.ptr != self.data.as_ptr() {
446            return Err(self); // Data is offset
447        }
448
449        let v_capacity = layout.size() / std::mem::size_of::<T>();
450        match Layout::array::<T>(v_capacity) {
451            Ok(expected) if layout == &expected => {}
452            _ => return Err(self), // Incorrect layout
453        }
454
455        let length = self.length;
456        let ptr = self.ptr;
457        let v_len = self.length / std::mem::size_of::<T>();
458
459        Arc::try_unwrap(self.data)
460            .map(|bytes| unsafe {
461                let ptr = bytes.ptr().as_ptr().cast();
462                #[cfg(feature = "pool")]
463                drop(bytes.reservation.take());
464                std::mem::forget(bytes);
465                // Safety
466                // Verified that bytes layout matches that of Vec
467                Vec::from_raw_parts(ptr, v_len, v_capacity)
468            })
469            .map_err(|bytes| Buffer {
470                data: bytes,
471                ptr,
472                length,
473            })
474    }
475
476    /// Returns true if this [`Buffer`] is equal to `other`, using pointer comparisons
477    /// to determine buffer equality. This is cheaper than `PartialEq::eq` but may
478    /// return false when the arrays are logically equal
479    #[inline]
480    pub fn ptr_eq(&self, other: &Self) -> bool {
481        self.ptr == other.ptr && self.length == other.length
482    }
483
484    /// Register this [`Buffer`] with the provided [`MemoryPool`]
485    ///
486    /// This claims the memory used by this buffer in the pool, allowing for
487    /// accurate accounting of memory usage. Any prior reservation will be
488    /// released so this works well when the buffer is being shared among
489    /// multiple arrays.
490    #[cfg(feature = "pool")]
491    pub fn claim(&self, pool: &dyn MemoryPool) {
492        self.data.claim(pool)
493    }
494}
495
496/// Note that here we deliberately do not implement
497/// `impl<T: AsRef<[u8]>> From<T> for Buffer`
498/// As it would accept `Buffer::from(vec![...])` that would cause an unexpected copy.
499/// Instead, we ask user to be explicit when copying is occurring, e.g., `Buffer::from(vec![...].to_byte_slice())`.
500/// For zero-copy conversion, user should use `Buffer::from_vec(vec![...])`.
501///
502/// Since we removed impl for `AsRef<u8>`, we added the following three specific implementations to reduce API breakage.
503/// See <https://github.com/apache/arrow-rs/issues/6033> for more discussion on this.
504impl From<&[u8]> for Buffer {
505    fn from(p: &[u8]) -> Self {
506        Self::from_slice_ref(p)
507    }
508}
509
510impl<const N: usize> From<[u8; N]> for Buffer {
511    fn from(p: [u8; N]) -> Self {
512        Self::from_slice_ref(p)
513    }
514}
515
516impl<const N: usize> From<&[u8; N]> for Buffer {
517    fn from(p: &[u8; N]) -> Self {
518        Self::from_slice_ref(p)
519    }
520}
521
522impl<T: ArrowNativeType> From<Vec<T>> for Buffer {
523    fn from(value: Vec<T>) -> Self {
524        Self::from_vec(value)
525    }
526}
527
528impl<T: ArrowNativeType> From<ScalarBuffer<T>> for Buffer {
529    fn from(value: ScalarBuffer<T>) -> Self {
530        value.into_inner()
531    }
532}
533
534/// Convert from internal `Bytes` (not [`bytes::Bytes`]) to `Buffer`
535impl From<Bytes> for Buffer {
536    #[inline]
537    fn from(bytes: Bytes) -> Self {
538        let length = bytes.len();
539        let ptr = bytes.as_ptr();
540        Self {
541            data: Arc::new(bytes),
542            ptr,
543            length,
544        }
545    }
546}
547
548/// Convert from [`bytes::Bytes`], not internal `Bytes` to `Buffer`
549impl From<bytes::Bytes> for Buffer {
550    fn from(bytes: bytes::Bytes) -> Self {
551        let bytes: Bytes = bytes.into();
552        Self::from(bytes)
553    }
554}
555
556/// Convert a `Buffer` into a [`bytes::Bytes`]
557impl From<Buffer> for bytes::Bytes {
558    fn from(buffer: Buffer) -> Self {
559        Self::from_owner(buffer)
560    }
561}
562
563/// Create a `Buffer` instance by storing the boolean values into the buffer
564impl FromIterator<bool> for Buffer {
565    fn from_iter<I>(iter: I) -> Self
566    where
567        I: IntoIterator<Item = bool>,
568    {
569        MutableBuffer::from_iter(iter).into()
570    }
571}
572
573impl std::ops::Deref for Buffer {
574    type Target = [u8];
575
576    fn deref(&self) -> &[u8] {
577        unsafe { std::slice::from_raw_parts(self.as_ptr(), self.len()) }
578    }
579}
580
581impl AsRef<[u8]> for Buffer {
582    fn as_ref(&self) -> &[u8] {
583        self.as_slice()
584    }
585}
586
587impl From<MutableBuffer> for Buffer {
588    #[inline]
589    fn from(buffer: MutableBuffer) -> Self {
590        buffer.into_buffer()
591    }
592}
593
594impl<T: ArrowNativeType> From<BufferBuilder<T>> for Buffer {
595    fn from(mut value: BufferBuilder<T>) -> Self {
596        value.finish()
597    }
598}
599
600impl Buffer {
601    /// Creates a [`Buffer`] from an [`Iterator`] with a trusted (upper) length.
602    ///
603    /// Prefer this to `collect` whenever possible, as it is ~60% faster.
604    ///
605    /// # Example
606    /// ```
607    /// # use arrow_buffer::buffer::Buffer;
608    /// let v = vec![1u32];
609    /// let iter = v.iter().map(|x| x * 2);
610    /// let buffer = unsafe { Buffer::from_trusted_len_iter(iter) };
611    /// assert_eq!(buffer.len(), 4) // u32 has 4 bytes
612    /// ```
613    /// # Safety
614    /// This method assumes that the iterator's size is correct and is undefined behavior
615    /// to use it on an iterator that reports an incorrect length.
616    // This implementation is required for two reasons:
617    // 1. there is no trait `TrustedLen` in stable rust and therefore
618    //    we can't specialize `extend` for `TrustedLen` like `Vec` does.
619    // 2. `from_trusted_len_iter` is faster.
620    #[inline]
621    pub unsafe fn from_trusted_len_iter<T: ArrowNativeType, I: Iterator<Item = T>>(
622        iterator: I,
623    ) -> Self {
624        unsafe { MutableBuffer::from_trusted_len_iter(iterator).into() }
625    }
626
627    /// Creates a [`Buffer`] from an [`Iterator`] with a trusted (upper) length or errors
628    /// if any of the items of the iterator is an error.
629    /// Prefer this to `collect` whenever possible, as it is ~60% faster.
630    /// # Safety
631    /// This method assumes that the iterator's size is correct and is undefined behavior
632    /// to use it on an iterator that reports an incorrect length.
633    #[inline]
634    pub unsafe fn try_from_trusted_len_iter<
635        E,
636        T: ArrowNativeType,
637        I: Iterator<Item = Result<T, E>>,
638    >(
639        iterator: I,
640    ) -> Result<Self, E> {
641        unsafe { Ok(MutableBuffer::try_from_trusted_len_iter(iterator)?.into()) }
642    }
643}
644
645impl<T: ArrowNativeType> FromIterator<T> for Buffer {
646    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
647        let vec = Vec::from_iter(iter);
648        Buffer::from_vec(vec)
649    }
650}
651
652#[cfg(test)]
653mod tests {
654    use crate::i256;
655    #[cfg(feature = "pool")]
656    use crate::pool::{MemoryPool, TrackingMemoryPool};
657    use std::panic::{RefUnwindSafe, UnwindSafe};
658    use std::thread;
659
660    use super::*;
661
662    #[test]
663    fn test_buffer_data_equality() {
664        let buf1 = Buffer::from(&[0, 1, 2, 3, 4]);
665        let buf2 = Buffer::from(&[0, 1, 2, 3, 4]);
666        assert_eq!(buf1, buf2);
667
668        // slice with same offset and same length should still preserve equality
669        let buf3 = buf1.slice(2);
670        assert_ne!(buf1, buf3);
671        let buf4 = buf2.slice_with_length(2, 3);
672        assert_eq!(buf3, buf4);
673
674        // Different capacities should still preserve equality
675        let mut buf2 = MutableBuffer::new(65);
676        buf2.extend_from_slice(&[0u8, 1, 2, 3, 4]);
677
678        let buf2 = buf2.into();
679        assert_eq!(buf1, buf2);
680
681        // unequal because of different elements
682        let buf2 = Buffer::from(&[0, 0, 2, 3, 4]);
683        assert_ne!(buf1, buf2);
684
685        // unequal because of different length
686        let buf2 = Buffer::from(&[0, 1, 2, 3]);
687        assert_ne!(buf1, buf2);
688    }
689
690    #[test]
691    fn test_from_raw_parts() {
692        let buf = Buffer::from(&[0, 1, 2, 3, 4]);
693        assert_eq!(5, buf.len());
694        assert!(!buf.as_ptr().is_null());
695        assert_eq!([0, 1, 2, 3, 4], buf.as_slice());
696    }
697
698    #[test]
699    fn test_from_vec() {
700        let buf = Buffer::from(&[0, 1, 2, 3, 4]);
701        assert_eq!(5, buf.len());
702        assert!(!buf.as_ptr().is_null());
703        assert_eq!([0, 1, 2, 3, 4], buf.as_slice());
704    }
705
706    #[test]
707    fn test_copy() {
708        let buf = Buffer::from(&[0, 1, 2, 3, 4]);
709        let buf2 = buf;
710        assert_eq!(5, buf2.len());
711        assert_eq!(64, buf2.capacity());
712        assert!(!buf2.as_ptr().is_null());
713        assert_eq!([0, 1, 2, 3, 4], buf2.as_slice());
714    }
715
716    #[test]
717    fn test_try_slice_with_length() {
718        let buf = Buffer::from(&[2, 4, 6, 8, 10]);
719        assert_eq!(
720            [4, 6, 8],
721            buf.try_slice_with_length(1, 3).unwrap().as_slice()
722        );
723        assert!(buf.try_slice_with_length(5, 0).unwrap().is_empty());
724        assert!(buf.try_slice_with_length(6, 0).is_err());
725        assert!(buf.try_slice_with_length(usize::MAX, 1).is_err());
726        assert_eq!(
727            buf.try_slice_with_length(3, 3).unwrap_err().to_string(),
728            "the offset of the new Buffer cannot exceed the existing length: slice offset=3 length=3 selflen=5"
729        );
730
731        let buf2 = buf.slice(2);
732        assert_eq!(
733            [8, 10],
734            buf2.try_slice_with_length(1, 2).unwrap().as_slice()
735        );
736        assert!(buf2.try_slice_with_length(1, 3).is_err());
737    }
738
739    #[test]
740    fn test_slice() {
741        let buf = Buffer::from(&[2, 4, 6, 8, 10]);
742        let buf2 = buf.slice(2);
743
744        assert_eq!([6, 8, 10], buf2.as_slice());
745        assert_eq!(3, buf2.len());
746        assert_eq!(unsafe { buf.as_ptr().add(2) }, buf2.as_ptr());
747
748        let buf3 = buf2.slice_with_length(1, 2);
749        assert_eq!([8, 10], buf3.as_slice());
750        assert_eq!(2, buf3.len());
751        assert_eq!(unsafe { buf.as_ptr().add(3) }, buf3.as_ptr());
752
753        let buf4 = buf.slice(5);
754        let empty_slice: [u8; 0] = [];
755        assert_eq!(empty_slice, buf4.as_slice());
756        assert_eq!(0, buf4.len());
757        assert!(buf4.is_empty());
758        assert_eq!(buf2.slice_with_length(2, 1).as_slice(), &[10]);
759    }
760
761    #[test]
762    fn test_shrink_to_fit() {
763        let original = Buffer::from(&[0, 1, 2, 3, 4, 5, 6, 7]);
764        assert_eq!(original.as_slice(), &[0, 1, 2, 3, 4, 5, 6, 7]);
765        assert_eq!(original.capacity(), 64);
766
767        let slice = original.slice_with_length(2, 3);
768        drop(original); // Make sure the buffer isn't shared (or shrink_to_fit won't work)
769        assert_eq!(slice.as_slice(), &[2, 3, 4]);
770        assert_eq!(slice.capacity(), 64);
771
772        let mut shrunk = slice;
773        shrunk.shrink_to_fit();
774        assert_eq!(shrunk.as_slice(), &[2, 3, 4]);
775        assert_eq!(shrunk.capacity(), 5); // shrink_to_fit is allowed to keep the elements before the offset
776
777        // Test that we can handle empty slices:
778        let empty_slice = shrunk.slice_with_length(1, 0);
779        drop(shrunk); // Make sure the buffer isn't shared (or shrink_to_fit won't work)
780        assert_eq!(empty_slice.as_slice(), &[]);
781        assert_eq!(empty_slice.capacity(), 5);
782
783        let mut shrunk_empty = empty_slice;
784        shrunk_empty.shrink_to_fit();
785        assert_eq!(shrunk_empty.as_slice(), &[]);
786        assert_eq!(shrunk_empty.capacity(), 0);
787    }
788
789    #[test]
790    #[should_panic(expected = "the offset of the new Buffer cannot exceed the existing length")]
791    fn test_slice_offset_out_of_bound() {
792        let buf = Buffer::from(&[2, 4, 6, 8, 10]);
793        buf.slice(6);
794    }
795
796    #[test]
797    fn test_access_concurrently() {
798        let buffer = Buffer::from([1, 2, 3, 4, 5]);
799        let buffer2 = buffer.clone();
800        assert_eq!([1, 2, 3, 4, 5], buffer.as_slice());
801
802        let buffer_copy = thread::spawn(move || {
803            // access buffer in another thread.
804            buffer
805        })
806        .join();
807
808        assert!(buffer_copy.is_ok());
809        assert_eq!(buffer2, buffer_copy.ok().unwrap());
810    }
811
812    macro_rules! check_as_typed_data {
813        ($input: expr, $native_t: ty) => {{
814            let buffer = Buffer::from_slice_ref($input);
815            let slice: &[$native_t] = buffer.typed_data::<$native_t>();
816            assert_eq!($input, slice);
817        }};
818    }
819
820    #[test]
821    #[expect(clippy::float_cmp_const)]
822    fn test_as_typed_data() {
823        check_as_typed_data!(&[1i8, 3i8, 6i8], i8);
824        check_as_typed_data!(&[1u8, 3u8, 6u8], u8);
825        check_as_typed_data!(&[1i16, 3i16, 6i16], i16);
826        check_as_typed_data!(&[1i32, 3i32, 6i32], i32);
827        check_as_typed_data!(&[1i64, 3i64, 6i64], i64);
828        check_as_typed_data!(&[1u16, 3u16, 6u16], u16);
829        check_as_typed_data!(&[1u32, 3u32, 6u32], u32);
830        check_as_typed_data!(&[1u64, 3u64, 6u64], u64);
831        check_as_typed_data!(&[1f32, 3f32, 6f32], f32);
832        check_as_typed_data!(&[1f64, 3f64, 6f64], f64);
833    }
834
835    #[test]
836    fn test_count_bits() {
837        assert_eq!(0, Buffer::from(&[0b00000000]).count_set_bits_offset(0, 8));
838        assert_eq!(8, Buffer::from(&[0b11111111]).count_set_bits_offset(0, 8));
839        assert_eq!(3, Buffer::from(&[0b00001101]).count_set_bits_offset(0, 8));
840        assert_eq!(
841            6,
842            Buffer::from(&[0b01001001, 0b01010010]).count_set_bits_offset(0, 16)
843        );
844        assert_eq!(
845            16,
846            Buffer::from(&[0b11111111, 0b11111111]).count_set_bits_offset(0, 16)
847        );
848    }
849
850    #[test]
851    fn test_count_bits_slice() {
852        assert_eq!(
853            0,
854            Buffer::from(&[0b11111111, 0b00000000])
855                .slice(1)
856                .count_set_bits_offset(0, 8)
857        );
858        assert_eq!(
859            8,
860            Buffer::from(&[0b11111111, 0b11111111])
861                .slice_with_length(1, 1)
862                .count_set_bits_offset(0, 8)
863        );
864        assert_eq!(
865            3,
866            Buffer::from(&[0b11111111, 0b11111111, 0b00001101])
867                .slice(2)
868                .count_set_bits_offset(0, 8)
869        );
870        assert_eq!(
871            6,
872            Buffer::from(&[0b11111111, 0b01001001, 0b01010010])
873                .slice_with_length(1, 2)
874                .count_set_bits_offset(0, 16)
875        );
876        assert_eq!(
877            16,
878            Buffer::from(&[0b11111111, 0b11111111, 0b11111111, 0b11111111])
879                .slice(2)
880                .count_set_bits_offset(0, 16)
881        );
882    }
883
884    #[test]
885    fn test_count_bits_offset_slice() {
886        assert_eq!(8, Buffer::from(&[0b11111111]).count_set_bits_offset(0, 8));
887        assert_eq!(3, Buffer::from(&[0b11111111]).count_set_bits_offset(0, 3));
888        assert_eq!(5, Buffer::from(&[0b11111111]).count_set_bits_offset(3, 5));
889        assert_eq!(1, Buffer::from(&[0b11111111]).count_set_bits_offset(3, 1));
890        assert_eq!(0, Buffer::from(&[0b11111111]).count_set_bits_offset(8, 0));
891        assert_eq!(2, Buffer::from(&[0b01010101]).count_set_bits_offset(0, 3));
892        assert_eq!(
893            16,
894            Buffer::from(&[0b11111111, 0b11111111]).count_set_bits_offset(0, 16)
895        );
896        assert_eq!(
897            10,
898            Buffer::from(&[0b11111111, 0b11111111]).count_set_bits_offset(0, 10)
899        );
900        assert_eq!(
901            10,
902            Buffer::from(&[0b11111111, 0b11111111]).count_set_bits_offset(3, 10)
903        );
904        assert_eq!(
905            8,
906            Buffer::from(&[0b11111111, 0b11111111]).count_set_bits_offset(8, 8)
907        );
908        assert_eq!(
909            5,
910            Buffer::from(&[0b11111111, 0b11111111]).count_set_bits_offset(11, 5)
911        );
912        assert_eq!(
913            0,
914            Buffer::from(&[0b11111111, 0b11111111]).count_set_bits_offset(16, 0)
915        );
916        assert_eq!(
917            2,
918            Buffer::from(&[0b01101101, 0b10101010]).count_set_bits_offset(7, 5)
919        );
920        assert_eq!(
921            4,
922            Buffer::from(&[0b01101101, 0b10101010]).count_set_bits_offset(7, 9)
923        );
924    }
925
926    #[test]
927    fn test_unwind_safe() {
928        fn assert_unwind_safe<T: RefUnwindSafe + UnwindSafe>() {}
929        assert_unwind_safe::<Buffer>()
930    }
931
932    #[test]
933    fn test_from_foreign_vec() {
934        let mut vector = vec![1_i32, 2, 3, 4, 5];
935        let buffer = unsafe {
936            Buffer::from_custom_allocation(
937                NonNull::new_unchecked(vector.as_mut_ptr().cast::<u8>()),
938                vector.len() * std::mem::size_of::<i32>(),
939                Arc::new(vector),
940            )
941        };
942
943        let slice = buffer.typed_data::<i32>();
944        assert_eq!(slice, &[1, 2, 3, 4, 5]);
945
946        let buffer = buffer.slice(std::mem::size_of::<i32>());
947
948        let slice = buffer.typed_data::<i32>();
949        assert_eq!(slice, &[2, 3, 4, 5]);
950    }
951
952    #[test]
953    #[should_panic(expected = "the offset of the new Buffer cannot exceed the existing length")]
954    fn slice_overflow() {
955        let buffer = Buffer::from(MutableBuffer::from_len_zeroed(12));
956        buffer.slice_with_length(2, usize::MAX);
957    }
958
959    #[test]
960    #[cfg(feature = "pool")]
961    fn test_into_vec_releases_reservation() {
962        let pool = TrackingMemoryPool::default();
963        let buffer = Buffer::from_vec(vec![1_u8, 2, 3]);
964        buffer.claim(&pool);
965        assert_eq!(pool.used(), 3);
966
967        let shared = buffer.clone();
968        let buffer = buffer.into_vec::<u8>().unwrap_err();
969        assert_eq!(pool.used(), 3);
970        drop(shared);
971
972        let ptr = buffer.as_ptr();
973        let values = buffer.into_vec::<u8>().unwrap();
974        assert_eq!(values.as_ptr(), ptr);
975        assert_eq!(values, [1, 2, 3]);
976        assert_eq!(pool.used(), 0);
977
978        drop(values);
979        assert_eq!(pool.used(), 0);
980    }
981
982    #[test]
983    fn test_vec_interop() {
984        // Test empty vec
985        let a: Vec<i128> = Vec::new();
986        let b = Buffer::from_vec(a);
987        b.into_vec::<i128>().unwrap();
988
989        // Test vec with capacity
990        let a: Vec<i128> = Vec::with_capacity(20);
991        let b = Buffer::from_vec(a);
992        let back = b.into_vec::<i128>().unwrap();
993        assert_eq!(back.len(), 0);
994        assert_eq!(back.capacity(), 20);
995
996        // Test vec with values
997        let mut a: Vec<i128> = Vec::with_capacity(3);
998        a.extend_from_slice(&[1, 2, 3]);
999        let b = Buffer::from_vec(a);
1000        let back = b.into_vec::<i128>().unwrap();
1001        assert_eq!(back.len(), 3);
1002        assert_eq!(back.capacity(), 3);
1003
1004        // Test vec with values and spare capacity
1005        let mut a: Vec<i128> = Vec::with_capacity(20);
1006        a.extend_from_slice(&[1, 4, 7, 8, 9, 3, 6]);
1007        let b = Buffer::from_vec(a);
1008        let back = b.into_vec::<i128>().unwrap();
1009        assert_eq!(back.len(), 7);
1010        assert_eq!(back.capacity(), 20);
1011
1012        // Test incorrect alignment
1013        let a: Vec<i128> = Vec::new();
1014        let b = Buffer::from_vec(a);
1015        let b = b.into_vec::<i32>().unwrap_err();
1016        b.into_vec::<i8>().unwrap_err();
1017
1018        // Test convert between types with same alignment
1019        // This is an implementation quirk, but isn't harmful
1020        // as ArrowNativeType are trivially transmutable
1021        let a: Vec<i64> = vec![1, 2, 3, 4];
1022        let b = Buffer::from_vec(a);
1023        let back = b.into_vec::<u64>().unwrap();
1024        assert_eq!(back.len(), 4);
1025        assert_eq!(back.capacity(), 4);
1026
1027        // i256 has the same layout as i128 so this is valid
1028        let mut b: Vec<i128> = Vec::with_capacity(4);
1029        b.extend_from_slice(&[1, 2, 3, 4]);
1030        let b = Buffer::from_vec(b);
1031        let back = b.into_vec::<i256>().unwrap();
1032        assert_eq!(back.len(), 2);
1033        assert_eq!(back.capacity(), 2);
1034
1035        // Invalid layout
1036        let b: Vec<i128> = vec![1, 2, 3];
1037        let b = Buffer::from_vec(b);
1038        b.into_vec::<i256>().unwrap_err();
1039
1040        // Invalid layout
1041        let mut b: Vec<i128> = Vec::with_capacity(5);
1042        b.extend_from_slice(&[1, 2, 3, 4]);
1043        let b = Buffer::from_vec(b);
1044        b.into_vec::<i256>().unwrap_err();
1045
1046        // Truncates length
1047        // This is an implementation quirk, but isn't harmful
1048        let mut b: Vec<i128> = Vec::with_capacity(4);
1049        b.extend_from_slice(&[1, 2, 3]);
1050        let b = Buffer::from_vec(b);
1051        let back = b.into_vec::<i256>().unwrap();
1052        assert_eq!(back.len(), 1);
1053        assert_eq!(back.capacity(), 2);
1054
1055        // Cannot use aligned allocation
1056        let b = Buffer::from(MutableBuffer::new(10));
1057        let b = b.into_vec::<u8>().unwrap_err();
1058        b.into_vec::<u64>().unwrap_err();
1059
1060        // Test slicing
1061        let mut a: Vec<i128> = Vec::with_capacity(20);
1062        a.extend_from_slice(&[1, 4, 7, 8, 9, 3, 6]);
1063        let b = Buffer::from_vec(a);
1064        let slice = b.slice_with_length(0, 64);
1065
1066        // Shared reference fails
1067        let slice = slice.into_vec::<i128>().unwrap_err();
1068        drop(b);
1069
1070        // Succeeds as no outstanding shared reference
1071        let back = slice.into_vec::<i128>().unwrap();
1072        assert_eq!(&back, &[1, 4, 7, 8]);
1073        assert_eq!(back.capacity(), 20);
1074
1075        // Slicing by non-multiple length truncates
1076        let mut a: Vec<i128> = Vec::with_capacity(8);
1077        a.extend_from_slice(&[1, 4, 7, 3]);
1078
1079        let b = Buffer::from_vec(a);
1080        let slice = b.slice_with_length(0, 34);
1081        drop(b);
1082
1083        let back = slice.into_vec::<i128>().unwrap();
1084        assert_eq!(&back, &[1, 4]);
1085        assert_eq!(back.capacity(), 8);
1086
1087        // Offset prevents conversion
1088        let a: Vec<u32> = vec![1, 3, 4, 6];
1089        let b = Buffer::from_vec(a).slice(2);
1090        b.into_vec::<u32>().unwrap_err();
1091
1092        let b = MutableBuffer::new(16).into_buffer();
1093        let b = b.into_vec::<u8>().unwrap_err(); // Invalid layout
1094        let b = b.into_vec::<u32>().unwrap_err(); // Invalid layout
1095        b.into_mutable().unwrap();
1096
1097        let b = Buffer::from_vec(vec![1_u32, 3, 5]);
1098        let b = b.into_mutable().unwrap();
1099        let b = Buffer::from(b);
1100        let b = b.into_vec::<u32>().unwrap();
1101        assert_eq!(b, &[1, 3, 5]);
1102    }
1103
1104    #[test]
1105    #[should_panic(expected = "capacity overflow")]
1106    fn test_from_iter_overflow() {
1107        let iter_len = usize::MAX / std::mem::size_of::<u64>() + 1;
1108        let _ = Buffer::from_iter(std::iter::repeat_n(0_u64, iter_len));
1109    }
1110
1111    #[test]
1112    fn bit_slice_length_preserved() {
1113        // Create a boring buffer
1114        let buf = Buffer::from_iter(std::iter::repeat_n(true, 64));
1115
1116        let assert_preserved = |offset: usize, len: usize| {
1117            let new_buf = buf.bit_slice(offset, len);
1118            assert_eq!(new_buf.len(), bit_util::ceil(len, 8));
1119
1120            // if the offset is not byte-aligned, we have to create a deep copy to a new buffer
1121            // (since the `offset` value inside a Buffer is byte-granular, not bit-granular), so
1122            // checking the offset should always return 0 if so. If the offset IS byte-aligned, we
1123            // want to make sure it doesn't unnecessarily create a deep copy.
1124            if offset.is_multiple_of(8) {
1125                assert_eq!(new_buf.ptr_offset(), offset / 8);
1126            } else {
1127                assert_eq!(new_buf.ptr_offset(), 0);
1128            }
1129        };
1130
1131        // go through every available value for offset
1132        for o in 0..=64 {
1133            // and go through every length that could accompany that offset - we can't have a
1134            // situation where offset + len > 64, because that would go past the end of the buffer,
1135            // so we use the map to ensure it's in range.
1136            for l in (o..=64).map(|l| l - o) {
1137                // and we just want to make sure every one of these keeps its offset and length
1138                // when needed
1139                assert_preserved(o, l);
1140            }
1141        }
1142    }
1143
1144    #[test]
1145    fn test_strong_count() {
1146        let buffer = Buffer::from_iter(std::iter::repeat_n(0_u8, 100));
1147        assert_eq!(buffer.strong_count(), 1);
1148
1149        let buffer2 = buffer.clone();
1150        assert_eq!(buffer.strong_count(), 2);
1151
1152        let buffer3 = buffer2.clone();
1153        assert_eq!(buffer.strong_count(), 3);
1154
1155        drop(buffer);
1156        assert_eq!(buffer2.strong_count(), 2);
1157        assert_eq!(buffer3.strong_count(), 2);
1158
1159        // Strong count does not increase on move
1160        let capture = move || {
1161            assert_eq!(buffer3.strong_count(), 2);
1162        };
1163
1164        capture();
1165        assert_eq!(buffer2.strong_count(), 2);
1166
1167        drop(capture);
1168        assert_eq!(buffer2.strong_count(), 1);
1169    }
1170
1171    #[test]
1172    fn into_mutable_should_return_error_for_sliced_owned_buffer_when_ptr_offset_is_not_0() {
1173        let original_buffer_data = [1_u8, 2, 3, 4, 5, 6, 7, 8];
1174        for (slice_from, slice_length) in [
1175            (original_buffer_data.len(), 0),
1176            (2, 4),
1177            (2, original_buffer_data.len() - 2),
1178        ] {
1179            let buffer = Buffer::from(original_buffer_data);
1180            let sliced = buffer.slice_with_length(slice_from, slice_length);
1181            drop(buffer); // Keep only 1 owner
1182            assert_ne!(sliced.ptr_offset(), 0);
1183
1184            sliced
1185                .into_mutable()
1186                .expect_err("should not convert sliced buffer when ptr_offset is not 0");
1187        }
1188    }
1189
1190    #[test]
1191    fn into_mutable_should_allow_converting_sliced_owned_buffer_when_ptr_offset_is_0() {
1192        let original_buffer_data = [1_u8, 2, 3, 4, 5, 6, 7, 8];
1193        for slice_length in [0, original_buffer_data.len() - 2] {
1194            let buffer = Buffer::from(original_buffer_data);
1195            let sliced = buffer.slice_with_length(0, slice_length);
1196            drop(buffer); // Keep only 1 owner
1197            assert_eq!(sliced.ptr_offset(), 0);
1198
1199            let original_ptr = sliced.data_ptr();
1200
1201            let mutable = sliced
1202                        .into_mutable()
1203                        .unwrap_or_else(|_| panic!("should allow converting to mutable when not sliced from end when slice_length is {slice_length}"));
1204
1205            let buffer_back: Buffer = mutable.into();
1206            assert_eq!(buffer_back.data_ptr(), original_ptr);
1207
1208            let expected = Buffer::from(original_buffer_data).slice_with_length(0, slice_length);
1209            assert_eq!(buffer_back.as_slice(), expected.as_slice());
1210        }
1211    }
1212
1213    #[test]
1214    #[cfg(feature = "pool")]
1215    fn test_shrink_to_fit_panicking_reservation() {
1216        use std::panic::{AssertUnwindSafe, catch_unwind};
1217
1218        use crate::pool::{MemoryPool, MemoryReservation};
1219
1220        #[derive(Debug)]
1221        struct PanicPool;
1222
1223        #[derive(Debug)]
1224        struct PanicReservation {
1225            panicked: bool,
1226        }
1227
1228        impl MemoryReservation for PanicReservation {
1229            fn size(&self) -> usize {
1230                0
1231            }
1232            fn resize(&mut self, _: usize) {
1233                if !self.panicked {
1234                    self.panicked = true;
1235                    panic!("intentional panic in resize");
1236                }
1237            }
1238        }
1239
1240        impl MemoryPool for PanicPool {
1241            fn reserve(&self, _: usize) -> Box<dyn MemoryReservation> {
1242                Box::new(PanicReservation { panicked: false })
1243            }
1244            fn available(&self) -> isize {
1245                isize::MAX
1246            }
1247            fn used(&self) -> usize {
1248                0
1249            }
1250            fn capacity(&self) -> usize {
1251                usize::MAX
1252            }
1253        }
1254
1255        let pool = PanicPool;
1256        let data: Vec<u8> = (0..8).collect();
1257        let mut buf = Buffer::from_slice_ref(data.as_slice());
1258        buf.claim(&pool);
1259
1260        // shrink_to_fit panics because PanicReservation::resize panics, but
1261        // Buffer::ptr must stay consistent with Bytes::ptr (no use-after-free).
1262        let _ = catch_unwind(AssertUnwindSafe(|| buf.shrink_to_fit()));
1263
1264        assert_eq!(buf.as_slice(), data.as_slice());
1265    }
1266}