pgrx_pg_sys/submodules/
datum.rs1use crate::NullableDatum;
12use std::ptr::NonNull;
13
14#[repr(C)]
27struct DatumBlob {
28 _data: [u8; 0],
29 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
30}
31
32#[repr(transparent)]
57#[derive(Debug, Copy, Clone, PartialEq)]
58pub struct Datum(*mut DatumBlob);
59
60impl Datum {
61 #[inline]
64 pub fn value(self) -> usize {
65 sptr::Strict::addr(self.0)
66 }
67
68 #[inline]
69 pub const fn null() -> Datum {
70 Datum(core::ptr::null_mut())
71 }
72
73 #[inline]
75 pub fn is_null(self) -> bool {
76 self.0.is_null()
77 }
78
79 #[inline]
82 pub fn cast_mut_ptr<T>(self) -> *mut T {
83 self.0.cast()
84 }
85}
86
87impl From<usize> for Datum {
88 #[inline]
89 fn from(val: usize) -> Datum {
90 Datum(sptr::Strict::with_addr(NonNull::<DatumBlob>::dangling().as_ptr(), val))
91 }
92}
93
94impl From<Datum> for usize {
95 #[inline]
96 fn from(val: Datum) -> usize {
97 sptr::Strict::addr(val.0)
98 }
99}
100
101impl From<isize> for Datum {
102 #[inline]
103 fn from(val: isize) -> Datum {
104 Datum::from(val as usize)
105 }
106}
107
108impl From<u8> for Datum {
109 #[inline]
110 fn from(val: u8) -> Datum {
111 Datum::from(usize::from(val))
112 }
113}
114
115impl From<u16> for Datum {
116 #[inline]
117 fn from(val: u16) -> Datum {
118 Datum::from(usize::from(val))
119 }
120}
121
122impl From<u32> for Datum {
123 #[inline]
124 fn from(val: u32) -> Datum {
125 Datum::from(val as usize)
126 }
127}
128
129impl From<u64> for Datum {
130 #[inline]
131 fn from(val: u64) -> Datum {
132 if cfg!(target_pointer_width = "64") {
133 Datum::from(val as usize)
134 } else {
135 unsafe {
136 let ptr = crate::palloc(size_of::<u64>()) as *mut u64;
137 *ptr = val;
138 Datum::from(ptr)
139 }
140 }
141 }
142}
143
144impl From<i8> for Datum {
145 #[inline]
146 fn from(val: i8) -> Datum {
147 Datum::from(isize::from(val))
148 }
149}
150
151impl From<i16> for Datum {
152 #[inline]
153 fn from(val: i16) -> Datum {
154 Datum::from(isize::from(val))
155 }
156}
157
158impl From<i32> for Datum {
159 #[inline]
160 fn from(val: i32) -> Datum {
161 Datum::from(val as usize)
162 }
163}
164
165impl From<i64> for Datum {
166 #[inline]
167 fn from(val: i64) -> Datum {
168 if cfg!(target_pointer_width = "64") {
169 Datum::from(val as usize)
170 } else {
171 unsafe {
172 let ptr = crate::palloc(size_of::<i64>()) as *mut i64;
173 *ptr = val;
174 Datum::from(ptr)
175 }
176 }
177 }
178}
179
180impl From<bool> for Datum {
181 #[inline]
182 fn from(val: bool) -> Datum {
183 Datum::from(val as usize)
184 }
185}
186
187impl<T> From<*mut T> for Datum {
188 #[inline]
189 fn from(val: *mut T) -> Datum {
190 Datum(val.cast())
191 }
192}
193
194impl<T> From<*const T> for Datum {
195 #[inline]
196 fn from(val: *const T) -> Datum {
197 Datum(val as *mut _)
198 }
199}
200
201impl<T> PartialEq<*mut T> for Datum {
202 #[inline]
203 fn eq(&self, other: &*mut T) -> bool {
204 &self.0.cast() == other
205 }
206}
207
208impl<T> PartialEq<Datum> for *mut T {
209 #[inline]
210 fn eq(&self, other: &Datum) -> bool {
211 self == &other.0.cast()
212 }
213}
214
215impl TryFrom<NullableDatum> for Datum {
216 type Error = ();
217
218 #[inline]
219 fn try_from(nd: NullableDatum) -> Result<Datum, ()> {
220 let NullableDatum { value, isnull } = nd;
221 if isnull {
222 Err(())
223 } else {
224 Ok(value)
225 }
226 }
227}
228
229impl From<NullableDatum> for Option<Datum> {
230 #[inline]
231 fn from(nd: NullableDatum) -> Option<Datum> {
232 Datum::try_from(nd).ok()
233 }
234}
235
236#[cfg(test)]
237mod test {
238 use super::*;
239
240 #[test]
241 fn roundtrip_integers() {
242 let val = i64::MAX;
243 let datum = Datum::from(val);
244 assert_eq!(datum.value() as i64, val);
245
246 let val = isize::MAX;
247 let datum = Datum::from(val);
248 assert_eq!(datum.value() as isize, val);
249
250 let val = i64::MIN;
251 let datum = Datum::from(val);
252 assert_eq!(datum.value() as i64, val);
253
254 let val = isize::MIN;
255 let datum = Datum::from(val);
256 assert_eq!(datum.value() as isize, val);
257
258 let val = u64::MAX;
259 let datum = Datum::from(val);
260 assert_eq!(datum.value() as u64, val);
261
262 let val = usize::MAX;
263 let datum = Datum::from(val);
264 assert_eq!(datum.value(), val);
265 }
266}