pgrx/
slice.rs

1//LICENSE Portions Copyright 2019-2021 ZomboDB, LLC.
2//LICENSE
3//LICENSE Portions Copyright 2021-2023 Technology Concepts & Design, Inc.
4//LICENSE
5//LICENSE Portions Copyright 2023-2023 PgCentral Foundation, Inc. <contact@pgcentral.org>
6//LICENSE
7//LICENSE All rights reserved.
8//LICENSE
9//LICENSE Use of this source code is governed by the MIT license that can be found in the LICENSE file.
10#![allow(dead_code)]
11use crate::prelude::*;
12use core::marker::PhantomData;
13use core::ptr;
14
15/// PallocSlice is between slice and Vec: PallocSlice does not assume the underlying T is valid for all indices
16/// and so does not implement the safe trait Index, but does let you call an `unsafe fn get` to do so,
17/// and manages its own Drop implementation for the pallocation.
18///
19/// Note that while it's technically not lifetime-bound, it's still bound to the lifetime of the memory context.
20/// You should use this inside types that are themselves lifetime-bound to prevent inappropriate "escape".
21pub struct PallocSlice<T> {
22    pallocd: ptr::NonNull<[T]>,
23    _phantom: PhantomData<Box<[T]>>,
24}
25
26impl<T> PallocSlice<T> {
27    pub unsafe fn from_raw_parts(ptr: ptr::NonNull<T>, len: usize) -> Self {
28        PallocSlice {
29            pallocd: ptr::NonNull::new_unchecked(ptr::slice_from_raw_parts_mut(ptr.as_ptr(), len)),
30            _phantom: PhantomData,
31        }
32    }
33
34    /// # Safety
35    /// You must know the underlying type at that index is validly initialized in Rust.
36    #[inline]
37    pub unsafe fn get(&self, index: usize) -> Option<&T> {
38        index.le(&self.pallocd.len()).then(|| self.get_unchecked(index))
39    }
40
41    /// # Safety
42    /// You must know the underlying type at that index is validly initialized in Rust,
43    /// AND that the index is inbounds.
44    #[inline]
45    pub unsafe fn get_unchecked(&self, index: usize) -> &T {
46        self.pallocd.as_ptr().cast::<T>().add(index).as_ref().unwrap_unchecked()
47    }
48}
49
50impl<T> Drop for PallocSlice<T> {
51    fn drop(&mut self) {
52        unsafe { pg_sys::pfree(self.pallocd.cast().as_ptr()) }
53    }
54}