1use crate::aws_lc::{
5 BN_free, ECDSA_SIG_free, EC_GROUP_free, EC_KEY_free, EC_POINT_free, EVP_AEAD_CTX_free,
6 EVP_CIPHER_CTX_free, EVP_PKEY_CTX_free, EVP_PKEY_free, OPENSSL_free, RSA_free, BIGNUM,
7 ECDSA_SIG, EC_GROUP, EC_KEY, EC_POINT, EVP_AEAD_CTX, EVP_CIPHER_CTX, EVP_PKEY, EVP_PKEY_CTX,
8 RSA,
9};
10use core::ops::Deref;
11use std::marker::PhantomData;
12
13pub(crate) type LcPtr<T> = ManagedPointer<*mut T>;
14pub(crate) type DetachableLcPtr<T> = DetachablePointer<*mut T>;
15
16#[derive(Debug)]
17pub(crate) struct ManagedPointer<P: Pointer> {
18 pointer: P,
19}
20
21impl<P: Pointer> ManagedPointer<P> {
22 #[inline]
23 pub fn new<T: IntoPointer<P>>(value: T) -> Result<Self, ()> {
24 if let Some(pointer) = value.into_pointer() {
25 Ok(Self { pointer })
26 } else {
27 Err(())
28 }
29 }
30
31 pub unsafe fn as_slice(&self, len: usize) -> &[P::T] {
32 core::slice::from_raw_parts(self.pointer.as_const_ptr(), len)
33 }
34}
35
36impl<P: Pointer> Drop for ManagedPointer<P> {
37 #[inline]
38 fn drop(&mut self) {
39 self.pointer.free();
40 }
41}
42
43impl<'a, P: Pointer> From<&'a ManagedPointer<P>> for ConstPointer<'a, P::T> {
44 fn from(ptr: &'a ManagedPointer<P>) -> ConstPointer<'a, P::T> {
45 ConstPointer {
46 ptr: ptr.pointer.as_const_ptr(),
47 _lifetime: PhantomData,
48 }
49 }
50}
51
52impl<P: Pointer> ManagedPointer<P> {
53 #[inline]
54 pub fn as_const(&self) -> ConstPointer<'_, P::T> {
55 self.into()
56 }
57
58 pub fn project_const_lifetime<'a, C>(
59 &'a self,
60 f: unsafe fn(&'a Self) -> *const C,
61 ) -> Result<ConstPointer<'a, C>, ()> {
62 let ptr = unsafe { f(self) };
63 if ptr.is_null() {
64 return Err(());
65 }
66 Ok(ConstPointer {
67 ptr,
68 _lifetime: PhantomData,
69 })
70 }
71
72 #[inline]
73 pub unsafe fn as_mut_unsafe(&self) -> MutPointer<P::T> {
74 MutPointer {
75 ptr: self.pointer.as_const_ptr() as *mut P::T,
76 }
77 }
78
79 #[inline]
80 pub fn as_mut(&mut self) -> MutPointer<P::T> {
81 MutPointer {
82 ptr: self.pointer.as_mut_ptr(),
83 }
84 }
85}
86
87impl<P: Pointer> DetachablePointer<P> {
88 #[inline]
89 pub fn as_mut(&mut self) -> MutPointer<P::T> {
90 MutPointer {
91 ptr: self.pointer.as_mut().unwrap().as_mut_ptr(),
92 }
93 }
94}
95
96#[derive(Debug)]
97#[allow(clippy::module_name_repetitions)]
98pub(crate) struct DetachablePointer<P: Pointer> {
99 pointer: Option<P>,
100}
101
102impl<P: Pointer> Deref for DetachablePointer<P> {
103 type Target = P;
104 #[inline]
105 fn deref(&self) -> &Self::Target {
106 match &self.pointer {
107 Some(pointer) => pointer,
108 None => {
109 unreachable!()
111 }
112 }
113 }
114}
115
116impl<P: Pointer> DetachablePointer<P> {
117 #[inline]
118 pub fn new<T: IntoPointer<P>>(value: T) -> Result<Self, ()> {
119 if let Some(pointer) = value.into_pointer() {
120 Ok(Self {
121 pointer: Some(pointer),
122 })
123 } else {
124 Err(())
125 }
126 }
127
128 #[inline]
129 pub fn detach(mut self) -> P {
130 self.pointer.take().unwrap()
131 }
132}
133
134impl<P: Pointer> From<DetachablePointer<P>> for ManagedPointer<P> {
135 #[inline]
136 fn from(mut dptr: DetachablePointer<P>) -> Self {
137 match dptr.pointer.take() {
138 Some(pointer) => ManagedPointer { pointer },
139 None => {
140 unreachable!()
142 }
143 }
144 }
145}
146
147impl<P: Pointer> Drop for DetachablePointer<P> {
148 #[inline]
149 fn drop(&mut self) {
150 if let Some(mut pointer) = self.pointer.take() {
151 pointer.free();
152 }
153 }
154}
155
156#[derive(Debug)]
157pub(crate) struct ConstPointer<'a, T> {
158 ptr: *const T,
159 _lifetime: PhantomData<&'a T>,
160}
161
162impl<T> ConstPointer<'static, T> {
163 pub unsafe fn new_static(ptr: *const T) -> Result<Self, ()> {
164 if ptr.is_null() {
165 return Err(());
166 }
167 Ok(ConstPointer {
168 ptr,
169 _lifetime: PhantomData,
170 })
171 }
172}
173
174impl<T> ConstPointer<'_, T> {
175 pub fn project_const_lifetime<'a, C>(
176 &'a self,
177 f: unsafe fn(&'a Self) -> *const C,
178 ) -> Result<ConstPointer<'a, C>, ()> {
179 let ptr = unsafe { f(self) };
180 if ptr.is_null() {
181 return Err(());
182 }
183 Ok(ConstPointer {
184 ptr,
185 _lifetime: PhantomData,
186 })
187 }
188}
189
190impl<T> Deref for ConstPointer<'_, T> {
191 type Target = *const T;
192
193 fn deref(&self) -> &Self::Target {
194 &self.ptr
195 }
196}
197
198#[derive(Debug)]
199pub(crate) struct MutPointer<T> {
200 ptr: *mut T,
201}
202
203impl<T> Deref for MutPointer<T> {
204 type Target = *mut T;
205
206 fn deref(&self) -> &Self::Target {
207 &self.ptr
208 }
209}
210
211pub(crate) trait Pointer {
212 type T;
213
214 fn free(&mut self);
215 fn as_const_ptr(&self) -> *const Self::T;
216 fn as_mut_ptr(&mut self) -> *mut Self::T;
217}
218
219pub(crate) trait IntoPointer<P> {
220 fn into_pointer(self) -> Option<P>;
221}
222
223impl<T> IntoPointer<*mut T> for *mut T {
224 #[inline]
225 fn into_pointer(self) -> Option<*mut T> {
226 if self.is_null() {
227 None
228 } else {
229 Some(self)
230 }
231 }
232}
233
234macro_rules! create_pointer {
235 ($ty:ty, $free:path) => {
236 impl Pointer for *mut $ty {
237 type T = $ty;
238
239 #[inline]
240 fn free(&mut self) {
241 unsafe {
242 let ptr = *self;
243 $free(ptr.cast());
244 }
245 }
246
247 #[inline]
248 fn as_const_ptr(&self) -> *const Self::T {
249 self.cast()
250 }
251
252 #[inline]
253 fn as_mut_ptr(&mut self) -> *mut Self::T {
254 *self
255 }
256 }
257 };
258}
259
260create_pointer!(u8, OPENSSL_free);
264create_pointer!(EC_GROUP, EC_GROUP_free);
265create_pointer!(EC_POINT, EC_POINT_free);
266create_pointer!(EC_KEY, EC_KEY_free);
267create_pointer!(ECDSA_SIG, ECDSA_SIG_free);
268create_pointer!(BIGNUM, BN_free);
269create_pointer!(EVP_PKEY, EVP_PKEY_free);
270create_pointer!(EVP_PKEY_CTX, EVP_PKEY_CTX_free);
271create_pointer!(RSA, RSA_free);
272create_pointer!(EVP_AEAD_CTX, EVP_AEAD_CTX_free);
273create_pointer!(EVP_CIPHER_CTX, EVP_CIPHER_CTX_free);
274
275#[cfg(test)]
276mod tests {
277 use crate::aws_lc::BIGNUM;
278 use crate::ptr::{DetachablePointer, ManagedPointer};
279
280 #[test]
281 fn test_debug() {
282 let num = 100u64;
283 let detachable_ptr: DetachablePointer<*mut BIGNUM> =
284 DetachablePointer::try_from(num).unwrap();
285 let debug = format!("{detachable_ptr:?}");
286 assert!(debug.contains("DetachablePointer { pointer: Some("));
287
288 let lc_ptr = ManagedPointer::new(detachable_ptr.detach()).unwrap();
289 let debug = format!("{lc_ptr:?}");
290 assert!(debug.contains("ManagedPointer { pointer:"));
291 }
292}