intuicio_framework_pointer/
lib.rs1use std::{
5 marker::PhantomData,
6 ops::{Deref, DerefMut},
7};
8
9use intuicio_core::{registry::Registry, transformer::ValueTransformer};
10
11pub type VoidPtr = Ptr<()>;
12
13#[repr(transparent)]
14pub struct Ptr<T> {
15 pointer: *mut T,
16}
17
18impl<T> Default for Ptr<T> {
19 fn default() -> Self {
20 Self {
21 pointer: std::ptr::null_mut(),
22 }
23 }
24}
25
26impl<T> Ptr<T> {
27 pub fn is_null(self) -> bool {
28 self.pointer.is_null()
29 }
30
31 pub fn to_ptr(self) -> *const T {
32 self.pointer
33 }
34
35 pub fn to_ptr_mut(self) -> *mut T {
36 self.pointer
37 }
38
39 pub unsafe fn as_ref(&self) -> Option<&T> {
41 if self.is_null() {
42 None
43 } else {
44 Some(unsafe { &*(self.pointer as *const T) })
45 }
46 }
47
48 pub unsafe fn as_ref_mut(&mut self) -> Option<&mut T> {
50 if self.is_null() {
51 None
52 } else {
53 Some(unsafe { &mut *self.pointer })
54 }
55 }
56
57 pub unsafe fn cast<U>(self) -> Ptr<U> {
59 Ptr {
60 pointer: self.pointer as *mut U,
61 }
62 }
63
64 pub unsafe fn into_box(self) -> Box<T> {
66 unsafe { Box::from_raw(self.pointer) }
67 }
68
69 pub unsafe fn from_box(value: Box<T>) -> Self {
71 Self {
72 pointer: Box::leak(value) as *mut T,
73 }
74 }
75}
76
77impl<T> From<*mut T> for Ptr<T> {
78 fn from(value: *mut T) -> Self {
79 Self { pointer: value }
80 }
81}
82
83impl<T> From<*const T> for Ptr<T> {
84 fn from(value: *const T) -> Self {
85 Self {
86 pointer: value as *mut T,
87 }
88 }
89}
90
91impl<T> From<&mut T> for Ptr<T> {
92 fn from(value: &mut T) -> Self {
93 Self {
94 pointer: value as *mut T,
95 }
96 }
97}
98
99impl<T> From<&T> for Ptr<T> {
100 fn from(value: &T) -> Self {
101 Self {
102 pointer: value as *const T as *mut T,
103 }
104 }
105}
106
107impl<T> From<Ptr<T>> for *const T {
108 fn from(value: Ptr<T>) -> Self {
109 value.pointer as *const T
110 }
111}
112
113impl<T> From<Ptr<T>> for *mut T {
114 fn from(value: Ptr<T>) -> Self {
115 value.pointer
116 }
117}
118
119impl<T> Deref for Ptr<T> {
120 type Target = T;
121
122 fn deref(&self) -> &Self::Target {
123 unsafe { self.as_ref().expect("Trying to dereference null pointer!") }
124 }
125}
126
127impl<T> DerefMut for Ptr<T> {
128 fn deref_mut(&mut self) -> &mut Self::Target {
129 unsafe {
130 self.as_ref_mut()
131 .expect("Trying to dereference null pointer!")
132 }
133 }
134}
135
136impl<T> Copy for Ptr<T> {}
137
138impl<T> Clone for Ptr<T> {
139 fn clone(&self) -> Self {
140 *self
141 }
142}
143
144unsafe impl<T> Send for Ptr<T> where T: Send {}
147unsafe impl<T> Sync for Ptr<T> where T: Sync {}
148
149impl<T> std::fmt::Debug for Ptr<T> {
150 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151 write!(f, "{:?}", self.pointer)
152 }
153}
154
155impl<T> std::fmt::Display for Ptr<T> {
156 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157 write!(f, "{:?}", self.pointer)
158 }
159}
160
161pub struct PtrValueTransformer<T: Default + Clone + 'static>(PhantomData<fn() -> T>);
162
163impl<T: Default + Clone + 'static> ValueTransformer for PtrValueTransformer<T> {
164 type Type = T;
165 type Borrow<'r> = &'r T;
166 type BorrowMut<'r> = &'r mut T;
167 type Dependency = ();
168 type Owned = T;
169 type Ref = Ptr<T>;
170 type RefMut = Ptr<T>;
171
172 fn from_owned(_: &Registry, value: Self::Type) -> Self::Owned {
173 value
174 }
175
176 fn from_ref(_: &Registry, value: &Self::Type, _: Option<Self::Dependency>) -> Self::Ref {
177 Ptr::from(value)
178 }
179
180 fn from_ref_mut(
181 _: &Registry,
182 value: &mut Self::Type,
183 _: Option<Self::Dependency>,
184 ) -> Self::RefMut {
185 Ptr::from(value)
186 }
187
188 fn into_owned(value: Self::Owned) -> Self::Type {
189 value
190 }
191
192 fn into_ref(value: &Self::Ref) -> Self::Borrow<'_> {
193 unsafe { value.as_ref().unwrap() }
194 }
195
196 fn into_ref_mut(value: &mut Self::RefMut) -> Self::BorrowMut<'_> {
197 unsafe { value.as_ref_mut().unwrap() }
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204 use intuicio_core::prelude::*;
205 use intuicio_derive::intuicio_function;
206
207 #[test]
208 fn test_async() {
209 fn is_async<T: Send + Sync>() {}
210
211 is_async::<Ptr<usize>>();
212 is_async::<Ptr<Ptr<usize>>>();
213 }
214
215 #[intuicio_function(transformer = "PtrValueTransformer")]
216 fn add(a: &usize, b: &mut usize) -> usize {
217 *a + *b
218 }
219
220 #[test]
221 fn test_raw_pointer_on_stack() {
222 let mut registry = Registry::default().with_basic_types();
223 registry.add_type(define_native_struct! {
224 registry => struct (Ptr<usize>) {}
225 });
226 let add = registry.add_function(add::define_function(®istry));
227 let mut context = Context::new(10240, 10240);
228 let a = 40usize;
229 let mut b = 2usize;
230 let (r,) = add.call::<(usize,), _>(
231 &mut context,
232 ®istry,
233 (Ptr::from(&a), Ptr::from(&mut b)),
234 true,
235 );
236 assert_eq!(r, 42);
237 }
238
239 #[test]
240 fn test_allocation() {
241 unsafe {
242 let a = Box::new(42usize);
243 let mut b = Ptr::from_box(a);
244 *b.as_ref_mut().unwrap() = 10;
245 let c = b.into_box();
246 let d = *c;
247 assert_eq!(d, 10);
248 }
249 }
250}