twizzler/ptr/
global.rs

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