1use twizzler_rt_abi::object::ObjectHandle;
2
3use super::{Allocator, OwnedGlobalPtr};
4use crate::{
5 marker::Invariant,
6 ptr::{GlobalPtr, InvPtr, Ref},
7};
8
9pub struct InvBox<T: Invariant, Alloc: Allocator> {
10 raw: InvPtr<T>,
11 alloc: Alloc,
12}
13
14impl<T: Invariant, Alloc: Allocator> InvBox<T, Alloc> {
15 pub unsafe fn from_invptr(raw: InvPtr<T>, alloc: Alloc) -> Self {
16 Self { raw, alloc }
17 }
18
19 pub fn new_in(tx: impl AsRef<ObjectHandle>, val: T, alloc: Alloc) -> crate::Result<Self> {
20 let p = alloc.alloc_with(|r| Ok(r.write(val)))?;
21 let ogp = unsafe { OwnedGlobalPtr::from_global(p.cast(), alloc) };
22 Self::from_in(tx, ogp)
23 }
24
25 pub fn from_in(
26 tx: impl AsRef<ObjectHandle>,
27 ogp: OwnedGlobalPtr<T, Alloc>,
28 ) -> crate::Result<Self> {
29 let raw = InvPtr::new(tx, ogp.global())?;
30 Ok(Self {
31 raw,
32 alloc: ogp.allocator().clone(),
33 })
34 }
35
36 pub fn resolve(&self) -> Ref<'_, T> {
37 unsafe { self.raw.resolve() }
38 }
39
40 pub fn global(&self) -> GlobalPtr<T> {
41 self.raw.global()
42 }
43
44 pub fn as_ptr(&self) -> &InvPtr<T> {
45 &self.raw
46 }
47
48 pub fn alloc(&self) -> &Alloc {
49 &self.alloc
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use twizzler_derive::BaseType;
56
57 use super::InvBox;
58 use crate::{
59 alloc::arena::{ArenaAllocator, ArenaObject},
60 object::{ObjectBuilder, TypedObject},
61 };
62
63 #[derive(BaseType)]
64 struct Foo {
65 x: InvBox<u32, ArenaAllocator>,
66 }
67
68 #[test]
69 fn box_simple() {
70 let arena = ArenaObject::new(ObjectBuilder::default()).unwrap();
71 let alloc = arena.allocator();
72 let mut tx = arena.into_tx().unwrap();
73 let foo = tx
74 .alloc(Foo {
75 x: InvBox::new_in(&tx, 3, alloc).unwrap(),
76 })
77 .unwrap();
78
79 let base = foo.resolve();
80 assert_eq!(*base.x.resolve(), 3);
81 }
82
83 #[test]
84 fn box_alloc_builder() {
85 let alloc = ArenaObject::new(ObjectBuilder::default()).unwrap();
86 let foo = alloc
87 .alloc_inplace(|tx| {
88 let foo = Foo {
89 x: InvBox::new_in(&tx, 3, alloc.allocator()).unwrap(),
90 };
91 Ok(tx.write(foo))
92 })
93 .unwrap();
94 let foo = foo.resolve();
95 assert_eq!(*foo.x.resolve(), 3);
96 }
97
98 #[test]
99 fn box_simple_builder() {
100 let builder = ObjectBuilder::<Foo>::default();
101 let alloc = ArenaObject::new(ObjectBuilder::default()).unwrap();
102 let obj = builder
103 .build_inplace(|tx| {
104 let x = InvBox::new_in(&tx, 3, alloc.allocator()).unwrap();
105 tx.write(Foo { x })
106 })
107 .unwrap();
108 let base = obj.base();
109 assert_eq!(*base.x.resolve(), 3);
110 assert_eq!(*base.x.resolve(), 3);
112 assert_eq!(*base.x.resolve(), 3);
113 assert_eq!(*base.x.resolve(), 3);
114 }
115}