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