Skip to main content

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