Skip to content

Commit 6389adb

Browse files
Add array::Element and callconv::DatumPass (pgcentralfoundation#2218)
This enables adding `FlatArray` with a correct model of nested arrays for Postgres (i.e. there is no such thing).
1 parent e30ee9f commit 6389adb

5 files changed

Lines changed: 62 additions & 4 deletions

File tree

output.log

Whitespace-only changes.

pgrx/src/array.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ use bitvec::slice::BitSlice;
1616
use core::ptr::{self, NonNull};
1717
use core::slice;
1818

19+
mod element;
1920
mod port;
2021

22+
pub use element::Element;
23+
2124
/**
2225
An aligned, dereferenceable `NonNull<ArrayType>` with low-level accessors.
2326

pgrx/src/array/element.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use crate::callconv::DatumPass;
2+
use crate::datum::BorrowDatum;
3+
use crate::layout::PassBy;
4+
use core::ptr;
5+
6+
/// `BorrowDatum` for array elements
7+
///
8+
/// # Safety
9+
/// As BorrowDatum, due to the blanket implementation.
10+
pub unsafe trait Element {
11+
unsafe fn point_from(ptr: ptr::NonNull<u8>) -> ptr::NonNull<Self>;
12+
13+
/// Cast a pointer to aligned varlena headers to this type
14+
///
15+
/// This version allows you to assume the pointer is aligned to, and readable for, 4 bytes.
16+
/// This optimization is not required. When in doubt, avoid implementing it, and rely on your
17+
/// `point_from` implementation alone.
18+
///
19+
/// # Safety
20+
/// - This must be correctly invoked for the pointee type, as it may deref.
21+
/// - This must be 4-byte aligned!
22+
unsafe fn point_from_align4(ptr: ptr::NonNull<u32>) -> ptr::NonNull<Self> {
23+
debug_assert!(ptr.is_aligned());
24+
unsafe { Element::point_from(ptr.cast()) }
25+
}
26+
27+
/// Optimization for borrowing the referent
28+
unsafe fn borrow_unchecked<'dat>(ptr: ptr::NonNull<u8>) -> &'dat Self {
29+
unsafe { Element::point_from(ptr).as_ref() }
30+
}
31+
}
32+
33+
unsafe impl<T> BorrowDatum for T
34+
where
35+
T: ?Sized + Element + DatumPass,
36+
{
37+
const PASS: PassBy = <T as DatumPass>::PASS;
38+
39+
unsafe fn point_from(ptr: ptr::NonNull<u8>) -> std::ptr::NonNull<Self> {
40+
unsafe { Element::point_from(ptr) }
41+
}
42+
43+
unsafe fn point_from_align4(ptr: ptr::NonNull<u32>) -> ptr::NonNull<Self> {
44+
unsafe { Element::point_from_align4(ptr.cast()) }
45+
}
46+
}

pgrx/src/callconv.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,3 +1031,8 @@ impl<'fcx> ReturnSetInfoWrapper<'fcx> {
10311031
unsafe { (*self.0).setDesc }
10321032
}
10331033
}
1034+
1035+
/// Denotes a type that may be passed as a Datum
1036+
pub unsafe trait DatumPass {
1037+
const PASS: PassBy;
1038+
}

pgrx/src/datum/borrow.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![deny(unsafe_op_in_unsafe_fn)]
22
use super::*;
3+
use crate::array::Element;
4+
use crate::callconv::DatumPass;
35
use crate::layout::PassBy;
46
use core::{ffi, mem, ptr};
57

@@ -87,13 +89,14 @@ where
8789
macro_rules! impl_borrow_fixed_len {
8890
($($value_ty:ty),*) => {
8991
$(
90-
unsafe impl BorrowDatum for $value_ty {
92+
unsafe impl DatumPass for $value_ty {
9193
const PASS: PassBy = if mem::size_of::<Self>() <= mem::size_of::<Datum>() {
9294
PassBy::Value
9395
} else {
9496
PassBy::Ref
9597
};
96-
98+
}
99+
unsafe impl Element for $value_ty {
97100
unsafe fn point_from(ptr: ptr::NonNull<u8>) -> ptr::NonNull<Self> {
98101
#[cfg(target_endian = "big")]
99102
unsafe {
@@ -120,9 +123,10 @@ impl_borrow_fixed_len! {
120123
}
121124

122125
/// It is rare to pass CStr via Datums, but not unheard of
123-
unsafe impl BorrowDatum for ffi::CStr {
126+
unsafe impl DatumPass for ffi::CStr {
124127
const PASS: PassBy = PassBy::Ref;
125-
128+
}
129+
unsafe impl Element for ffi::CStr {
126130
unsafe fn point_from(ptr: ptr::NonNull<u8>) -> ptr::NonNull<Self> {
127131
let char_ptr: *mut ffi::c_char = ptr.as_ptr().cast();
128132
unsafe {

0 commit comments

Comments
 (0)