wolf_crypto/
ptr.rs

1#![allow(dead_code)] // WIP
2
3use core::ops;
4use core::fmt;
5
6#[repr(transparent)]
7pub struct MutPtr<T> {
8    inner: *mut T
9}
10
11impl<T> MutPtr<T> {
12    #[cfg(debug_assertions)]
13    #[inline]
14    #[track_caller]
15    pub fn new(inner: *mut T) -> Self {
16        assert!(!inner.is_null(), "`MutPtr` initialized with null pointer");
17        Self { inner }
18    }
19
20    #[cfg(not(debug_assertions))]
21    #[inline]
22    pub const fn new(inner: *mut T) -> Self {
23        unsafe { core::mem::transmute(inner) }
24    }
25
26    #[cfg(debug_assertions)]
27    #[inline]
28    #[track_caller]
29    pub fn assert_not_null(&self) {
30        assert!(
31            !self.inner.is_null(),
32            "`MutPtr` was null under safe operation, this is not allowed"
33        );
34    }
35
36    #[cfg(not(debug_assertions))]
37    #[inline(always)]
38    pub const fn assert_not_null(&self) {}
39
40    #[inline]
41    pub const unsafe fn null() -> Self {
42        Self { inner: core::ptr::null_mut() }
43    }
44
45    #[inline]
46    pub const unsafe fn get_unchecked(&self) -> *mut T {
47        self.inner
48    }
49
50    #[cfg(debug_assertions)]
51    #[inline]
52    #[track_caller]
53    pub fn get(&self) -> *mut T {
54        self.assert_not_null();
55        self.inner
56    }
57
58    #[cfg(not(debug_assertions))]
59    #[inline]
60    pub const fn get(&self) -> *mut T {
61        self.inner
62    }
63
64    // Not unsafe as MutPtr copy is unsafe, we consume the type to prevent any further aliasing.
65    #[inline]
66    #[cfg_attr(debug_assertions, track_caller)]
67    pub fn into_const(self) -> ConstPtr<T> {
68        ConstPtr::new(self.inner.cast_const())
69    }
70
71    #[cfg_attr(not(debug_assertions), inline(always))]
72    #[cfg_attr(debug_assertions, track_caller)]
73    pub unsafe fn copy(&self) -> Self {
74        Self::new(self.inner)
75    }
76}
77
78impl<T> ops::Deref for MutPtr<T> {
79    type Target = T;
80
81    #[cfg_attr(debug_assertions, track_caller)]
82    #[inline]
83    fn deref(&self) -> &Self::Target {
84        unsafe { &*self.get() }
85    }
86}
87
88impl<T> ops::DerefMut for MutPtr<T> {
89    #[cfg_attr(debug_assertions, track_caller)]
90    #[inline]
91    fn deref_mut(&mut self) -> &mut Self::Target {
92        unsafe { &mut *self.get() }
93    }
94}
95
96impl<T> fmt::Debug for MutPtr<T> {
97    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98        write!(f, "MutPtr {{ is_null: {} }}", self.inner.is_null())
99    }
100}
101
102#[repr(transparent)]
103pub struct ConstPtr<T> {
104    inner: *const T
105}
106
107impl<T> ConstPtr<T> {
108    #[cfg(debug_assertions)]
109    #[inline]
110    #[track_caller]
111    pub fn new(inner: *const T) -> Self {
112        assert!(!inner.is_null(), "`ConstPtr` initialized with null pointer");
113        Self { inner }
114    }
115
116    #[cfg(not(debug_assertions))]
117    #[inline]
118    pub const fn new(inner: *const T) -> Self {
119        unsafe { core::mem::transmute(inner) }
120    }
121
122    #[cfg(debug_assertions)]
123    #[inline]
124    #[track_caller]
125    pub fn assert_not_null(&self) {
126        assert!(
127            !self.inner.is_null(),
128            "`ConstPtr` was null under safe operation, this is not allowed"
129        );
130    }
131
132    #[cfg(not(debug_assertions))]
133    #[inline(always)]
134    pub const fn assert_not_null(&self) {}
135
136    #[inline]
137    pub const unsafe fn null() -> Self {
138        Self { inner: core::ptr::null() }
139    }
140
141    #[inline]
142    pub const unsafe fn get_unchecked(&self) -> *const T {
143        self.inner
144    }
145
146    #[cfg(debug_assertions)]
147    #[inline]
148    #[track_caller]
149    pub fn get(&self) -> *const T {
150        self.assert_not_null();
151        self.inner
152    }
153
154    #[cfg(not(debug_assertions))]
155    #[inline]
156    pub const fn get(&self) -> *const T {
157        self.inner
158    }
159
160    // unsafe as copy for ConstPtr is not unsafe, mutable aliasing invariant.
161    #[inline]
162    #[cfg_attr(debug_assertions, track_caller)]
163    pub unsafe fn into_mut(self) -> MutPtr<T> {
164        MutPtr::new(self.inner.cast_mut())
165    }
166
167    #[cfg_attr(not(debug_assertions), inline(always))]
168    #[cfg_attr(debug_assertions, track_caller)]
169    pub fn copy(&self) -> Self {
170        Self::new(self.inner)
171    }
172}
173
174impl<T> ops::Deref for ConstPtr<T> {
175    type Target = T;
176
177    #[cfg_attr(debug_assertions, track_caller)]
178    #[inline]
179    fn deref(&self) -> &Self::Target {
180        unsafe { &*self.get() }
181    }
182}
183
184impl<T> fmt::Debug for ConstPtr<T> {
185    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186        write!(f, "ConstPtr {{ is_null: {} }}", self.inner.is_null())
187    }
188}