1use super::{constructor::Constructor, object::Object};
2
3#[repr(transparent)]
4#[derive(Debug)]
5pub struct Fixed<T>(pub T);
6
7impl<T> Object for Fixed<T> {}
8
9impl<T> Constructor for Fixed<T> {
10 type Result = Fixed<T>;
11 #[inline(always)]
12 fn result_size(&self) -> usize {
13 Self::Result::object_size(self)
14 }
15 #[inline(always)]
16 unsafe fn construct(self, p: *mut Self::Result) {
17 p.write(self);
18 }
19}
20
21#[cfg(test)]
22mod test {
23 use core::{
24 mem::forget,
25 ptr::null,
26 sync::atomic::{AtomicIsize, Ordering},
27 };
28
29 use wasm_bindgen_test::wasm_bindgen_test;
30
31 use super::{Fixed, *};
32
33 #[test]
34 #[wasm_bindgen_test]
35 fn test_object() {
36 let a = Fixed(5);
37 assert_eq!(a.object_size(), 4);
38 }
39
40 struct X<'a>(&'a AtomicIsize);
41
42 impl Object for X<'_> {}
43
44 impl Drop for X<'_> {
45 fn drop(&mut self) {
46 self.0.fetch_add(1, Ordering::Relaxed);
47 }
48 }
49
50 #[test]
51 #[wasm_bindgen_test]
52 fn test_object_drop_in_place() {
53 let a = AtomicIsize::new(5);
54 {
55 let mut x = X(&a);
56 unsafe { x.object_drop() };
57 assert_eq!(a.load(Ordering::Relaxed), 6);
58 forget(x);
59 }
60 assert_eq!(a.load(Ordering::Relaxed), 6);
61 }
62
63 struct Y(*const AtomicIsize);
64
65 impl Drop for Y {
66 fn drop(&mut self) {
67 unsafe { (*self.0).fetch_add(1, Ordering::Relaxed) };
68 }
69 }
70
71 #[test]
72 #[wasm_bindgen_test]
73 fn test_fixed_object_drop_in_place() {
74 let a = AtomicIsize::new(5);
75 {
76 let mut x = Fixed(Y(&a));
77 unsafe { x.object_drop() };
78 assert_eq!(a.load(Ordering::Relaxed), 6);
79 forget(x);
80 }
81 assert_eq!(a.load(Ordering::Relaxed), 6);
82 }
83
84 #[test]
85 #[wasm_bindgen_test]
86 fn test_new_in_place() {
87 let a = AtomicIsize::new(5);
88 {
89 let x = Fixed(Y(&a as *const AtomicIsize));
90 {
91 let mut y = Fixed(Y(null()));
92 unsafe { x.construct(&mut y) };
93 assert_eq!(a.load(Ordering::Relaxed), 5);
94 }
95 assert_eq!(a.load(Ordering::Relaxed), 6);
96 }
97 assert_eq!(a.load(Ordering::Relaxed), 6);
98 }
99}