sel4_abstract_ptr/abstract_ptr/
operations.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::{marker::PhantomData, ptr::NonNull};
9
10use crate::{
11    access::{Access, ReadOnly, ReadWrite, Readable, RestrictAccess, Writable, WriteOnly},
12    memory_type::UnitaryOps,
13    AbstractPtr,
14};
15
16/// Constructor functions.
17impl<'a, M, T> AbstractPtr<'a, M, T>
18where
19    T: ?Sized,
20{
21    pub unsafe fn new(pointer: NonNull<T>) -> AbstractPtr<'a, M, T, ReadWrite> {
22        unsafe { AbstractPtr::new_restricted(ReadWrite, pointer) }
23    }
24
25    pub const unsafe fn new_read_only(pointer: NonNull<T>) -> AbstractPtr<'a, M, T, ReadOnly> {
26        unsafe { Self::new_restricted(ReadOnly, pointer) }
27    }
28
29    pub const unsafe fn new_restricted<A>(
30        access: A,
31        pointer: NonNull<T>,
32    ) -> AbstractPtr<'a, M, T, A>
33    where
34        A: Access,
35    {
36        let _ = access;
37        unsafe { Self::new_generic(pointer) }
38    }
39
40    pub(super) const unsafe fn new_generic<A>(pointer: NonNull<T>) -> AbstractPtr<'a, M, T, A> {
41        AbstractPtr {
42            pointer,
43            memory_type: PhantomData,
44            reference: PhantomData,
45            access: PhantomData,
46        }
47    }
48}
49
50impl<'a, M, T, A> AbstractPtr<'a, M, T, A>
51where
52    T: ?Sized,
53{
54    #[must_use]
55    pub fn read(self) -> T
56    where
57        M: UnitaryOps<T>,
58        T: Sized,
59        A: Readable,
60    {
61        unsafe { M::read(self.pointer.as_ptr()) }
62    }
63
64    pub fn write(self, value: T)
65    where
66        M: UnitaryOps<T>,
67        T: Sized,
68        A: Writable,
69    {
70        unsafe { M::write(self.pointer.as_ptr(), value) };
71    }
72
73    pub fn update<F>(self, f: F)
74    where
75        M: UnitaryOps<T>,
76        T: Sized,
77        A: Readable + Writable,
78        F: FnOnce(T) -> T,
79    {
80        let new = f(self.read());
81        self.write(new);
82    }
83
84    #[must_use]
85    pub fn as_raw_ptr(self) -> NonNull<T> {
86        self.pointer
87    }
88
89    pub unsafe fn map<F, U>(self, f: F) -> AbstractPtr<'a, M, U, A>
90    where
91        F: FnOnce(NonNull<T>) -> NonNull<U>,
92        A: Access,
93        U: ?Sized,
94    {
95        unsafe { AbstractPtr::new_restricted(A::default(), f(self.pointer)) }
96    }
97}
98
99/// Methods for restricting access.
100impl<'a, M, T, A> AbstractPtr<'a, M, T, A>
101where
102    T: ?Sized,
103{
104    pub fn restrict<To>(self) -> AbstractPtr<'a, M, T, A::Restricted>
105    where
106        A: RestrictAccess<To>,
107    {
108        unsafe { AbstractPtr::new_restricted(Default::default(), self.pointer) }
109    }
110}
111
112/// Methods for restricting access.
113impl<'a, M, T> AbstractPtr<'a, M, T, ReadWrite>
114where
115    T: ?Sized,
116{
117    pub fn read_only(self) -> AbstractPtr<'a, M, T, ReadOnly> {
118        self.restrict()
119    }
120
121    pub fn write_only(self) -> AbstractPtr<'a, M, T, WriteOnly> {
122        self.restrict()
123    }
124}