1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use core::cell::UnsafeCell;
15 
16 pub struct ForeignRefWrapper(UnsafeCell<()>);
17 
18 pub trait Foreign: Sized {
19     /// The raw C struct.
20     type CStruct;
21     /// A reference to the rust type.
22     type Ref: ForeignRef<CStruct = Self::CStruct>;
23 
24     /// The raw C struct pointer to rust type.
from_ptr(ptr: *mut Self::CStruct) -> Self25     fn from_ptr(ptr: *mut Self::CStruct) -> Self;
26     /// Returns a raw pointer to the C struct.
as_ptr(&self) -> *mut Self::CStruct27     fn as_ptr(&self) -> *mut Self::CStruct;
28 }
29 
30 pub trait ForeignRef: Sized {
31     /// The raw C struct.
32     type CStruct;
33 
34     /// # Safety
35     /// Dereference of raw pointer.
36     #[inline]
from_ptr<'a>(ptr: *mut Self::CStruct) -> &'a Self37     unsafe fn from_ptr<'a>(ptr: *mut Self::CStruct) -> &'a Self {
38         &*(ptr as *mut _)
39     }
40 
41     /// # Safety
42     /// Dereference of raw pointer.
43     #[inline]
from_ptr_mut<'a>(ptr: *mut Self::CStruct) -> &'a mut Self44     unsafe fn from_ptr_mut<'a>(ptr: *mut Self::CStruct) -> &'a mut Self {
45         &mut *(ptr as *mut _)
46     }
47 
48     /// Returns a raw pointer to the C struct.
49     #[inline]
as_ptr(&self) -> *mut Self::CStruct50     fn as_ptr(&self) -> *mut Self::CStruct {
51         self as *const _ as *mut _
52     }
53 }
54 
55 macro_rules! foreign_type {
56     (
57         type CStruct = $ctype:ty;
58         fn drop = $drop:expr;
59 
60         $(#[$own_attr:meta])*
61         pub(crate) struct $owned:ident;
62 
63         $(#[$borrow_attr:meta])*
64         pub(crate) struct $borrowed:ident;
65     ) => {
66         // Wraps * mut C struct.
67         $(#[$own_attr])*
68         pub(crate) struct $owned(*mut $ctype);
69 
70         impl crate::util::c_openssl::foreign::Foreign for $owned {
71             type CStruct = $ctype;
72             type Ref = $borrowed;
73 
74             #[inline]
75             fn from_ptr(ptr: *mut $ctype) -> $owned {
76                 $owned(ptr)
77             }
78 
79             #[inline]
80             fn as_ptr(&self) -> *mut $ctype {
81                 self.0
82             }
83         }
84 
85         impl Drop for $owned {
86             #[inline]
87             fn drop(&mut self) {
88                 unsafe { $drop(self.0) }
89             }
90         }
91 
92         // * owned -> * Deref::deref(&owned) -> * &borrowed -> borrowed
93         impl core::ops::Deref for $owned {
94             type Target = $borrowed;
95 
96             #[inline]
97             fn deref(&self) -> &$borrowed {
98                 unsafe{ crate::util::c_openssl::foreign::ForeignRef::from_ptr(self.0) }
99             }
100         }
101 
102         // * owned -> * DerefMut::deref_mut(&mut owned) -> * &mut borrowed -> mut borrowed
103         impl core::ops::DerefMut for $owned {
104             #[inline]
105             fn deref_mut(&mut self) -> &mut $borrowed {
106                 unsafe{ crate::util::c_openssl::foreign::ForeignRef::from_ptr_mut(self.0) }
107             }
108         }
109 
110         // owned.borrow -> & borrowed
111         impl std::borrow::Borrow<$borrowed> for $owned {
112             #[inline]
113             fn borrow(&self) -> &$borrowed {
114                 &**self
115             }
116         }
117 
118         // owned.as_ref -> & borrowed
119         impl AsRef<$borrowed> for $owned {
120             #[inline]
121             fn as_ref(&self) -> &$borrowed {
122                 &**self
123             }
124         }
125 
126         // A type implementing `ForeignRef` should simply be a newtype wrapper around `ForeignRefWrapper`.
127         $(#[$borrow_attr:meta])*
128         pub(crate) struct $borrowed(crate::util::c_openssl::foreign::ForeignRefWrapper);
129 
130         impl crate::util::c_openssl::foreign::ForeignRef for $borrowed {
131             type CStruct = $ctype;
132         }
133 
134         // Unsate Send and Sync mark.
135         unsafe impl Send for $owned {}
136         unsafe impl Send for $borrowed {}
137         unsafe impl Sync for $owned {}
138         unsafe impl Sync for $borrowed {}
139     };
140 }
141