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