wasmi_c_api/
vec.rs

1use crate::{
2    wasm_exporttype_t,
3    wasm_extern_t,
4    wasm_externtype_t,
5    wasm_frame_t,
6    wasm_functype_t,
7    wasm_globaltype_t,
8    wasm_importtype_t,
9    wasm_memorytype_t,
10    wasm_tabletype_t,
11    wasm_val_t,
12    wasm_valtype_t,
13};
14use alloc::{boxed::Box, string::String, vec, vec::Vec};
15use core::{mem::MaybeUninit, ptr, slice};
16
17/// A Wasm name string buffer.
18pub type wasm_name_t = wasm_byte_vec_t;
19
20impl wasm_name_t {
21    pub(crate) fn from_name(name: String) -> wasm_name_t {
22        name.into_bytes().into()
23    }
24}
25
26macro_rules! declare_vecs {
27    (
28        $(
29            struct $name:ident $(<$lt:tt>)? {
30                type element = $elem_ty:ty;
31                fn new: $new:ident;
32                fn empty: $empty:ident;
33                fn uninit: $uninit:ident;
34                fn copy: $copy:ident;
35                fn delete: $delete:ident;
36            }
37        )*
38    ) => {$(
39        #[doc = concat!("A Wasm compatible vector with element type [`", stringify!($elem_ty), "`].")]
40        #[doc = ""]
41        #[doc = "# Note"]
42        #[doc = ""]
43        #[doc = concat!("This is similar to `Box<[", stringify!($elem_ty), "]>`.")]
44        #[repr(C)]
45        pub struct $name $(<$lt>)? {
46            size: usize,
47            data: *mut $elem_ty,
48        }
49
50        impl$(<$lt>)? $name $(<$lt>)? {
51            /// Sets the data buffer of `self` to `buffer` and leaks the current data buffer.
52            pub fn set_buffer(&mut self, buffer: Box<[$elem_ty]>) {
53                let slice = Box::leak(buffer);
54                self.size = slice.len();
55                self.data = slice.as_mut_ptr();
56            }
57
58            /// Returns the underlying data as shared slice.
59            pub fn as_slice(&self) -> &[$elem_ty] {
60                // Note: here we avoid creating a slice with a `null` data pointer
61                //       because this is undefined behavior in Rust.
62                match self.size {
63                    0 => &[],
64                    _ => {
65                        assert!(!self.data.is_null());
66                        unsafe { slice::from_raw_parts(self.data, self.size) }
67                    }
68                }
69            }
70
71            /// Returns the underlying data as [`MaybeUninit`] slice.
72            pub fn as_uninit_slice(&mut self) -> &mut [MaybeUninit<$elem_ty>] {
73                // Note: here we avoid creating a slice with a `null` data pointer
74                //       because this is undefined behavior in Rust.
75                match self.size {
76                    0 => &mut [],
77                    _ => {
78                        assert!(!self.data.is_null());
79                        unsafe { slice::from_raw_parts_mut(self.data as _, self.size) }
80                    }
81                }
82            }
83
84            /// Takes the data from `self` and returns it.
85            ///
86            /// # Note
87            ///
88            /// This leaves `self` empty after this operation.
89            pub fn take(&mut self) -> Box<[$elem_ty]> {
90                if self.data.is_null() {
91                    return [].into();
92                }
93                let vec = unsafe {
94                    Vec::from_raw_parts(self.data, self.size, self.size).into_boxed_slice()
95                };
96                self.size = 0;
97                self.data = ptr::null_mut();
98                return vec;
99            }
100        }
101
102        impl$(<$lt>)? Clone for $name $(<$lt>)? {
103            fn clone(&self) -> Self {
104                let slice: Box<[$elem_ty]> = self.as_slice().into();
105                Self::from(slice)
106            }
107        }
108
109        impl$(<$lt>)? From<Box<[$elem_ty]>> for $name $(<$lt>)? {
110            fn from(slice: Box<[$elem_ty]>) -> Self {
111                let slice = Box::leak(slice);
112                let result = $name {
113                    size: slice.len(),
114                    data: slice.as_mut_ptr(),
115                };
116                result
117            }
118        }
119
120        impl$(<$lt>)? From<Vec<$elem_ty>> for $name $(<$lt>)? {
121            fn from(vec: Vec<$elem_ty>) -> Self {
122                Self::from(vec.into_boxed_slice())
123            }
124        }
125
126        impl$(<$lt>)? Drop for $name $(<$lt>)? {
127            fn drop(&mut self) {
128                drop(self.take());
129            }
130        }
131
132        #[doc = concat!("Creates an empty [`", stringify!($name),"`]")]
133        #[doc = ""]
134        #[doc = "# Note"]
135        #[doc = ""]
136        #[doc = concat!("Returns the resulting [`", stringify!($name), "`] in `out`.")]
137        #[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
138        #[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
139        pub extern "C" fn $empty(out: &mut $name) {
140            out.size = 0;
141            out.data = ptr::null_mut();
142        }
143
144        #[doc = concat!("Creates an uninitialized [`", stringify!($name),"`] with the given `size`.")]
145        #[doc = ""]
146        #[doc = "# Note"]
147        #[doc = ""]
148        #[doc = concat!("Returns the resulting [`", stringify!($name), "`] in `out`.")]
149        #[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
150        #[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
151        pub extern "C" fn $uninit(out: &mut $name, size: usize) {
152            out.set_buffer(vec![Default::default(); size].into());
153        }
154
155        #[doc = concat!("Creates an new [`", stringify!($name),"`] with the given `size` and `ptr` data.")]
156        #[doc = ""]
157        #[doc = "# Note"]
158        #[doc = ""]
159        #[doc = "- The `ptr` must point to a buffer of length `size` or larger."]
160        #[doc = concat!("- Returns the resulting [`", stringify!($name), "`] in `out`.")]
161        #[doc = ""]
162        #[doc = "# Safety"]
163        #[doc = ""]
164        #[doc = "It is the callers responsibility to provide a valid pair of `ptr` and `size`."]
165        #[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
166        #[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
167        pub unsafe extern "C" fn $new $(<$lt>)? (
168            out: &mut $name $(<$lt>)?,
169            size: usize,
170            ptr: *const $elem_ty,
171        ) {
172            let vec = (0..size).map(|i| ptr.add(i).read()).collect();
173            out.set_buffer(vec);
174        }
175
176        #[doc = concat!("Copies the [`", stringify!($name),"`] in `src`.")]
177        #[doc = ""]
178        #[doc = "# Note"]
179        #[doc = ""]
180        #[doc = concat!("- Returns the resulting [`", stringify!($name), "`] in `out`.")]
181        #[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
182        #[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
183        pub extern "C" fn $copy $(<$lt>)? (
184            out: &mut $name $(<$lt>)?,
185            src: &$name $(<$lt>)?,
186        ) {
187            out.set_buffer(src.as_slice().into());
188        }
189
190        #[doc = concat!("Frees memory associated to the [`", stringify!($name),"`].")]
191        #[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
192        #[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
193        pub extern "C" fn $delete $(<$lt>)? (out: &mut $name $(<$lt>)?) {
194            out.take();
195        }
196    )*};
197}
198
199declare_vecs! {
200    struct wasm_byte_vec_t {
201        type element = u8;
202        fn new: wasm_byte_vec_new;
203        fn empty: wasm_byte_vec_new_empty;
204        fn uninit: wasm_byte_vec_new_uninitialized;
205        fn copy: wasm_byte_vec_copy;
206        fn delete: wasm_byte_vec_delete;
207    }
208    struct wasm_valtype_vec_t {
209        type element = Option<Box<wasm_valtype_t>>;
210        fn new: wasm_valtype_vec_new;
211        fn empty: wasm_valtype_vec_new_empty;
212        fn uninit: wasm_valtype_vec_new_uninitialized;
213        fn copy: wasm_valtype_vec_copy;
214        fn delete: wasm_valtype_vec_delete;
215    }
216    struct wasm_functype_vec_t {
217        type element = Option<Box<wasm_functype_t>>;
218        fn new: wasm_functype_vec_new;
219        fn empty: wasm_functype_vec_new_empty;
220        fn uninit: wasm_functype_vec_new_uninitialized;
221        fn copy: wasm_functype_vec_copy;
222        fn delete: wasm_functype_vec_delete;
223    }
224    struct wasm_globaltype_vec_t {
225        type element = Option<Box<wasm_globaltype_t>>;
226        fn new: wasm_globaltype_vec_new;
227        fn empty: wasm_globaltype_vec_new_empty;
228        fn uninit: wasm_globaltype_vec_new_uninitialized;
229        fn copy: wasm_globaltype_vec_copy;
230        fn delete: wasm_globaltype_vec_delete;
231    }
232    struct wasm_tabletype_vec_t {
233        type element = Option<Box<wasm_tabletype_t>>;
234        fn new: wasm_tabletype_vec_new;
235        fn empty: wasm_tabletype_vec_new_empty;
236        fn uninit: wasm_tabletype_vec_new_uninitialized;
237        fn copy: wasm_tabletype_vec_copy;
238        fn delete: wasm_tabletype_vec_delete;
239    }
240    struct wasm_memorytype_vec_t {
241        type element = Option<Box<wasm_memorytype_t>>;
242        fn new: wasm_memorytype_vec_new;
243        fn empty: wasm_memorytype_vec_new_empty;
244        fn uninit: wasm_memorytype_vec_new_uninitialized;
245        fn copy: wasm_memorytype_vec_copy;
246        fn delete: wasm_memorytype_vec_delete;
247    }
248    struct wasm_externtype_vec_t {
249        type element = Option<Box<wasm_externtype_t>>;
250        fn new: wasm_externtype_vec_new;
251        fn empty: wasm_externtype_vec_new_empty;
252        fn uninit: wasm_externtype_vec_new_uninitialized;
253        fn copy: wasm_externtype_vec_copy;
254        fn delete: wasm_externtype_vec_delete;
255    }
256    struct wasm_importtype_vec_t {
257        type element = Option<Box<wasm_importtype_t>>;
258        fn new: wasm_importtype_vec_new;
259        fn empty: wasm_importtype_vec_new_empty;
260        fn uninit: wasm_importtype_vec_new_uninitialized;
261        fn copy: wasm_importtype_vec_copy;
262        fn delete: wasm_importtype_vec_delete;
263    }
264    struct wasm_exporttype_vec_t {
265        type element = Option<Box<wasm_exporttype_t>>;
266        fn new: wasm_exporttype_vec_new;
267        fn empty: wasm_exporttype_vec_new_empty;
268        fn uninit: wasm_exporttype_vec_new_uninitialized;
269        fn copy: wasm_exporttype_vec_copy;
270        fn delete: wasm_exporttype_vec_delete;
271    }
272    struct wasm_val_vec_t {
273        type element = wasm_val_t;
274        fn new: wasm_val_vec_new;
275        fn empty: wasm_val_vec_new_empty;
276        fn uninit: wasm_val_vec_new_uninitialized;
277        fn copy: wasm_val_vec_copy;
278        fn delete: wasm_val_vec_delete;
279    }
280    struct wasm_frame_vec_t<'a> {
281        type element = Option<Box<wasm_frame_t<'a>>>;
282        fn new: wasm_frame_vec_new;
283        fn empty: wasm_frame_vec_new_empty;
284        fn uninit: wasm_frame_vec_new_uninitialized;
285        fn copy: wasm_frame_vec_copy;
286        fn delete: wasm_frame_vec_delete;
287    }
288    struct wasm_extern_vec_t {
289        type element = Option<Box<wasm_extern_t>>;
290        fn new: wasm_extern_vec_new;
291        fn empty: wasm_extern_vec_new_empty;
292        fn uninit: wasm_extern_vec_new_uninitialized;
293        fn copy: wasm_extern_vec_copy;
294        fn delete: wasm_extern_vec_delete;
295    }
296}