Struct RawArray

Source
pub struct RawArray { /* private fields */ }
Expand description

An aligned, dereferenceable NonNull<ArrayType> with low-level accessors.

It offers safe accessors to the fields of pg_sys::ArrayType and mostly-safe accessors to the “dynamic fields” of the defined Postgres varlena array, but only requires validity of ArrayType itself and the dimensions slice (always valid if ndim == 0). This means the NonNull pointers that are returned may not be valid to read. Validating the correctness of the entire array requires a bit more effort.

It is not Copy or Clone to make it slightly harder to misuse versus *mut ArrayType. However, &mut self accessors do not give lifetimes to returned NonNull<[T]>! Instead, these are raw pointers, and &mut RawArray only makes &RawArray safer.

The reason RawArray works almost entirely with raw pointers is that it is not currently valid to go from &mut ArrayType to *mut ArrayType, take an offset beyond ArrayType’s fields, and then create a new slice there and read from that. The result is currently undefined behavior, though with emphasis on “undefined”: it may become defined in the future of Rust.

At the current moment, however, it is best to exercise an abundance of caution.

§On sizes and subscripts

Postgres uses C’s int (c_int in Rust) for sizes, and Rust uses usize. Thus various functions of RawArray return c_int values, but you must convert to usize. On 32-bit or 64-bit machines with 32-bit c_ints, you may losslessly upgrade as usize, except with negative indices, which Postgres asserts against creating. PGX currently only intentionally supports 64-bit machines, and while support for ILP32 or I64LP128 C data models may become possible, PGX will not support 16-bit machines in any practical case, even though Rust does.

Implementations§

Source§

impl RawArray

Source

pub unsafe fn from_ptr(ptr: NonNull<ArrayType>) -> RawArray

Returns a handle to the raw array header.

§Safety

When calling this method, you have to ensure that all of the following is true:

  • The pointer must be properly aligned.
  • It must be “dereferenceable” in the sense defined in the std documentation.
  • The pointer must point to an initialized instance of pg_sys::ArrayType.
  • The ndim field must be a correct value, or 0, so dims is aligned and readable, or no data is actually read at all.
  • This is a unique, “owning pointer” for the varlena, so it won’t be aliased while held, and it points to data in the Postgres ArrayType format.

It should be noted that despite all these requirements, RawArray has no lifetime, nor produces slices with such, so it can still be racy and unsafe!

Source

