1use std::any::{Any, type_name};
2use std::ffi::c_void;
3use std::ptr::NonNull;
4
5use crate::erased::ErasedBorrowedPtr;
6use crate::{BoxerError, Result};
7
8#[repr(transparent)]
9pub struct BorrowedPtr<T: Any> {
10 ptr: *mut T,
11}
12
13impl<T: Any> BorrowedPtr<T> {
14 pub fn from_ref(value: &T) -> Self {
15 Self {
16 ptr: (value as *const T).cast_mut(),
17 }
18 }
19
20 pub fn from_mut(value: &mut T) -> Self {
21 Self {
22 ptr: value as *mut T,
23 }
24 }
25
26 pub const unsafe fn from_raw(ptr: *mut T) -> Self {
31 Self { ptr }
32 }
33
34 pub const fn null() -> Self {
35 Self {
36 ptr: std::ptr::null_mut(),
37 }
38 }
39
40 pub const fn as_raw(&self) -> *mut T {
41 self.ptr
42 }
43
44 pub fn erase(&self) -> ErasedBorrowedPtr {
57 unsafe { ErasedBorrowedPtr::from_raw(self.ptr.cast()) }
58 }
59
60 pub fn is_null(&self) -> bool {
61 self.ptr.is_null()
62 }
63
64 pub fn with_ref<R: Any, F>(&self, op: F) -> Result<R>
65 where
66 F: FnOnce(&T) -> Result<R>,
67 {
68 let pointer = self.non_null()?;
69 unsafe { op(pointer.as_ref()) }
70 }
71
72 pub fn with_option_ref<R: Any, F>(&self, op: F) -> Result<R>
73 where
74 F: FnOnce(Option<&T>) -> Result<R>,
75 {
76 if !self.is_null() {
77 self.with_ref(|value| op(Some(value)))
78 } else {
79 op(None)
80 }
81 }
82
83 pub fn with_ref_ok<R: Any, F>(&self, op: F) -> Result<R>
84 where
85 F: FnOnce(&T) -> R,
86 {
87 self.with_ref(|value| Ok(op(value)))
88 }
89
90 pub fn with_mut<R: Any, F>(&mut self, op: F) -> Result<R>
91 where
92 F: FnOnce(&mut T) -> Result<R>,
93 {
94 let mut pointer = self.non_null()?;
95 unsafe { op(pointer.as_mut()) }
96 }
97
98 pub fn with_mut_ok<R: Any, F>(&mut self, op: F) -> Result<R>
99 where
100 F: FnOnce(&mut T) -> R,
101 {
102 self.with_mut(|value| Ok(op(value)))
103 }
104
105 pub fn with_clone<R: Any, F>(&self, op: F) -> Result<R>
106 where
107 F: FnOnce(T) -> Result<R>,
108 T: Clone,
109 {
110 self.with_ref(|value| op(value.clone()))
111 }
112
113 pub fn with_clone_ok<R: Any, F>(&self, op: F) -> Result<R>
114 where
115 F: FnOnce(T) -> R,
116 T: Clone,
117 {
118 self.with_clone(|value| Ok(op(value)))
119 }
120
121 pub fn with_ptr<R: Any, F>(&self, op: F) -> Result<R>
122 where
123 F: FnOnce(NonNull<c_void>) -> Result<R>,
124 {
125 let pointer = self.non_null()?.cast::<c_void>();
126 op(pointer)
127 }
128
129 pub fn with_ptr_ok<R: Any, F>(&self, op: F) -> Result<R>
130 where
131 F: FnOnce(NonNull<c_void>) -> R,
132 {
133 self.with_ptr(|pointer| Ok(op(pointer)))
134 }
135
136 pub fn with_ref_ref<R: Any, F, P: Any>(&self, ptr: &BorrowedPtr<P>, op: F) -> Result<R>
137 where
138 F: FnOnce(&T, &P) -> Result<R>,
139 {
140 self.with_ref(|t| ptr.with_ref(|p| op(t, p)))
141 }
142
143 pub fn with_ref_ref_ref<R: Any, F, P1: Any, P2: Any>(
144 &self,
145 ptr1: &BorrowedPtr<P1>,
146 ptr2: &BorrowedPtr<P2>,
147 op: F,
148 ) -> Result<R>
149 where
150 F: FnOnce(&T, &P1, &P2) -> Result<R>,
151 {
152 self.with_ref(|t| ptr1.with_ref(|p1| ptr2.with_ref(|p2| op(t, p1, p2))))
153 }
154
155 pub fn with_ref_ref_ref_ref<R: Any, F, P1: Any, P2: Any, P3: Any>(
156 &self,
157 ptr1: &BorrowedPtr<P1>,
158 ptr2: &BorrowedPtr<P2>,
159 ptr3: &BorrowedPtr<P3>,
160 op: F,
161 ) -> Result<R>
162 where
163 F: FnOnce(&T, &P1, &P2, &P3) -> Result<R>,
164 {
165 self.with_ref(|t| {
166 ptr1.with_ref(|p1| ptr2.with_ref(|p2| ptr3.with_ref(|p3| op(t, p1, p2, p3))))
167 })
168 }
169
170 fn non_null(&self) -> Result<NonNull<T>> {
171 NonNull::new(self.ptr).ok_or_else(|| BoxerError::NullPointer(type_name::<T>().to_string()))
172 }
173}
174
175impl<T: Any> Default for BorrowedPtr<T> {
176 fn default() -> Self {
177 Self::null()
178 }
179}