1use core::{cmp::Ordering, fmt, hash, marker::PhantomData, ptr::NonNull};
9
10use crate::{
11 abstract_ptr::AbstractPtr,
12 access::{Access, Copyable, ReadOnly, ReadWrite, RestrictAccess, WriteOnly},
13};
14
15#[must_use]
16#[repr(transparent)]
17pub struct AbstractRef<'a, M, T, A = ReadWrite>
18where
19 T: ?Sized,
20{
21 pointer: NonNull<T>,
22 memory_type: PhantomData<M>,
23 reference: PhantomData<&'a T>,
24 access: PhantomData<A>,
25}
26
27impl<'a, M, T> AbstractRef<'a, M, T>
28where
29 T: ?Sized,
30{
31 pub unsafe fn new(pointer: NonNull<T>) -> Self {
32 unsafe { AbstractRef::new_restricted(ReadWrite, pointer) }
33 }
34
35 pub const unsafe fn new_read_only(pointer: NonNull<T>) -> AbstractRef<'a, M, T, ReadOnly> {
36 unsafe { Self::new_restricted(ReadOnly, pointer) }
37 }
38
39 pub const unsafe fn new_restricted<A>(
40 access: A,
41 pointer: NonNull<T>,
42 ) -> AbstractRef<'a, M, T, A>
43 where
44 A: Access,
45 {
46 let _ = access;
47 unsafe { Self::new_generic(pointer) }
48 }
49
50 pub fn from_ref(reference: &'a T) -> AbstractRef<'a, M, T, ReadOnly>
51 where
52 T: 'a,
53 {
54 unsafe { AbstractRef::new_restricted(ReadOnly, reference.into()) }
55 }
56
57 pub fn from_mut_ref(reference: &'a mut T) -> Self
58 where
59 T: 'a,
60 {
61 unsafe { AbstractRef::new(reference.into()) }
62 }
63
64 const unsafe fn new_generic<A>(pointer: NonNull<T>) -> AbstractRef<'a, M, T, A> {
65 AbstractRef {
66 pointer,
67 memory_type: PhantomData,
68 reference: PhantomData,
69 access: PhantomData,
70 }
71 }
72}
73
74impl<'a, M, T, A> AbstractRef<'a, M, T, A>
75where
76 T: ?Sized,
77{
78 pub fn borrow(&self) -> AbstractRef<'_, M, T, A::Restricted>
79 where
80 A: RestrictAccess<ReadOnly>,
81 {
82 unsafe { AbstractRef::new_restricted(Default::default(), self.pointer) }
83 }
84
85 pub fn borrow_mut(&mut self) -> AbstractRef<'_, M, T, A>
86 where
87 A: Access,
88 {
89 unsafe { AbstractRef::new_restricted(Default::default(), self.pointer) }
90 }
91
92 pub fn as_ptr(&self) -> AbstractPtr<'_, M, T, A::Restricted>
93 where
94 A: RestrictAccess<ReadOnly>,
95 {
96 unsafe { AbstractPtr::new_restricted(Default::default(), self.pointer) }
97 }
98
99 pub fn as_mut_ptr(&mut self) -> AbstractPtr<'_, M, T, A>
100 where
101 A: Access,
102 {
103 unsafe { AbstractPtr::new_restricted(Default::default(), self.pointer) }
104 }
105
106 pub fn into_ptr(self) -> AbstractPtr<'a, M, T, A>
107 where
108 A: Access,
109 {
110 unsafe { AbstractPtr::new_restricted(Default::default(), self.pointer) }
111 }
112}
113
114impl<'a, M, T, A> AbstractRef<'a, M, T, A>
115where
116 T: ?Sized,
117{
118 pub fn restrict<To>(self) -> AbstractRef<'a, M, T, A::Restricted>
119 where
120 A: RestrictAccess<To>,
121 {
122 unsafe { AbstractRef::new_restricted(Default::default(), self.pointer) }
123 }
124}
125
126impl<'a, M, T> AbstractRef<'a, M, T, ReadWrite>
127where
128 T: ?Sized,
129{
130 pub fn read_only(self) -> AbstractRef<'a, M, T, ReadOnly> {
131 self.restrict()
132 }
133
134 pub fn write_only(self) -> AbstractRef<'a, M, T, WriteOnly> {
135 self.restrict()
136 }
137}
138
139impl<M, T, A> Clone for AbstractRef<'_, M, T, A>
140where
141 T: ?Sized,
142 A: Access + Copyable,
143{
144 fn clone(&self) -> Self {
145 *self
146 }
147}
148
149impl<M, T, A> Copy for AbstractRef<'_, M, T, A>
150where
151 T: ?Sized,
152 A: Access + Copyable,
153{
154}
155
156unsafe impl<M, T, A> Send for AbstractRef<'_, M, T, A> where T: Sync + ?Sized {}
157unsafe impl<M, T, A> Sync for AbstractRef<'_, M, T, A> where T: Sync + ?Sized {}
158
159impl<M, T, A> fmt::Debug for AbstractRef<'_, M, T, A>
160where
161 T: ?Sized,
162{
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 self.pointer.fmt(f)
165 }
166}
167
168impl<M, T, A> fmt::Pointer for AbstractRef<'_, M, T, A>
169where
170 T: ?Sized,
171{
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 self.pointer.fmt(f)
174 }
175}
176
177impl<M, T, A> PartialEq for AbstractRef<'_, M, T, A>
178where
179 T: ?Sized,
180{
181 #[allow(ambiguous_wide_pointer_comparisons)]
182 fn eq(&self, other: &Self) -> bool {
183 self.pointer.eq(&other.pointer)
184 }
185}
186
187impl<M, T, A> Eq for AbstractRef<'_, M, T, A> where T: ?Sized {}
188
189impl<M, T, A> PartialOrd for AbstractRef<'_, M, T, A>
190where
191 T: ?Sized,
192{
193 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
194 Some(self.cmp(other))
195 }
196}
197
198impl<M, T, A> Ord for AbstractRef<'_, M, T, A>
199where
200 T: ?Sized,
201{
202 #[allow(ambiguous_wide_pointer_comparisons)]
203 fn cmp(&self, other: &Self) -> Ordering {
204 self.pointer.cmp(&other.pointer)
205 }
206}
207
208impl<M, T, A> hash::Hash for AbstractRef<'_, M, T, A>
209where
210 T: ?Sized,
211{
212 fn hash<H: hash::Hasher>(&self, state: &mut H) {
213 self.pointer.hash(state);
214 }
215}