twizzler/ptr/
global.rs

1use core::fmt::Debug;
2use std::marker::PhantomData;
3
4use twizzler_rt_abi::object::{MapFlags, ObjID, ObjectHandle};
5
6use super::{Ref, RefMut};
7use crate::{marker::Invariant, object::RawObject};
8
9#[derive(Default, PartialOrd, Ord, Hash)]
10/// A global pointer, containing a fully qualified object ID and offset.
11pub struct GlobalPtr<T> {
12    id: ObjID,
13    offset: u64,
14    _pd: PhantomData<*const T>,
15}
16
17impl<T> Eq for GlobalPtr<T> {}
18
19impl<T> PartialEq for GlobalPtr<T> {
20    fn eq(&self, other: &Self) -> bool {
21        self.id == other.id && self.offset() == other.offset()
22    }
23}
24
25unsafe impl<T: Invariant> Invariant for GlobalPtr<T> {}
26
27impl<T> Debug for GlobalPtr<T> {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        f.debug_struct("GlobalPtr")
30            .field("id", &self.id())
31            .field("offset", &self.offset())
32            .finish()
33    }
34}
35
36impl<T> GlobalPtr<T> {
37    /// Creates a new global pointer.
38    pub fn new(id: ObjID, offset: u64) -> Self {
39        Self {
40            id,
41            offset,
42            _pd: PhantomData,
43        }
44    }
45
46    /// Casts the global pointer to a different type.
47    pub fn cast<U>(self) -> GlobalPtr<U> {
48        GlobalPtr::new(self.id, self.offset)
49    }
50
51    /// Checks if the global pointer is local from the perspective of a given object.
52    pub fn is_local(&self, place: impl AsRef<ObjectHandle>) -> bool {
53        place.as_ref().id() == self.id()
54    }
55
56    /// Resolve a global pointer into a reference.
57    ///
58    /// # Safety
59    /// The underlying object must not mutate while the reference exists, unless
60    /// the underlying type is Sync + Send. The memory referenced by the pointer
61    /// must have an valid representation of the type.
62    pub unsafe fn resolve_stable(&self) -> Ref<'_, T> {
63        let handle = twizzler_rt_abi::object::twz_rt_map_object(
64            self.id(),
65            MapFlags::READ | MapFlags::INDIRECT,
66        )
67        .expect("failed to map global pointer object");
68        let ptr = handle
69            .lea(self.offset() as usize, size_of::<T>())
70            .expect("failed to resolve global pointer");
71        Ref::from_handle(handle, ptr.cast())
72    }
73
74    /// Resolve a global pointer into a reference.
75    ///
76    /// # Safety
77    /// The underlying object must not mutate while the reference exists, unless
78    /// the underlying type is Sync + Send. The memory referenced by the pointer
79    /// must have an valid representation of the type.
80    pub unsafe fn resolve(&self) -> Ref<'_, T> {
81        let handle = twizzler_rt_abi::object::twz_rt_map_object(self.id(), MapFlags::READ)
82            .expect("failed to map global pointer object");
83        let ptr = handle
84            .lea(self.offset() as usize, size_of::<T>())
85            .expect("failed to resolve global pointer");
86        Ref::from_handle(handle, ptr.cast())
87    }
88
89    /// Resolve a global pointer into a reference.
90    ///
91    /// # Safety
92    /// The underlying object must not mutate while the reference exists, unless
93    /// the underlying type is Sync + Send. The memory referenced by the pointer
94    /// must have an valid representation of the type. No other references may be
95    /// alive referring to the underlying data.
96    pub unsafe fn resolve_mut(&self) -> RefMut<'_, T> {
97        let handle = twizzler_rt_abi::object::twz_rt_map_object(
98            self.id(),
99            MapFlags::READ | MapFlags::WRITE | MapFlags::PERSIST,
100        )
101        .expect("failed to map global pointer object");
102        let ptr = handle
103            .lea_mut(self.offset() as usize, size_of::<T>())
104            .expect("failed to resolve global pointer");
105        RefMut::from_handle(handle, ptr.cast())
106    }
107
108    /// Returns true if the global pointer is null.
109    pub fn is_null(&self) -> bool {
110        self.id.raw() == 0
111    }
112
113    /// Returns the object ID of the global pointer.
114    pub fn id(&self) -> ObjID {
115        self.id
116    }
117
118    /// Returns the offset of the global pointer.
119    pub fn offset(&self) -> u64 {
120        self.offset
121    }
122}
123
124impl<T> Clone for GlobalPtr<T> {
125    fn clone(&self) -> Self {
126        Self {
127            id: self.id,
128            offset: self.offset,
129            _pd: PhantomData,
130        }
131    }
132}
133
134impl<T> Copy for GlobalPtr<T> {}