twizzler/object/
builder.rs1use std::{marker::PhantomData, mem::MaybeUninit};
2
3use twizzler_abi::{
4 object::Protections,
5 syscall::{
6 BackingType, CreateTieSpec, LifetimeType, ObjectCreate, ObjectCreateFlags, ObjectSource,
7 },
8};
9use twizzler_rt_abi::object::MapFlags;
10
11use super::{Object, TxObject};
12use crate::{
13 marker::{BaseType, StoreCopy},
14 Result,
15};
16
17#[derive(Clone)]
19pub struct ObjectBuilder<Base: BaseType> {
20 spec: ObjectCreate,
21 src_objs: Vec<ObjectSource>,
22 ties: Vec<CreateTieSpec>,
23 _pd: PhantomData<Base>,
24}
25
26impl<Base: BaseType> ObjectBuilder<Base> {
27 pub fn new(spec: ObjectCreate) -> Self {
29 Self {
30 spec,
31 _pd: PhantomData,
32 src_objs: Vec::new(),
33 ties: Vec::new(),
34 }
35 }
36
37 pub fn persist(mut self) -> Self {
39 self.spec.lt = LifetimeType::Persistent;
40 self
41 }
42
43 pub fn cast<U: BaseType>(self) -> ObjectBuilder<U> {
45 ObjectBuilder::<U>::new(self.spec)
46 }
47
48 pub fn add_src(mut self, obj_src: ObjectSource) -> Self {
50 self.src_objs.push(obj_src);
51 self
52 }
53
54 pub fn add_tie(mut self, tie: CreateTieSpec) -> Self {
56 self.ties.push(tie);
57 self
58 }
59}
60
61impl<Base: BaseType + StoreCopy> ObjectBuilder<Base> {
62 pub fn build(&self, base: Base) -> Result<Object<Base>> {
70 self.build_inplace(|tx| tx.write(base))
71 }
72}
73
74impl<Base: BaseType> ObjectBuilder<Base> {
75 pub fn build_inplace<F>(&self, ctor: F) -> Result<Object<Base>>
86 where
87 F: FnOnce(TxObject<MaybeUninit<Base>>) -> Result<TxObject<Base>>,
88 {
89 let id = twizzler_abi::syscall::sys_object_create(
90 self.spec,
91 self.src_objs.as_slice(),
92 self.ties.as_slice(),
93 )?;
94 let mut flags = MapFlags::READ | MapFlags::WRITE;
95 if self.spec.lt == LifetimeType::Persistent {
96 flags.insert(MapFlags::PERSIST);
97 }
98 let mu_object = unsafe { Object::<MaybeUninit<Base>>::map_unchecked(id, flags) }?;
99 let object = ctor(mu_object.into_tx()?)?;
100 object.into_object()
101 }
102
103 pub unsafe fn build_ctor<F>(&self, ctor: F) -> Result<Object<Base>>
125 where
126 F: FnOnce(&mut TxObject<MaybeUninit<Base>>),
127 {
128 self.build_inplace(|mut tx| {
129 ctor(&mut tx);
130 Ok(tx.assume_init())
131 })
132 }
133}
134
135impl<Base: BaseType> Default for ObjectBuilder<Base> {
136 fn default() -> Self {
137 Self::new(ObjectCreate::new(
138 BackingType::Normal,
139 LifetimeType::Volatile,
140 None,
141 ObjectCreateFlags::empty(),
142 Protections::all(),
143 ))
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::ObjectBuilder;
150 use crate::{marker::BaseType, object::TypedObject, ptr::InvPtr};
151
152 #[test]
153 fn builder_simple() {
154 let builder = ObjectBuilder::default();
155 let obj = builder.build(42u32).unwrap();
156 let base = obj.base();
157 assert_eq!(*base, 42);
158 }
159
160 struct Foo {
161 ptr: InvPtr<u32>,
162 }
163 impl BaseType for Foo {}
164
165 #[test]
166 fn builder_complex() {
167 let builder = ObjectBuilder::default();
168 let obj_1 = builder.build(42u32).unwrap();
169 let base = obj_1.base_ref();
170 assert_eq!(*base, 42);
171
172 let builder = ObjectBuilder::<Foo>::default();
173 let obj = builder
174 .build_inplace(|tx| {
175 let foo = Foo {
176 ptr: InvPtr::new(&tx, base)?,
177 };
178 tx.write(foo)
179 })
180 .unwrap();
181 let base_foo = obj.base();
182 let r = unsafe { base_foo.ptr.resolve() };
183 assert_eq!(*r, 42);
184 }
185}