1use core::{alloc::Layout, marker::PhantomData};
2
3use super::{field_layout::FieldLayout, manager::Dealloc, object::Object};
4
5#[repr(transparent)]
6pub struct Block<T: Object, D: Dealloc> {
7 pub header: D::BlockHeader,
8 _0: PhantomData<T>,
9}
10
11impl<T: Object, D: Dealloc> Block<T, D> {
12 const BLOCK_HEADER_LAYOUT: FieldLayout<D::BlockHeader, T> =
13 FieldLayout::align_to(T::OBJECT_ALIGN);
14 #[inline(always)]
15 pub const fn block_layout(object_size: usize) -> Layout {
16 Self::BLOCK_HEADER_LAYOUT.layout(object_size)
17 }
18 pub unsafe fn delete(&mut self) {
19 let object = self.object_mut();
20 let object_size = object.object_size();
21 object.object_drop();
22 D::dealloc(self as *mut _ as *mut u8, Self::block_layout(object_size));
23 }
24 #[inline(always)]
25 pub fn object(&self) -> &T {
26 unsafe { &*Self::BLOCK_HEADER_LAYOUT.to_adjacent(&self.header) }
27 }
28 #[inline(always)]
29 pub fn object_mut(&mut self) -> &mut T {
30 unsafe { &mut *Self::BLOCK_HEADER_LAYOUT.into_adjacent_mut(&mut self.header) }
31 }
32}
33
34#[cfg(test)]
35mod test {
36 use core::{alloc::Layout, cell::Cell, marker::PhantomData};
37
38 use wasm_bindgen_test::wasm_bindgen_test;
39
40 use crate::mem::{
41 block::Block, fixed::Fixed, manager::Dealloc, object::Object,
42 ref_counter_update::RefCounterUpdate,
43 };
44
45 use super::super::block_header::BlockHeader;
46
47 #[derive(Debug)]
48 struct M();
49
50 impl Dealloc for M {
51 type BlockHeader = BH;
52 unsafe fn dealloc(_: *mut u8, _: Layout) {}
53 }
54
55 #[derive(Default)]
56 struct BH();
57
58 impl BlockHeader for BH {
59 unsafe fn ref_counter_update(&self, _: RefCounterUpdate) -> isize {
60 todo!()
61 }
62 }
63
64 #[test]
65 #[wasm_bindgen_test]
66 fn test_0() {
67 assert_eq!(Block::<Fixed<()>, M>::block_layout(0).size(), 0);
68 assert_eq!(Block::<Fixed<()>, M>::block_layout(0).align(), 1);
69 assert_eq!(Block::<Fixed<()>, M>::block_layout(2).size(), 2);
70 assert_eq!(Block::<Fixed<()>, M>::block_layout(2).align(), 1);
71 let mut b = Block::<Fixed<()>, M> {
72 header: BH::default(),
73 _0: Default::default(),
74 };
75 assert_eq!(b.object().object_size(), 0);
76 let x = b.object_mut();
77 assert_eq!(x.object_size(), 0);
78 unsafe { b.delete() };
79 }
80
81 #[test]
82 #[wasm_bindgen_test]
83 fn test() {
84 #[derive(Default)]
85 struct Xbh(Cell<isize>);
86
87 #[derive(Debug)]
88 struct D();
89
90 impl Dealloc for D {
91 type BlockHeader = Xbh;
92 unsafe fn dealloc(_: *mut u8, _: Layout) {}
93 }
94
95 impl BlockHeader for Xbh {
96 unsafe fn ref_counter_update(&self, i: RefCounterUpdate) -> isize {
97 let result = self.0.get();
98 self.0.set(result + i as isize);
99 result
100 }
101 }
102
103 let mut x = Block::<Fixed<()>, D> {
104 header: Xbh::default(),
105 _0: PhantomData,
106 };
107 let p = unsafe { x.header.block::<Fixed<()>, D>() };
108 assert_eq!(p as *mut _, (&mut x) as _);
109 unsafe {
110 assert_eq!(x.header.ref_counter_update(RefCounterUpdate::Read), 0);
111 assert_eq!(x.header.ref_counter_update(RefCounterUpdate::AddRef), 0);
112 assert_eq!(x.header.ref_counter_update(RefCounterUpdate::Read), 1);
113 }
114 }
115}