use super::uuid::Uuid;
use super::Datum;
use crate::prelude::*;
use crate::varlena::{text_to_rust_str_unchecked, varlena_to_byte_slice};
use crate::{Json, JsonB};
use alloc::ffi::CString;
use core::ffi::CStr;
pub unsafe trait UnboxDatum {
type As<'src>
where
Self: 'src;
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src;
}
macro_rules! unbox_int {
($($int_ty:ty),*) => {
$(
unsafe impl UnboxDatum for $int_ty {
type As<'src> = $int_ty;
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src> where Self: 'src {
datum.0.value() as $int_ty
}
}
)*
}
}
unbox_int! {
i8, i16, i32, i64
}
unsafe impl UnboxDatum for bool {
type As<'src> = bool;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
datum.0.value() != 0
}
}
unsafe impl UnboxDatum for f32 {
type As<'src> = f32;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
f32::from_bits(datum.0.value() as u32)
}
}
unsafe impl UnboxDatum for f64 {
type As<'src> = f64;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
f64::from_bits(datum.0.value() as u64)
}
}
unsafe impl UnboxDatum for str {
type As<'src> = &'src str;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
unsafe { text_to_rust_str_unchecked(datum.0.cast_mut_ptr()) }
}
}
unsafe impl UnboxDatum for &str {
type As<'src> = &'src str where Self: 'src;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
unsafe { text_to_rust_str_unchecked(datum.0.cast_mut_ptr()) }
}
}
unsafe impl UnboxDatum for CStr {
type As<'src> = &'src CStr;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
unsafe { CStr::from_ptr(datum.0.cast_mut_ptr()) }
}
}
unsafe impl UnboxDatum for &CStr {
type As<'src> = &'src CStr where Self: 'src;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
unsafe { CStr::from_ptr(datum.0.cast_mut_ptr()) }
}
}
unsafe impl UnboxDatum for [u8] {
type As<'src> = &'src [u8];
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
unsafe { varlena_to_byte_slice(datum.0.cast_mut_ptr()) }
}
}
unsafe impl UnboxDatum for &[u8] {
type As<'src> = &'src [u8] where Self: 'src;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
unsafe { varlena_to_byte_slice(datum.0.cast_mut_ptr()) }
}
}
unsafe impl UnboxDatum for pg_sys::Oid {
type As<'src> = pg_sys::Oid;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
pg_sys::Oid::from(datum.0.value() as u32)
}
}
unsafe impl UnboxDatum for String {
type As<'src> = String;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
unsafe { str::unbox(datum) }.to_owned()
}
}
unsafe impl UnboxDatum for CString {
type As<'src> = CString;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
unsafe { CStr::unbox(datum) }.to_owned()
}
}
unsafe impl UnboxDatum for pg_sys::Datum {
type As<'src> = pg_sys::Datum;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
datum.0
}
}
unsafe impl UnboxDatum for Uuid {
type As<'src> = Uuid;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
Uuid::from_bytes(datum.0.cast_mut_ptr::<[u8; 16]>().read())
}
}
unsafe impl UnboxDatum for Date {
type As<'src> = Date;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
Date::try_from(i32::unbox(datum)).unwrap_unchecked()
}
}
unsafe impl UnboxDatum for Time {
type As<'src> = Time;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
Time::try_from(i64::unbox(datum)).unwrap_unchecked()
}
}
unsafe impl UnboxDatum for Timestamp {
type As<'src> = Timestamp;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
Timestamp::try_from(i64::unbox(datum)).unwrap_unchecked()
}
}
unsafe impl UnboxDatum for TimestampWithTimeZone {
type As<'src> = TimestampWithTimeZone;
#[inline]
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
TimestampWithTimeZone::try_from(i64::unbox(datum)).unwrap_unchecked()
}
}
macro_rules! unbox_with_fromdatum {
($($from_ty:ty,)*) => {
$(
unsafe impl UnboxDatum for $from_ty {
type As<'src> = $from_ty;
unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src> where Self: 'src {
Self::from_datum(datum.0, false).unwrap()
}
}
)*
}
}
unbox_with_fromdatum! {
TimeWithTimeZone, AnyNumeric, char, pg_sys::Point, Interval, pg_sys::BOX,
}
unsafe impl UnboxDatum for PgHeapTuple<'_, crate::AllocatedByRust> {
type As<'src> = PgHeapTuple<'src, AllocatedByRust> where Self: 'src;
#[inline]
unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
PgHeapTuple::from_datum(d.0, false).unwrap()
}
}
unsafe impl<T: FromDatum + UnboxDatum> UnboxDatum for Array<'_, T> {
type As<'src> = Array<'src, T> where Self: 'src;
unsafe fn unbox<'src>(d: Datum<'src>) -> Array<'src, T>
where
Self: 'src,
{
Array::from_datum(d.0, false).unwrap()
}
}
unsafe impl<T: FromDatum + UnboxDatum> UnboxDatum for VariadicArray<'_, T> {
type As<'src> = VariadicArray<'src, T> where Self: 'src;
unsafe fn unbox<'src>(d: Datum<'src>) -> VariadicArray<'src, T>
where
Self: 'src,
{
VariadicArray::from_datum(d.0, false).unwrap()
}
}
unsafe impl<T: FromDatum + UnboxDatum + RangeSubType> UnboxDatum for Range<T> {
type As<'src> = Range<T> where Self: 'src;
unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
Range::<T>::from_datum(d.0, false).unwrap()
}
}
unsafe impl<const P: u32, const S: u32> UnboxDatum for Numeric<P, S> {
type As<'src> = Numeric<P, S>;
#[inline]
unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
Numeric::from_datum(d.0, false).unwrap()
}
}
unsafe impl<T> UnboxDatum for PgBox<T, AllocatedByPostgres> {
type As<'src> = PgBox<T> where Self: 'src;
#[inline]
unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
PgBox::from_datum(d.0, false).unwrap()
}
}
unsafe impl UnboxDatum for Json {
type As<'src> = Json where Self: 'src;
#[inline]
unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
Json::from_datum(d.0, false).unwrap()
}
}
unsafe impl UnboxDatum for JsonB {
type As<'src> = JsonB where Self: 'src;
#[inline]
unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
where
Self: 'src,
{
JsonB::from_datum(d.0, false).unwrap()
}
}