pub unsafe fn from_array<T: FromDatum>(arr: Array<'_, T>) -> Option<RawArray>

§Safety

Array must have been made from an ArrayType pointer, or a null value, as-if RawArray::from_ptr.

Source

pub fn into_ptr(self) -> NonNull<ArrayType>

Returns the inner raw pointer to the ArrayType.

Source

pub fn dims(&self) -> &[c_int]

A slice of the dimensions.

Oxidized form of ARR_DIMS(ArrayType*). The length will be within 0..=pg_sys::MAXDIM.

Safe to use because validity of this slice was asserted on construction.

Source

pub fn len(&self) -> usize

The flattened length of the array over every single element. Includes all items, even the ones that might be null.

Source

pub fn oid(&self) -> Oid

Accessor for ArrayType’s elemtype.

Source

pub fn nulls(&mut self) -> Option<NonNull<[u8]>>

Oxidized form of ARR_NULLBITMAP(ArrayType*)

If this returns None, the array cannot have nulls. If this returns Some, it points to the bitslice that marks nulls in this array.

Note that unlike the is_null: bool that appears elsewhere, here a 0 bit is null, or possibly out of bounds for the final byte of the bitslice.

Note that if this is None, that does not mean it’s always okay to read! If len is 0, then this slice will be valid for 0 bytes.

Source

pub fn nulls_bitslice(&mut self) -> Option<NonNull<BitSlice<u8>>>

The bitvec equivalent of RawArray::nulls. If this returns None, the array cannot have nulls. If this returns Some, it points to the bitslice that marks nulls in this array.

Note that unlike the is_null: bool that appears elsewhere, here a 0 bit is null. Unlike RawArray::nulls, this slice is bit-exact in length, so there are no caveats for safely-used BitSlices.

Source

pub unsafe fn any_nulls(&self) -> bool

Checks the array for any NULL values by assuming it is a proper varlena array,

§Safety
  • This requires every index is valid to read or correctly marked as null.
Source

pub fn data<T>(&mut self) -> NonNull<[T]>

Oxidized form of ARR_DATA_PTR(ArrayType*)

§Safety

While this function is safe to call, using the slice may risk undefined behavior. The raw slice is not guaranteed to be legible at any given index as T, e.g. it may be an “SQL null” if so indicated in the null bitmap. As a result, it is dangerous to reborrow this as &[T] or &mut [T] unless the type considers all bitpatterns to be valid values.

That is the primary reason this returns NonNull<[T]>. If it returned &mut [T], then for many possible types that can be undefined behavior, as it would assert each particular index was a valid T. A Rust borrow, including of a slice, will always be

  • non-null
  • aligned
  • validly initialized, except in the case of MaybeUninit types It is reasonable to assume data Postgres exposes logically to SQL is initialized, but it may be incorrect to assume data Postgres has marked “null” otherwise follows Rust-level initialization requirements.

As Postgres handles alignment requirements in its own particular ways, it is up to you to validate that each index is aligned correctly. The first element should be correctly aligned to the type, but that is not certain. Successive indices are even less likely to match the data type you want unless Postgres also uses an identical layout.

This returns a slice to make it somewhat harder to fail to read it correctly. However, it should be noted that a len 0 slice may not be read via raw pointers.

Trait Implementations§

Source§

impl Debug for RawArray

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithTypeIds for T
where T: 'static + ?Sized,

Source§

const ITEM_ID: Lazy<TypeId> = const ITEM_ID: Lazy<TypeId> = Lazy::new(|| TypeId::of::<T>());

Source§

const OPTION_ID: Lazy<Option<TypeId>> = const OPTION_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const VEC_ID: Lazy<Option<TypeId>> = const VEC_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const VEC_OPTION_ID: Lazy<Option<TypeId>> = const VEC_OPTION_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const OPTION_VEC_ID: Lazy<Option<TypeId>> = const OPTION_VEC_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const OPTION_VEC_OPTION_ID: Lazy<Option<TypeId>> = const OPTION_VEC_OPTION_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const ARRAY_ID: Lazy<Option<TypeId>> = const ARRAY_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const OPTION_ARRAY_ID: Lazy<Option<TypeId>> = const OPTION_ARRAY_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const VARIADICARRAY_ID: Lazy<Option<TypeId>> = const VARIADICARRAY_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const OPTION_VARIADICARRAY_ID: Lazy<Option<TypeId>> = const OPTION_VARIADICARRAY_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const VARLENA_ID: Lazy<Option<TypeId>> = const VARLENA_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

const OPTION_VARLENA_ID: Lazy<Option<TypeId>> = const OPTION_VARLENA_ID: Lazy<Option<TypeId>> = Lazy::new(|| None);

Source§

fn register_with_refs(map: &mut HashSet<RustSqlMapping>, single_sql: String)
where Self: 'static,

Source§

fn register_sized_with_refs( _map: &mut HashSet<RustSqlMapping>, _single_sql: String, )
where Self: 'static,

Source§

fn register_sized(_map: &mut HashSet<RustSqlMapping>, _single_sql: String)
where Self: 'static,

Source§

fn register_varlena_with_refs( _map: &mut HashSet<RustSqlMapping>, _single_sql: String, )
where Self: 'static,

Source§

fn register_varlena(_map: &mut HashSet<RustSqlMapping>, _single_sql: String)
where Self: 'static,

Source§

fn register_array_with_refs( _map: &mut HashSet<RustSqlMapping>, _single_sql: String, )
where Self: 'static,

Source§

fn register_array(_map: &mut HashSet<RustSqlMapping>, _single_sql: String)
where Self: 'static,

Source§

fn register(set: &mut HashSet<RustSqlMapping>, single_sql: String)
where Self: 'static,