sel4_abstract_ptr/
abstract_ref.rs

1//
2// Copyright 2024, Colias Group, LLC
3// Copyright (c) 2020 Philipp Oppermann
4//
5// SPDX-License-Identifier: MIT OR Apache-2.0
6//
7
8use 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}