1use super::uuid::Uuid;
2use super::Datum;
3use crate::prelude::*;
4use crate::varlena::{text_to_rust_str_unchecked, varlena_to_byte_slice};
5use crate::{Json, JsonB};
6use alloc::ffi::CString;
7use core::ffi::CStr;
8
9pub unsafe trait UnboxDatum {
28 type As<'src>
44 where
45 Self: 'src;
46 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
59 where
60 Self: 'src;
61}
62
63macro_rules! unbox_int {
64 ($($int_ty:ty),*) => {
65 $(
66 unsafe impl UnboxDatum for $int_ty {
67 type As<'src> = $int_ty;
68 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src> where Self: 'src {
69 datum.0.value() as $int_ty
70 }
71 }
72 )*
73 }
74}
75
76unbox_int! {
77 i8, i16, i32, i64
78}
79
80unsafe impl UnboxDatum for bool {
81 type As<'src> = bool;
82 #[inline]
83 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
84 where
85 Self: 'src,
86 {
87 datum.0.value() != 0
88 }
89}
90
91unsafe impl UnboxDatum for f32 {
92 type As<'src> = f32;
93 #[inline]
94 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
95 where
96 Self: 'src,
97 {
98 f32::from_bits(datum.0.value() as u32)
99 }
100}
101
102unsafe impl UnboxDatum for f64 {
103 type As<'src> = f64;
104 #[inline]
105 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
106 where
107 Self: 'src,
108 {
109 f64::from_bits(datum.0.value() as u64)
110 }
111}
112
113unsafe impl UnboxDatum for str {
114 type As<'src> = &'src str;
115 #[inline]
116 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
117 where
118 Self: 'src,
119 {
120 unsafe { text_to_rust_str_unchecked(datum.0.cast_mut_ptr()) }
121 }
122}
123
124unsafe impl UnboxDatum for &str {
125 #[rustfmt::skip]
126 type As<'src> = &'src str where Self: 'src;
127 #[inline]
128 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
129 where
130 Self: 'src,
131 {
132 unsafe { text_to_rust_str_unchecked(datum.0.cast_mut_ptr()) }
133 }
134}
135
136unsafe impl UnboxDatum for CStr {
137 type As<'src> = &'src CStr;
138 #[inline]
139 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
140 where
141 Self: 'src,
142 {
143 unsafe { CStr::from_ptr(datum.0.cast_mut_ptr()) }
144 }
145}
146
147unsafe impl UnboxDatum for &CStr {
148 #[rustfmt::skip]
149 type As<'src> = &'src CStr where Self: 'src;
150 #[inline]
151 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
152 where
153 Self: 'src,
154 {
155 unsafe { CStr::from_ptr(datum.0.cast_mut_ptr()) }
156 }
157}
158
159unsafe impl UnboxDatum for [u8] {
160 type As<'src> = &'src [u8];
161 #[inline]
162 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
163 where
164 Self: 'src,
165 {
166 unsafe { varlena_to_byte_slice(datum.0.cast_mut_ptr()) }
167 }
168}
169
170unsafe impl UnboxDatum for &[u8] {
171 #[rustfmt::skip]
172 type As<'src> = &'src [u8] where Self: 'src;
173 #[inline]
174 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
175 where
176 Self: 'src,
177 {
178 unsafe { varlena_to_byte_slice(datum.0.cast_mut_ptr()) }
179 }
180}
181
182unsafe impl UnboxDatum for pg_sys::Oid {
183 type As<'src> = pg_sys::Oid;
184 #[inline]
185 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
186 where
187 Self: 'src,
188 {
189 pg_sys::Oid::from(datum.0.value() as u32)
190 }
191}
192
193unsafe impl UnboxDatum for String {
194 type As<'src> = String;
195 #[inline]
196 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
197 where
198 Self: 'src,
199 {
200 unsafe { str::unbox(datum) }.to_owned()
201 }
202}
203
204unsafe impl UnboxDatum for CString {
205 type As<'src> = CString;
206 #[inline]
207 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
208 where
209 Self: 'src,
210 {
211 unsafe { CStr::unbox(datum) }.to_owned()
212 }
213}
214
215unsafe impl UnboxDatum for pg_sys::Datum {
216 type As<'src> = pg_sys::Datum;
217 #[inline]
218 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
219 where
220 Self: 'src,
221 {
222 datum.0
223 }
224}
225
226unsafe impl UnboxDatum for Uuid {
227 type As<'src> = Uuid;
228 #[inline]
229 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
230 where
231 Self: 'src,
232 {
233 Uuid::from_bytes(datum.0.cast_mut_ptr::<[u8; 16]>().read())
234 }
235}
236
237unsafe impl UnboxDatum for Date {
238 type As<'src> = Date;
239 #[inline]
240 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
241 where
242 Self: 'src,
243 {
244 Date::try_from(i32::unbox(datum)).unwrap_unchecked()
245 }
246}
247
248unsafe impl UnboxDatum for Time {
249 type As<'src> = Time;
250 #[inline]
251 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
252 where
253 Self: 'src,
254 {
255 Time::try_from(i64::unbox(datum)).unwrap_unchecked()
256 }
257}
258
259unsafe impl UnboxDatum for Timestamp {
260 type As<'src> = Timestamp;
261 #[inline]
262 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
263 where
264 Self: 'src,
265 {
266 Timestamp::try_from(i64::unbox(datum)).unwrap_unchecked()
267 }
268}
269
270unsafe impl UnboxDatum for TimestampWithTimeZone {
271 type As<'src> = TimestampWithTimeZone;
272 #[inline]
273 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src>
274 where
275 Self: 'src,
276 {
277 TimestampWithTimeZone::try_from(i64::unbox(datum)).unwrap_unchecked()
278 }
279}
280
281macro_rules! unbox_with_fromdatum {
282 ($($from_ty:ty,)*) => {
283 $(
284 unsafe impl UnboxDatum for $from_ty {
285 type As<'src> = $from_ty;
286 unsafe fn unbox<'src>(datum: Datum<'src>) -> Self::As<'src> where Self: 'src {
287 Self::from_datum(datum.0, false).unwrap()
288 }
289 }
290 )*
291 }
292}
293
294unbox_with_fromdatum! {
295 TimeWithTimeZone, AnyNumeric, char, pg_sys::Point, Interval, pg_sys::BOX, pg_sys::ItemPointerData,
296}
297
298unsafe impl UnboxDatum for PgHeapTuple<'_, crate::AllocatedByRust> {
299 #[rustfmt::skip]
300 type As<'src> = PgHeapTuple<'src, AllocatedByRust> where Self: 'src;
301 #[inline]
302 unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
303 where
304 Self: 'src,
305 {
306 PgHeapTuple::from_datum(d.0, false).unwrap()
307 }
308}
309
310unsafe impl<T: FromDatum + UnboxDatum> UnboxDatum for Array<'_, T> {
311 #[rustfmt::skip]
312 type As<'src> = Array<'src, T> where Self: 'src;
313 unsafe fn unbox<'src>(d: Datum<'src>) -> Array<'src, T>
314 where
315 Self: 'src,
316 {
317 Array::from_datum(d.0, false).unwrap()
318 }
319}
320
321unsafe impl<T: FromDatum + UnboxDatum> UnboxDatum for VariadicArray<'_, T> {
322 #[rustfmt::skip]
323 type As<'src> = VariadicArray<'src, T> where Self: 'src;
324 unsafe fn unbox<'src>(d: Datum<'src>) -> VariadicArray<'src, T>
325 where
326 Self: 'src,
327 {
328 VariadicArray::from_datum(d.0, false).unwrap()
329 }
330}
331
332unsafe impl<T: FromDatum + UnboxDatum + RangeSubType> UnboxDatum for Range<T> {
333 #[rustfmt::skip]
334 type As<'src> = Range<T> where Self: 'src;
335 unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
336 where
337 Self: 'src,
338 {
339 Range::<T>::from_datum(d.0, false).unwrap()
340 }
341}
342
343unsafe impl<const P: u32, const S: u32> UnboxDatum for Numeric<P, S> {
344 type As<'src> = Numeric<P, S>;
345 #[inline]
346 unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
347 where
348 Self: 'src,
349 {
350 Numeric::from_datum(d.0, false).unwrap()
351 }
352}
353
354unsafe impl<T> UnboxDatum for PgBox<T, AllocatedByPostgres> {
355 #[rustfmt::skip]
356 type As<'src> = PgBox<T> where Self: 'src;
357 #[inline]
358 unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
359 where
360 Self: 'src,
361 {
362 PgBox::from_datum(d.0, false).unwrap()
363 }
364}
365
366unsafe impl UnboxDatum for Json {
367 #[rustfmt::skip]
368 type As<'src> = Json where Self: 'src;
369 #[inline]
370 unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
371 where
372 Self: 'src,
373 {
374 Json::from_datum(d.0, false).unwrap()
375 }
376}
377
378unsafe impl UnboxDatum for JsonB {
379 #[rustfmt::skip]
380 type As<'src> = JsonB where Self: 'src;
381 #[inline]
382 unsafe fn unbox<'src>(d: Datum<'src>) -> Self::As<'src>
383 where
384 Self: 'src,
385 {
386 JsonB::from_datum(d.0, false).unwrap()
387 }
388}