twizzler/object/
object.rs

1use std::marker::PhantomData;
2
3use twizzler_abi::object::ObjID;
4use twizzler_rt_abi::{
5    object::{MapFlags, ObjectHandle},
6    Result,
7};
8
9use super::{MutObject, RawObject, TxObject, TypedObject};
10use crate::{marker::BaseType, ptr::Ref, util::maybe_remap};
11
12#[derive(Debug)]
13pub struct Object<Base> {
14    handle: ObjectHandle,
15    _pd: PhantomData<*const Base>,
16}
17
18unsafe impl<Base> Sync for Object<Base> {}
19unsafe impl<Base> Send for Object<Base> {}
20
21impl<B> Clone for Object<B> {
22    fn clone(&self) -> Self {
23        Self {
24            handle: self.handle.clone(),
25            _pd: PhantomData,
26        }
27    }
28}
29
30impl<Base> Object<Base> {
31    /// Start a transaction on this object, turning this object into a transaction object handle.
32    ///
33    /// # Example
34    /// ```
35    /// # use twizzler::object::ObjectBuilder;
36    ///
37    /// let obj = ObjectBuilder::new().build(12u32).unwrap();
38    /// let tx_obj = obj.into_tx().unwrap();
39    /// tx_obj.base_mut() += 1;
40    /// ```
41    pub fn into_tx(self) -> Result<TxObject<Base>> {
42        TxObject::new(self)
43    }
44
45    /// Start a transaction on this object, creating a new transaction object handle.
46    ///
47    /// # Example
48    /// ```
49    /// # use twizzler::object::ObjectBuilder;
50    ///
51    /// let obj = ObjectBuilder::new().build(12u32).unwrap();
52    /// let tx_obj = obj.as_tx().unwrap();
53    /// tx_obj.base_mut() += 1;
54    /// ```
55    pub fn as_tx(&self) -> Result<TxObject<Base>> {
56        TxObject::new(self.clone())
57    }
58
59    /// Perform a transaction on this object, within the provided closure.
60    ///
61    /// # Example
62    /// ```
63    /// # use twizzler::object::ObjectBuilder;
64    ///
65    /// let obj = ObjectBuilderrstarst::new().build(12u32).unwrap();
66    /// obj.with_tx(|tx| tx.base_mut() += 1).unwrap();
67    /// ```
68    pub fn with_tx<R>(&mut self, f: impl FnOnce(&mut TxObject<Base>) -> Result<R>) -> Result<R> {
69        let mut tx = self.as_tx()?;
70        let r = f(&mut tx)?;
71        let _ = self
72            .update()
73            .inspect_err(|e| tracing::warn!("failed to update {} on with_tx: {}", self.id(), e));
74        Ok(r)
75    }
76
77    /// Create a new mutable object handle from this object.
78    ///
79    /// # Safety
80    /// The caller must ensure that the underlying object is not changed
81    /// outside of this mapping.
82    pub unsafe fn as_mut(&self) -> Result<MutObject<Base>> {
83        let (handle, _) = maybe_remap(self.handle().clone(), core::ptr::null_mut::<()>());
84        Ok(unsafe { MutObject::from_handle_unchecked(handle) })
85    }
86
87    /// Create a new mutable object handle from this object.
88    ///
89    /// # Safety
90    /// The caller must ensure that the underlying object is not changed
91    /// outside of this mapping.
92    pub unsafe fn into_mut(self) -> Result<MutObject<Base>> {
93        let (handle, _) = maybe_remap(self.into_handle(), core::ptr::null_mut::<()>());
94        Ok(unsafe { MutObject::from_handle_unchecked(handle) })
95    }
96
97    pub unsafe fn from_handle_unchecked(handle: ObjectHandle) -> Self {
98        Self {
99            handle,
100            _pd: PhantomData,
101        }
102    }
103
104    pub fn from_handle(handle: ObjectHandle) -> Result<Self> {
105        // TODO: check base fingerprint
106        unsafe { Ok(Self::from_handle_unchecked(handle)) }
107    }
108
109    pub fn into_handle(self) -> ObjectHandle {
110        self.handle
111    }
112
113    pub unsafe fn cast<U>(self) -> Object<U> {
114        Object {
115            handle: self.handle,
116            _pd: PhantomData,
117        }
118    }
119
120    /// Open a new object from its ID.
121    ///
122    /// The provided map flags must contain at least READ, and for stable
123    /// read maps, INDIRECT. For writes, add WRITE and PERSIST.
124    ///
125    /// This function checks the underlying fingerprint of the base type against
126    /// the stored value and fails on mismatch to ensure type safety.
127    pub fn map(id: ObjID, flags: MapFlags) -> Result<Self> {
128        // TODO: check base fingerprint
129        let handle = twizzler_rt_abi::object::twz_rt_map_object(id, flags)?;
130        tracing::debug!("map: {} {:?} => {:?}", id, flags, handle.start());
131        Self::from_handle(handle)
132    }
133
134    /// Open a new object from its ID without checking the underlying fingerprint.
135    ///
136    /// # Safety
137    /// This function is unsafe because it does not check the underlying fingerprint
138    /// of the base type against the stored value. Use with caution.
139    pub unsafe fn map_unchecked(id: ObjID, flags: MapFlags) -> Result<Self> {
140        let handle = twizzler_rt_abi::object::twz_rt_map_object(id, flags)?;
141        unsafe { Ok(Self::from_handle_unchecked(handle)) }
142    }
143
144    /// Return the ID of the object.
145    pub fn id(&self) -> ObjID {
146        self.handle.id()
147    }
148
149    /// Update the underlying mapping of the object. This invalidates all references to
150    /// the object (hence why it takes &mut self).
151    pub fn update(&mut self) -> Result<()> {
152        twizzler_rt_abi::object::twz_rt_update_handle(&mut self.handle)
153    }
154
155    /// Sync the underlying object.
156    ///
157    /// # Safety
158    /// The caller must ensure that the object is not being concurrently modified by
159    /// another thread, and that the memory is in a valid state to represent the object.
160    pub unsafe fn sync(&mut self) -> Result<()> {
161        self.as_mut()?.sync()
162    }
163}
164
165impl<Base> RawObject for Object<Base> {
166    fn handle(&self) -> &ObjectHandle {
167        &self.handle
168    }
169}
170
171impl<Base: BaseType> TypedObject for Object<Base> {
172    type Base = Base;
173
174    fn base_ref(&self) -> Ref<'_, Self::Base> {
175        let base = self.base_ptr();
176        unsafe { Ref::from_raw_parts(base, self.handle()) }
177    }
178
179    #[inline]
180    fn base(&self) -> &Self::Base {
181        unsafe { self.base_ptr::<Self::Base>().as_ref().unwrap_unchecked() }
182    }
183}
184
185impl<T> AsRef<ObjectHandle> for Object<T> {
186    fn as_ref(&self) -> &ObjectHandle {
187        self.handle()
188    }
189}