nanvm_lib/mem/
fixed.rs

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}