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