nanvm_lib/mem/flexible_array/
constructor.rs

1use crate::{common::ref_mut::RefMut, mem::constructor::Constructor};
2
3use super::{header::FlexibleArrayHeader, FlexibleArray};
4
5pub struct FlexibleArrayConstructor<H: FlexibleArrayHeader, I: Iterator> {
6    header: H,
7    items: I,
8}
9
10impl<H: FlexibleArrayHeader, I: Iterator> FlexibleArrayConstructor<H, I> {
11    pub fn new(header: H, items: I) -> Self {
12        Self { header, items }
13    }
14}
15
16impl<H: FlexibleArrayHeader, I: Iterator> Constructor for FlexibleArrayConstructor<H, I> {
17    type Result = FlexibleArray<I::Item, H>;
18    #[inline(always)]
19    fn result_size(&self) -> usize {
20        Self::Result::flexible_size(self.header.len())
21    }
22    unsafe fn construct(self, p: *mut Self::Result) {
23        let v = &mut *p;
24        v.header.to_mut_ptr().write(self.header);
25        let mut src = self.items;
26        for dst in v.items_mut() {
27            dst.to_mut_ptr().write(src.next().unwrap());
28        }
29    }
30}
31
32impl<I: ExactSizeIterator> From<I> for FlexibleArrayConstructor<usize, I> {
33    #[inline(always)]
34    fn from(items: I) -> Self {
35        items.len().constructor(items)
36    }
37}
38
39#[cfg(test)]
40mod test {
41    use core::{mem::size_of, ptr::null_mut};
42
43    use wasm_bindgen_test::wasm_bindgen_test;
44
45    use crate::{
46        common::ref_mut::RefMut,
47        mem::{
48            constructor::Constructor, flexible_array::header::FlexibleArrayHeader, object::Object,
49        },
50    };
51
52    use super::FlexibleArrayConstructor;
53
54    #[repr(C)]
55    struct StaticVariable<T: FlexibleArrayHeader, I, const L: usize> {
56        header: T,
57        items: [I; L],
58    }
59
60    fn gen_test(t: usize) {
61        struct Header(u8, *mut u8);
62        impl Drop for Header {
63            fn drop(&mut self) {
64                unsafe {
65                    *self.1 += 1;
66                }
67            }
68        }
69        impl FlexibleArrayHeader for Header {
70            fn len(&self) -> usize {
71                self.0 as usize
72            }
73        }
74        let mut i = 0;
75        {
76            let new = FlexibleArrayConstructor {
77                header: Header(5, &mut i),
78                items: [42u8, 43, 44, 45, 46, 47, 48].into_iter().take(t),
79            };
80            {
81                let mut mem = StaticVariable::<Header, u8, 5> {
82                    header: Header(0, null_mut()),
83                    items: [0; 5],
84                };
85                let v = unsafe { mem.to_mut_ptr() as *mut _ };
86                unsafe { new.construct(v) };
87                let r = unsafe { &mut *v };
88                assert_eq!(mem.header.len(), 5);
89                assert_eq!(r.header.len(), 5);
90                assert_eq!(mem.header.0, 5);
91                assert_eq!(r.header.0, 5);
92                assert_eq!(mem.header.1, unsafe { i.to_mut_ptr() });
93                assert_eq!(r.header.1, unsafe { i.to_mut_ptr() });
94                assert_eq!(r.object_size(), size_of::<usize>() * 2 + 5);
95                assert_eq!(mem.items, [42, 43, 44, 45, 46]);
96                assert_eq!(r.items_mut(), &[42, 43, 44, 45, 46]);
97                assert_eq!(i, 0);
98                unsafe { (*v).object_drop() };
99                assert_eq!(i, 1);
100            }
101            assert_eq!(i, 2);
102        }
103        assert_eq!(i, 2);
104    }
105
106    #[test]
107    #[wasm_bindgen_test]
108    fn test_5() {
109        gen_test(5);
110    }
111
112    #[test]
113    #[wasm_bindgen_test]
114    fn test_10() {
115        gen_test(10);
116    }
117
118    #[test]
119    #[should_panic]
120    #[wasm_bindgen_test]
121    fn test_2() {
122        gen_test(2);
123    }
124}