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