Skip to main content

wasmer/wasm_c_api/
module.rs

1use super::store::wasm_store_t;
2use super::types::{wasm_byte_vec_t, wasm_exporttype_vec_t, wasm_importtype_vec_t};
3use std::ptr::NonNull;
4use wasmer_api::Module;
5
6/// Opaque type representing a WebAssembly module.
7#[derive(Clone)]
8#[allow(non_camel_case_types)]
9pub struct wasm_module_t {
10    pub(crate) inner: Module,
11}
12
13/// A WebAssembly module contains stateless WebAssembly code that has
14/// already been compiled and can be instantiated multiple times.
15///
16/// Creates a new WebAssembly Module given the configuration
17/// in the store.
18///
19/// ## Security
20///
21/// Before the code is compiled, it will be validated using the store
22/// features.
23///
24/// # Example
25///
26/// See the module's documentation.
27#[unsafe(no_mangle)]
28pub unsafe extern "C" fn wasm_module_new(
29    store: Option<&mut wasm_store_t>,
30    bytes: Option<&wasm_byte_vec_t>,
31) -> Option<Box<wasm_module_t>> {
32    let store = store?;
33    let store_mut = unsafe { store.inner.store_mut() };
34    let bytes = bytes?;
35
36    let module = c_try!(Module::from_binary(&store_mut, bytes.as_slice()));
37
38    Some(Box::new(wasm_module_t { inner: module }))
39}
40
41/// Deletes a WebAssembly module.
42///
43/// # Example
44///
45/// See [`wasm_module_new`].
46#[unsafe(no_mangle)]
47pub unsafe extern "C" fn wasm_module_delete(_module: Option<Box<wasm_module_t>>) {}
48
49/// Validates a new WebAssembly module given the configuration
50/// in the [store][super::store].
51///
52/// This validation is normally pretty fast and checks the enabled
53/// WebAssembly features in the [store engine][super::engine] to
54/// assure deterministic validation of the module.
55///
56/// # Example
57///
58/// ```rust
59/// # use inline_c::assert_c;
60/// # fn main() {
61/// #    (assert_c! {
62/// # #include "tests/wasmer.h"
63/// #
64/// int main() {
65///     // Create the engine and the store.
66///     wasm_engine_t* engine = wasm_engine_new();
67///     wasm_store_t* store = wasm_store_new(engine);
68///
69///     // Create a WebAssembly module from a WAT definition.
70///     wasm_byte_vec_t wat;
71///     wasmer_byte_vec_new_from_string(&wat, "(module)");
72///     wasm_byte_vec_t wasm;
73///     wat2wasm(&wat, &wasm);
74///
75///     // Validate that the WebAssembly module is correct.
76///     assert(wasm_module_validate(store, &wasm));
77///
78///     // Free everything.
79///     wasm_byte_vec_delete(&wasm);
80///     wasm_byte_vec_delete(&wat);
81///     wasm_store_delete(store);
82///     wasm_engine_delete(engine);
83///
84///     return 0;
85/// }
86/// #    })
87/// #    .success();
88/// # }
89/// ```
90#[unsafe(no_mangle)]
91pub unsafe extern "C" fn wasm_module_validate(
92    store: Option<&mut wasm_store_t>,
93    bytes: Option<&wasm_byte_vec_t>,
94) -> bool {
95    let store = match store {
96        Some(store) => unsafe { store.inner.store_mut() },
97        None => return false,
98    };
99    let bytes = match bytes {
100        Some(bytes) => bytes,
101        None => return false,
102    };
103
104    Module::validate(&store, bytes.as_slice())
105        .map(|_| true)
106        .unwrap_or(false)
107}
108
109/// Returns an array of the exported types in the module.
110///
111/// The order of the exports is guaranteed to be the same as in the
112/// WebAssembly bytecode.
113///
114/// # Example
115///
116/// ```rust
117/// # use inline_c::assert_c;
118/// # fn main() {
119/// #    (assert_c! {
120/// # #include "tests/wasmer.h"
121/// #
122/// int main() {
123///     // Create the engine and the store.
124///     wasm_engine_t* engine = wasm_engine_new();
125///     wasm_store_t* store = wasm_store_new(engine);
126///
127///     // Create a WebAssembly module from a WAT definition.
128///     wasm_byte_vec_t wat;
129///     wasmer_byte_vec_new_from_string(
130///         &wat,
131///         "(module\n"
132///         "  (func (export \"function\") (param i32 i64))\n"
133///         "  (global (export \"global\") i32 (i32.const 7))\n"
134///         "  (table (export \"table\") 0 funcref)\n"
135///         "  (memory (export \"memory\") 1))"
136///     );
137///     wasm_byte_vec_t wasm;
138///     wat2wasm(&wat, &wasm);
139///
140///     // Create the module.
141///     wasm_module_t* module = wasm_module_new(store, &wasm);
142///     assert(module);
143///
144///     // Extract the types exported by this module.
145///     wasm_exporttype_vec_t export_types;
146///     wasm_module_exports(module, &export_types);
147///
148///     // We have 4 of them.
149///     assert(export_types.size == 4);
150///
151///     // The first one is a function. Use
152///     // `wasm_externtype_as_functype_const` to continue to inspect the
153///     // type.
154///     {
155///         wasm_exporttype_t* export_type = export_types.data[0];
156///
157///         const wasm_name_t* export_name = wasm_exporttype_name(export_type);
158///         wasmer_assert_name(export_name, "function");
159///
160///         const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
161///         assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_FUNC);
162///     }
163///
164///     // The second one is a global. Use
165///     // `wasm_externtype_as_globaltype_const` to continue to inspect the
166///     // type.
167///     {
168///         wasm_exporttype_t* export_type = export_types.data[1];
169///
170///         const wasm_name_t* export_name = wasm_exporttype_name(export_type);
171///         wasmer_assert_name(export_name, "global");
172///
173///         const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
174///         assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_GLOBAL);
175///     }
176///
177///     // The third one is a table. Use
178///     // `wasm_externtype_as_tabletype_const` to continue to inspect the
179///     // type.
180///     {
181///         wasm_exporttype_t* export_type = export_types.data[2];
182///
183///         const wasm_name_t* export_name = wasm_exporttype_name(export_type);
184///         wasmer_assert_name(export_name, "table");
185///
186///         const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
187///         assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_TABLE);
188///     }
189///
190///     // The fourth one is a memory. Use
191///     // `wasm_externtype_as_memorytype_const` to continue to inspect the
192///     // type.
193///     {
194///         wasm_exporttype_t* export_type = export_types.data[3];
195///
196///         const wasm_name_t* export_name = wasm_exporttype_name(export_type);
197///         wasmer_assert_name(export_name, "memory");
198///
199///         const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
200///         assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_MEMORY);
201///     }
202///
203///     // Free everything.
204///     wasm_exporttype_vec_delete(&export_types);
205///     wasm_byte_vec_delete(&wasm);
206///     wasm_byte_vec_delete(&wat);
207///     wasm_module_delete(module);
208///     wasm_store_delete(store);
209///     wasm_engine_delete(engine);
210///
211///     return 0;
212/// }
213/// #    })
214/// #    .success();
215/// # }
216/// ```
217#[unsafe(no_mangle)]
218pub unsafe extern "C" fn wasm_module_exports(
219    module: &wasm_module_t,
220    // own
221    out: &mut wasm_exporttype_vec_t,
222) {
223    let exports = module
224        .inner
225        .exports()
226        .map(|export| Some(Box::new(export.into())))
227        .collect();
228
229    out.set_buffer(exports);
230}
231
232/// Returns an array of the imported types in the module.
233///
234/// The order of the imports is guaranteed to be the same as in the
235/// WebAssembly bytecode.
236///
237/// # Example
238///
239/// ```rust
240/// # use inline_c::assert_c;
241/// # fn main() {
242/// #    (assert_c! {
243/// # #include "tests/wasmer.h"
244/// #
245/// int main() {
246///     // Create the engine and the store.
247///     wasm_engine_t* engine = wasm_engine_new();
248///     wasm_store_t* store = wasm_store_new(engine);
249///
250///     // Create a WebAssembly module from a WAT definition.
251///     wasm_byte_vec_t wat;
252///     wasmer_byte_vec_new_from_string(
253///         &wat,
254///         "(module\n"
255///         "  (import \"ns\" \"function\" (func))\n"
256///         "  (import \"ns\" \"global\" (global f32))\n"
257///         "  (import \"ns\" \"table\" (table 1 2 funcref))\n"
258///         "  (import \"ns\" \"memory\" (memory 3 4)))"
259///     );
260///     wasm_byte_vec_t wasm;
261///     wat2wasm(&wat, &wasm);
262///
263///     // Create the module.
264///     wasm_module_t* module = wasm_module_new(store, &wasm);
265///     assert(module);
266///
267///     // Extract the types imported by the module.
268///     wasm_importtype_vec_t import_types;
269///     wasm_module_imports(module, &import_types);
270///
271///     // We have 4 of them.
272///     assert(import_types.size == 4);
273///
274///     // The first one is a function. Use
275///     // `wasm_externtype_as_functype_const` to continue to inspect the
276///     // type.
277///     {
278///         const wasm_importtype_t* import_type = import_types.data[0];
279///
280///         const wasm_name_t* import_module = wasm_importtype_module(import_type);
281///         wasmer_assert_name(import_module, "ns");
282///
283///         const wasm_name_t* import_name = wasm_importtype_name(import_type);
284///         wasmer_assert_name(import_name, "function");
285///
286///         const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
287///         assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_FUNC);
288///     }
289///
290///     // The second one is a global. Use
291///     // `wasm_externtype_as_globaltype_const` to continue to inspect
292///     // the type.
293///     {
294///         const wasm_importtype_t* import_type = import_types.data[1];
295///
296///         const wasm_name_t* import_module = wasm_importtype_module(import_type);
297///         wasmer_assert_name(import_module, "ns");
298///
299///         const wasm_name_t* import_name = wasm_importtype_name(import_type);
300///         wasmer_assert_name(import_name, "global");
301///
302///         const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
303///         assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_GLOBAL);
304///     }
305///
306///     // The third one is a table. Use
307///     // `wasm_externtype_as_tabletype_const` to continue to inspect
308///     // the type.
309///     {
310///         const wasm_importtype_t* import_type = import_types.data[2];
311///
312///         const wasm_name_t* import_module = wasm_importtype_module(import_type);
313///         wasmer_assert_name(import_module, "ns");
314///
315///         const wasm_name_t* import_name = wasm_importtype_name(import_type);
316///         wasmer_assert_name(import_name, "table");
317///
318///         const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
319///         assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_TABLE);
320///     }
321///
322///     // The fourth one is a memory. Use
323///     // `wasm_externtype_as_memorytype_const` to continue to inspect
324///     // the type.
325///     {
326///         const wasm_importtype_t* import_type = import_types.data[3];
327///
328///         const wasm_name_t* import_module = wasm_importtype_module(import_type);
329///         wasmer_assert_name(import_module, "ns");
330///
331///         const wasm_name_t* import_name = wasm_importtype_name(import_type);
332///         wasmer_assert_name(import_name, "memory");
333///
334///         const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
335///         assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_MEMORY);
336///
337///         const wasm_memorytype_t* memory_type = wasm_externtype_as_memorytype_const(extern_type);
338///         const wasm_limits_t* memory_limits = wasm_memorytype_limits(memory_type);
339///         assert(memory_limits->min == 3);
340///         assert(memory_limits->max == 4);
341///     }
342///
343///     // Free everything.
344///     wasm_importtype_vec_delete(&import_types);
345///     wasm_module_delete(module);
346///     wasm_byte_vec_delete(&wasm);
347///     wasm_byte_vec_delete(&wat);
348///     wasm_store_delete(store);
349///     wasm_engine_delete(engine);
350///
351///     return 0;
352/// }
353/// #    })
354/// #    .success();
355/// # }
356/// ```
357#[unsafe(no_mangle)]
358pub unsafe extern "C" fn wasm_module_imports(
359    module: &wasm_module_t,
360    // own
361    out: &mut wasm_importtype_vec_t,
362) {
363    let imports = module
364        .inner
365        .imports()
366        .map(|import| Some(Box::new(import.into())))
367        .collect();
368
369    out.set_buffer(imports);
370}
371
372/// Deserializes a serialized module binary into a `wasm_module_t`.
373///
374/// Note: the module has to be serialized before with the
375/// `wasm_module_serialize` function.
376///
377/// # Safety
378///
379/// This function is inherently **unsafe** as the provided bytes:
380///
381/// 1. Are going to be deserialized directly into Rust and C objects,
382/// 2. Contains the function assembly bodies and, if intercepted,
383///    a malicious actor could inject code into executable
384///    memory.
385///
386/// And as such, the `wasm_module_deserialize` method is unsafe.
387///
388/// # Example
389///
390/// ```rust
391/// # use inline_c::assert_c;
392/// # fn main() {
393/// #    (assert_c! {
394/// # #include "tests/wasmer.h"
395/// #
396/// int main() {
397///     // Create the engine and the store.
398///     wasm_engine_t* engine = wasm_engine_new();
399///     wasm_store_t* store = wasm_store_new(engine);
400///
401///     // Create a WebAssembly module from a WAT definition.
402///    wasm_byte_vec_t wat;
403///    wasmer_byte_vec_new_from_string(
404///        &wat,
405///        "(module\n"
406///        "  (func (export \"function\") (param i32 i64))\n"
407///        "  (global (export \"global\") i32 (i32.const 7))\n"
408///        "  (table (export \"table\") 0 funcref)\n"
409///        "  (memory (export \"memory\") 1))"
410///    );
411///    wasm_byte_vec_t wasm;
412///    wat2wasm(&wat, &wasm);
413///
414///    // Create the module.
415///    wasm_module_t* module = wasm_module_new(store, &wasm);
416///    assert(module);
417///
418///    // Serialize the module into bytes.
419///    wasm_byte_vec_t serialized_module;
420///    wasm_module_serialize(module, &serialized_module);
421///    assert(serialized_module.size > 0);
422///
423///    // Free the module.
424///    wasm_module_delete(module);
425///
426///    // Deserialize the serialized module. Note that the store must
427///    // be the same as the one used to serialize.
428///    wasm_module_t* deserialized_module = wasm_module_deserialize(
429///        store,
430///        &serialized_module
431///    );
432///    wasm_byte_vec_delete(&serialized_module);
433///    assert(deserialized_module);
434///
435///    // Check we have our 4 export types.
436///    wasm_exporttype_vec_t export_types;
437///    wasm_module_exports(deserialized_module, &export_types);
438///
439///    assert(export_types.size == 4);
440///
441///    // Free everything.
442///    wasm_exporttype_vec_delete(&export_types);
443///    wasm_module_delete(deserialized_module);
444///    wasm_byte_vec_delete(&wasm);
445///    wasm_byte_vec_delete(&wat);
446///    wasm_store_delete(store);
447///    wasm_engine_delete(engine);
448///
449///     return 0;
450/// }
451/// #    })
452/// #    .success();
453/// # }
454/// ```
455#[unsafe(no_mangle)]
456pub unsafe extern "C" fn wasm_module_deserialize(
457    store: &wasm_store_t,
458    bytes: Option<&wasm_byte_vec_t>,
459) -> Option<NonNull<wasm_module_t>> {
460    let bytes = bytes?;
461
462    let store_ref = unsafe { store.inner.store() };
463    let module = c_try!(unsafe { Module::deserialize(&store_ref, bytes.as_slice()) });
464
465    Some(unsafe {
466        NonNull::new_unchecked(Box::into_raw(Box::new(wasm_module_t { inner: module })))
467    })
468}
469
470/// Serializes a module into a binary representation that the
471/// [engine][super::engine] can later process via
472/// [`wasm_module_deserialize`].
473///
474/// # Example
475///
476/// See [`wasm_module_deserialize`].
477#[unsafe(no_mangle)]
478pub unsafe extern "C" fn wasm_module_serialize(module: &wasm_module_t, out: &mut wasm_byte_vec_t) {
479    let byte_vec = c_try!(module.inner.serialize(); otherwise ());
480    out.set_buffer(byte_vec.to_vec());
481}
482
483#[cfg(test)]
484mod tests {
485    use inline_c::assert_c;
486
487    #[allow(
488        unexpected_cfgs,
489        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
490    )]
491    #[cfg_attr(coverage_nightly, coverage(off))]
492    #[test]
493    fn test_module_validate() {
494        (assert_c! {
495            #include "tests/wasmer.h"
496
497            int main() {
498                wasm_engine_t* engine = wasm_engine_new();
499                wasm_store_t* store = wasm_store_new(engine);
500
501                wasm_byte_vec_t wat;
502                wasmer_byte_vec_new_from_string(&wat, "(module)");
503                wasm_byte_vec_t wasm;
504                wat2wasm(&wat, &wasm);
505
506                assert(wasm_module_validate(store, &wasm));
507
508                wasm_byte_vec_delete(&wasm);
509                wasm_byte_vec_delete(&wat);
510                wasm_store_delete(store);
511                wasm_engine_delete(engine);
512
513                return 0;
514            }
515        })
516        .success();
517    }
518
519    #[allow(
520        unexpected_cfgs,
521        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
522    )]
523    #[cfg_attr(coverage_nightly, coverage(off))]
524    #[test]
525    fn test_module_new() {
526        (assert_c! {
527            #include "tests/wasmer.h"
528
529            int main() {
530                wasm_engine_t* engine = wasm_engine_new();
531                wasm_store_t* store = wasm_store_new(engine);
532
533                wasm_byte_vec_t wat;
534                wasmer_byte_vec_new_from_string(&wat, "(module)");
535                wasm_byte_vec_t wasm;
536                wat2wasm(&wat, &wasm);
537
538                wasm_module_t* module = wasm_module_new(store, &wasm);
539                assert(module);
540
541                wasm_byte_vec_delete(&wasm);
542                wasm_byte_vec_delete(&wat);
543                wasm_module_delete(module);
544                wasm_store_delete(store);
545                wasm_engine_delete(engine);
546
547                return 0;
548            }
549        })
550        .success();
551    }
552
553    #[allow(
554        unexpected_cfgs,
555        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
556    )]
557    #[cfg_attr(coverage_nightly, coverage(off))]
558    #[test]
559    fn test_module_exports() {
560        (assert_c! {
561            #include "tests/wasmer.h"
562
563            int main() {
564                wasm_engine_t* engine = wasm_engine_new();
565                wasm_store_t* store = wasm_store_new(engine);
566
567                wasm_byte_vec_t wat;
568                wasmer_byte_vec_new_from_string(
569                    &wat,
570                    "(module\n"
571                    "  (func (export \"function\") (param i32 i64))\n"
572                    "  (global (export \"global\") i32 (i32.const 7))\n"
573                    "  (table (export \"table\") 0 funcref)\n"
574                    "  (memory (export \"memory\") 1))"
575                );
576                wasm_byte_vec_t wasm;
577                wat2wasm(&wat, &wasm);
578
579                wasm_module_t* module = wasm_module_new(store, &wasm);
580                assert(module);
581
582                wasm_exporttype_vec_t export_types;
583                wasm_module_exports(module, &export_types);
584
585                assert(export_types.size == 4);
586
587                {
588                    wasm_exporttype_t* export_type = export_types.data[0];
589
590                    const wasm_name_t* export_name = wasm_exporttype_name(export_type);
591                    wasmer_assert_name(export_name, "function");
592
593                    const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
594                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_FUNC);
595
596                    const wasm_functype_t* func_type = wasm_externtype_as_functype_const(extern_type);
597
598                    const wasm_valtype_vec_t* func_params = wasm_functype_params(func_type);
599                    assert(func_params && func_params->size == 2);
600                    assert(wasm_valtype_kind(func_params->data[0]) == WASM_I32);
601                    assert(wasm_valtype_kind(func_params->data[1]) == WASM_I64);
602
603                    const wasm_valtype_vec_t* func_results = wasm_functype_results(func_type);
604                    assert(func_results && func_results->size == 0);
605                }
606
607                {
608                    wasm_exporttype_t* export_type = export_types.data[1];
609
610                    const wasm_name_t* export_name = wasm_exporttype_name(export_type);
611                    wasmer_assert_name(export_name, "global");
612
613                    const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
614                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_GLOBAL);
615
616                    const wasm_globaltype_t* global_type = wasm_externtype_as_globaltype_const(extern_type);
617                    assert(wasm_valtype_kind(wasm_globaltype_content(global_type)) == WASM_I32);
618                    assert(wasm_globaltype_mutability(global_type) == WASM_CONST);
619                }
620
621                {
622                    wasm_exporttype_t* export_type = export_types.data[2];
623
624                    const wasm_name_t* export_name = wasm_exporttype_name(export_type);
625                    wasmer_assert_name(export_name, "table");
626
627                    const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
628                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_TABLE);
629
630                    const wasm_tabletype_t* table_type = wasm_externtype_as_tabletype_const(extern_type);
631                    assert(wasm_valtype_kind(wasm_tabletype_element(table_type)) == WASM_FUNCREF);
632
633                    const wasm_limits_t* table_limits = wasm_tabletype_limits(table_type);
634                    assert(table_limits->min == 0);
635                    assert(table_limits->max == wasm_limits_max_default);
636                }
637
638                {
639                    wasm_exporttype_t* export_type = export_types.data[3];
640
641                    const wasm_name_t* export_name = wasm_exporttype_name(export_type);
642                    wasmer_assert_name(export_name, "memory");
643
644                    const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
645                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_MEMORY);
646
647                    const wasm_memorytype_t* memory_type = wasm_externtype_as_memorytype_const(extern_type);
648                    const wasm_limits_t* memory_limits = wasm_memorytype_limits(memory_type);
649                    assert(memory_limits->min == 1);
650                    assert(memory_limits->max == wasm_limits_max_default);
651                }
652
653                wasm_exporttype_vec_delete(&export_types);
654                wasm_byte_vec_delete(&wasm);
655                wasm_byte_vec_delete(&wat);
656                wasm_module_delete(module);
657                wasm_store_delete(store);
658                wasm_engine_delete(engine);
659
660                return 0;
661            }
662        })
663        .success();
664    }
665
666    #[allow(
667        unexpected_cfgs,
668        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
669    )]
670    #[cfg_attr(coverage_nightly, coverage(off))]
671    #[test]
672    fn test_module_imports() {
673        (assert_c! {
674            #include "tests/wasmer.h"
675
676            int main() {
677                wasm_engine_t* engine = wasm_engine_new();
678                wasm_store_t* store = wasm_store_new(engine);
679
680                wasm_byte_vec_t wat;
681                wasmer_byte_vec_new_from_string(
682                    &wat,
683                    "(module\n"
684                    "  (import \"ns\" \"function\" (func))\n"
685                    "  (import \"ns\" \"global\" (global f32))\n"
686                    "  (import \"ns\" \"table\" (table 1 2 funcref))\n"
687                    "  (import \"ns\" \"memory\" (memory 3 4)))"
688                );
689                wasm_byte_vec_t wasm;
690                wat2wasm(&wat, &wasm);
691
692                wasm_module_t* module = wasm_module_new(store, &wasm);
693                assert(module);
694
695                wasm_importtype_vec_t import_types;
696                wasm_module_imports(module, &import_types);
697
698                assert(import_types.size == 4);
699
700                {
701                    const wasm_importtype_t* import_type = import_types.data[0];
702
703                    const wasm_name_t* import_module = wasm_importtype_module(import_type);
704                    wasmer_assert_name(import_module, "ns");
705
706                    const wasm_name_t* import_name = wasm_importtype_name(import_type);
707                    wasmer_assert_name(import_name, "function");
708
709                    const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
710                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_FUNC);
711
712                    const wasm_functype_t* func_type = wasm_externtype_as_functype_const(extern_type);
713
714                    const wasm_valtype_vec_t* func_params = wasm_functype_params(func_type);
715                    assert(func_params && func_params->size == 0);
716
717                    const wasm_valtype_vec_t* func_results = wasm_functype_results(func_type);
718                    assert(func_results && func_results->size == 0);
719                }
720
721                {
722                    const wasm_importtype_t* import_type = import_types.data[1];
723
724                    const wasm_name_t* import_module = wasm_importtype_module(import_type);
725                    wasmer_assert_name(import_module, "ns");
726
727                    const wasm_name_t* import_name = wasm_importtype_name(import_type);
728                    wasmer_assert_name(import_name, "global");
729
730                    const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
731                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_GLOBAL);
732
733                    const wasm_globaltype_t* global_type = wasm_externtype_as_globaltype_const(extern_type);
734                    assert(wasm_valtype_kind(wasm_globaltype_content(global_type)) == WASM_F32);
735                    assert(wasm_globaltype_mutability(global_type) == WASM_CONST);
736                }
737
738                {
739                    const wasm_importtype_t* import_type = import_types.data[2];
740
741                    const wasm_name_t* import_module = wasm_importtype_module(import_type);
742                    wasmer_assert_name(import_module, "ns");
743
744                    const wasm_name_t* import_name = wasm_importtype_name(import_type);
745                    wasmer_assert_name(import_name, "table");
746
747                    const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
748                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_TABLE);
749
750                    const wasm_tabletype_t* table_type = wasm_externtype_as_tabletype_const(extern_type);
751                    assert(wasm_valtype_kind(wasm_tabletype_element(table_type)) == WASM_FUNCREF);
752
753                    const wasm_limits_t* table_limits = wasm_tabletype_limits(table_type);
754                    assert(table_limits->min == 1);
755                    assert(table_limits->max == 2);
756                }
757
758                {
759                    const wasm_importtype_t* import_type = import_types.data[3];
760
761                    const wasm_name_t* import_module = wasm_importtype_module(import_type);
762                    wasmer_assert_name(import_module, "ns");
763
764                    const wasm_name_t* import_name = wasm_importtype_name(import_type);
765                    wasmer_assert_name(import_name, "memory");
766
767                    const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
768                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_MEMORY);
769
770                    const wasm_memorytype_t* memory_type = wasm_externtype_as_memorytype_const(extern_type);
771                    const wasm_limits_t* memory_limits = wasm_memorytype_limits(memory_type);
772                    assert(memory_limits->min == 3);
773                    assert(memory_limits->max == 4);
774                }
775
776                wasm_importtype_vec_delete(&import_types);
777                wasm_module_delete(module);
778                wasm_byte_vec_delete(&wasm);
779                wasm_byte_vec_delete(&wat);
780                wasm_store_delete(store);
781                wasm_engine_delete(engine);
782
783                return 0;
784            }
785        })
786        .success();
787    }
788
789    #[allow(
790        unexpected_cfgs,
791        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
792    )]
793    #[cfg_attr(coverage_nightly, coverage(off))]
794    #[test]
795    fn test_module_serialize() {
796        (assert_c! {
797            #include "tests/wasmer.h"
798
799            int main() {
800                wasm_engine_t* engine = wasm_engine_new();
801                wasm_store_t* store = wasm_store_new(engine);
802
803                wasm_byte_vec_t wat;
804                wasmer_byte_vec_new_from_string(&wat, "(module)");
805                wasm_byte_vec_t wasm;
806                wat2wasm(&wat, &wasm);
807
808                wasm_module_t* module = wasm_module_new(store, &wasm);
809                assert(module);
810
811                wasm_byte_vec_t serialized_module;
812                wasm_module_serialize(module, &serialized_module);
813                assert(serialized_module.size > 0);
814
815                wasm_module_delete(module);
816                wasm_byte_vec_delete(&serialized_module);
817                wasm_byte_vec_delete(&wasm);
818                wasm_byte_vec_delete(&wat);
819                wasm_store_delete(store);
820                wasm_engine_delete(engine);
821
822                return 0;
823            }
824        })
825        .success();
826    }
827
828    #[allow(
829        unexpected_cfgs,
830        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
831    )]
832    #[cfg_attr(coverage_nightly, coverage(off))]
833    #[test]
834    fn test_module_serialize_and_deserialize() {
835        (assert_c! {
836            #include "tests/wasmer.h"
837
838            int main() {
839                wasm_engine_t* engine = wasm_engine_new();
840                wasm_store_t* store = wasm_store_new(engine);
841
842                wasm_byte_vec_t wat;
843                wasmer_byte_vec_new_from_string(
844                    &wat,
845                    "(module\n"
846                    "  (func (export \"function\") (param i32 i64))\n"
847                    "  (global (export \"global\") i32 (i32.const 7))\n"
848                    "  (table (export \"table\") 0 funcref)\n"
849                    "  (memory (export \"memory\") 1))"
850                );
851                wasm_byte_vec_t wasm;
852                wat2wasm(&wat, &wasm);
853
854                wasm_module_t* module = wasm_module_new(store, &wasm);
855                assert(module);
856
857                wasm_byte_vec_t serialized_module;
858                wasm_module_serialize(module, &serialized_module);
859                assert(serialized_module.size > 0);
860
861                wasm_module_delete(module);
862                wasm_module_t* deserialized_module = wasm_module_deserialize(
863                    store,
864                    &serialized_module
865                );
866                wasm_byte_vec_delete(&serialized_module);
867                assert(deserialized_module);
868
869                wasm_exporttype_vec_t export_types;
870                wasm_module_exports(deserialized_module, &export_types);
871
872                assert(export_types.size == 4);
873
874                wasm_exporttype_vec_delete(&export_types);
875                wasm_module_delete(deserialized_module);
876                wasm_byte_vec_delete(&wasm);
877                wasm_byte_vec_delete(&wat);
878                wasm_store_delete(store);
879                wasm_engine_delete(engine);
880
881                return 0;
882            }
883        })
884        .success();
885    }
886}