wasmer_c_api/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 wasmer_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 wasmer_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 wasmer_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 wasmer_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    #[cfg(not(target_os = "windows"))]
486    use inline_c::assert_c;
487    #[cfg(target_os = "windows")]
488    use wasmer_inline_c::assert_c;
489
490    #[allow(
491        unexpected_cfgs,
492        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
493    )]
494    #[cfg_attr(coverage, ignore)]
495    #[test]
496    fn test_module_validate() {
497        (assert_c! {
498            #include "tests/wasmer.h"
499
500            int main() {
501                wasm_engine_t* engine = wasm_engine_new();
502                wasm_store_t* store = wasm_store_new(engine);
503
504                wasm_byte_vec_t wat;
505                wasmer_byte_vec_new_from_string(&wat, "(module)");
506                wasm_byte_vec_t wasm;
507                wat2wasm(&wat, &wasm);
508
509                assert(wasm_module_validate(store, &wasm));
510
511                wasm_byte_vec_delete(&wasm);
512                wasm_byte_vec_delete(&wat);
513                wasm_store_delete(store);
514                wasm_engine_delete(engine);
515
516                return 0;
517            }
518        })
519        .success();
520    }
521
522    #[allow(
523        unexpected_cfgs,
524        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
525    )]
526    #[cfg_attr(coverage, ignore)]
527    #[test]
528    fn test_module_new() {
529        (assert_c! {
530            #include "tests/wasmer.h"
531
532            int main() {
533                wasm_engine_t* engine = wasm_engine_new();
534                wasm_store_t* store = wasm_store_new(engine);
535
536                wasm_byte_vec_t wat;
537                wasmer_byte_vec_new_from_string(&wat, "(module)");
538                wasm_byte_vec_t wasm;
539                wat2wasm(&wat, &wasm);
540
541                wasm_module_t* module = wasm_module_new(store, &wasm);
542                assert(module);
543
544                wasm_byte_vec_delete(&wasm);
545                wasm_byte_vec_delete(&wat);
546                wasm_module_delete(module);
547                wasm_store_delete(store);
548                wasm_engine_delete(engine);
549
550                return 0;
551            }
552        })
553        .success();
554    }
555
556    #[allow(
557        unexpected_cfgs,
558        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
559    )]
560    #[cfg_attr(coverage, ignore)]
561    #[test]
562    fn test_module_exports() {
563        (assert_c! {
564            #include "tests/wasmer.h"
565
566            int main() {
567                wasm_engine_t* engine = wasm_engine_new();
568                wasm_store_t* store = wasm_store_new(engine);
569
570                wasm_byte_vec_t wat;
571                wasmer_byte_vec_new_from_string(
572                    &wat,
573                    "(module\n"
574                    "  (func (export \"function\") (param i32 i64))\n"
575                    "  (global (export \"global\") i32 (i32.const 7))\n"
576                    "  (table (export \"table\") 0 funcref)\n"
577                    "  (memory (export \"memory\") 1))"
578                );
579                wasm_byte_vec_t wasm;
580                wat2wasm(&wat, &wasm);
581
582                wasm_module_t* module = wasm_module_new(store, &wasm);
583                assert(module);
584
585                wasm_exporttype_vec_t export_types;
586                wasm_module_exports(module, &export_types);
587
588                assert(export_types.size == 4);
589
590                {
591                    wasm_exporttype_t* export_type = export_types.data[0];
592
593                    const wasm_name_t* export_name = wasm_exporttype_name(export_type);
594                    wasmer_assert_name(export_name, "function");
595
596                    const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
597                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_FUNC);
598
599                    const wasm_functype_t* func_type = wasm_externtype_as_functype_const(extern_type);
600
601                    const wasm_valtype_vec_t* func_params = wasm_functype_params(func_type);
602                    assert(func_params && func_params->size == 2);
603                    assert(wasm_valtype_kind(func_params->data[0]) == WASM_I32);
604                    assert(wasm_valtype_kind(func_params->data[1]) == WASM_I64);
605
606                    const wasm_valtype_vec_t* func_results = wasm_functype_results(func_type);
607                    assert(func_results && func_results->size == 0);
608                }
609
610                {
611                    wasm_exporttype_t* export_type = export_types.data[1];
612
613                    const wasm_name_t* export_name = wasm_exporttype_name(export_type);
614                    wasmer_assert_name(export_name, "global");
615
616                    const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
617                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_GLOBAL);
618
619                    const wasm_globaltype_t* global_type = wasm_externtype_as_globaltype_const(extern_type);
620                    assert(wasm_valtype_kind(wasm_globaltype_content(global_type)) == WASM_I32);
621                    assert(wasm_globaltype_mutability(global_type) == WASM_CONST);
622                }
623
624                {
625                    wasm_exporttype_t* export_type = export_types.data[2];
626
627                    const wasm_name_t* export_name = wasm_exporttype_name(export_type);
628                    wasmer_assert_name(export_name, "table");
629
630                    const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
631                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_TABLE);
632
633                    const wasm_tabletype_t* table_type = wasm_externtype_as_tabletype_const(extern_type);
634                    assert(wasm_valtype_kind(wasm_tabletype_element(table_type)) == WASM_FUNCREF);
635
636                    const wasm_limits_t* table_limits = wasm_tabletype_limits(table_type);
637                    assert(table_limits->min == 0);
638                    assert(table_limits->max == wasm_limits_max_default);
639                }
640
641                {
642                    wasm_exporttype_t* export_type = export_types.data[3];
643
644                    const wasm_name_t* export_name = wasm_exporttype_name(export_type);
645                    wasmer_assert_name(export_name, "memory");
646
647                    const wasm_externtype_t* extern_type = wasm_exporttype_type(export_type);
648                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_MEMORY);
649
650                    const wasm_memorytype_t* memory_type = wasm_externtype_as_memorytype_const(extern_type);
651                    const wasm_limits_t* memory_limits = wasm_memorytype_limits(memory_type);
652                    assert(memory_limits->min == 1);
653                    assert(memory_limits->max == wasm_limits_max_default);
654                }
655
656                wasm_exporttype_vec_delete(&export_types);
657                wasm_byte_vec_delete(&wasm);
658                wasm_byte_vec_delete(&wat);
659                wasm_module_delete(module);
660                wasm_store_delete(store);
661                wasm_engine_delete(engine);
662
663                return 0;
664            }
665        })
666        .success();
667    }
668
669    #[allow(
670        unexpected_cfgs,
671        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
672    )]
673    #[cfg_attr(coverage, ignore)]
674    #[test]
675    fn test_module_imports() {
676        (assert_c! {
677            #include "tests/wasmer.h"
678
679            int main() {
680                wasm_engine_t* engine = wasm_engine_new();
681                wasm_store_t* store = wasm_store_new(engine);
682
683                wasm_byte_vec_t wat;
684                wasmer_byte_vec_new_from_string(
685                    &wat,
686                    "(module\n"
687                    "  (import \"ns\" \"function\" (func))\n"
688                    "  (import \"ns\" \"global\" (global f32))\n"
689                    "  (import \"ns\" \"table\" (table 1 2 funcref))\n"
690                    "  (import \"ns\" \"memory\" (memory 3 4)))"
691                );
692                wasm_byte_vec_t wasm;
693                wat2wasm(&wat, &wasm);
694
695                wasm_module_t* module = wasm_module_new(store, &wasm);
696                assert(module);
697
698                wasm_importtype_vec_t import_types;
699                wasm_module_imports(module, &import_types);
700
701                assert(import_types.size == 4);
702
703                {
704                    const wasm_importtype_t* import_type = import_types.data[0];
705
706                    const wasm_name_t* import_module = wasm_importtype_module(import_type);
707                    wasmer_assert_name(import_module, "ns");
708
709                    const wasm_name_t* import_name = wasm_importtype_name(import_type);
710                    wasmer_assert_name(import_name, "function");
711
712                    const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
713                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_FUNC);
714
715                    const wasm_functype_t* func_type = wasm_externtype_as_functype_const(extern_type);
716
717                    const wasm_valtype_vec_t* func_params = wasm_functype_params(func_type);
718                    assert(func_params && func_params->size == 0);
719
720                    const wasm_valtype_vec_t* func_results = wasm_functype_results(func_type);
721                    assert(func_results && func_results->size == 0);
722                }
723
724                {
725                    const wasm_importtype_t* import_type = import_types.data[1];
726
727                    const wasm_name_t* import_module = wasm_importtype_module(import_type);
728                    wasmer_assert_name(import_module, "ns");
729
730                    const wasm_name_t* import_name = wasm_importtype_name(import_type);
731                    wasmer_assert_name(import_name, "global");
732
733                    const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
734                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_GLOBAL);
735
736                    const wasm_globaltype_t* global_type = wasm_externtype_as_globaltype_const(extern_type);
737                    assert(wasm_valtype_kind(wasm_globaltype_content(global_type)) == WASM_F32);
738                    assert(wasm_globaltype_mutability(global_type) == WASM_CONST);
739                }
740
741                {
742                    const wasm_importtype_t* import_type = import_types.data[2];
743
744                    const wasm_name_t* import_module = wasm_importtype_module(import_type);
745                    wasmer_assert_name(import_module, "ns");
746
747                    const wasm_name_t* import_name = wasm_importtype_name(import_type);
748                    wasmer_assert_name(import_name, "table");
749
750                    const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
751                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_TABLE);
752
753                    const wasm_tabletype_t* table_type = wasm_externtype_as_tabletype_const(extern_type);
754                    assert(wasm_valtype_kind(wasm_tabletype_element(table_type)) == WASM_FUNCREF);
755
756                    const wasm_limits_t* table_limits = wasm_tabletype_limits(table_type);
757                    assert(table_limits->min == 1);
758                    assert(table_limits->max == 2);
759                }
760
761                {
762                    const wasm_importtype_t* import_type = import_types.data[3];
763
764                    const wasm_name_t* import_module = wasm_importtype_module(import_type);
765                    wasmer_assert_name(import_module, "ns");
766
767                    const wasm_name_t* import_name = wasm_importtype_name(import_type);
768                    wasmer_assert_name(import_name, "memory");
769
770                    const wasm_externtype_t* extern_type = wasm_importtype_type(import_type);
771                    assert(wasm_externtype_kind(extern_type) == WASM_EXTERN_MEMORY);
772
773                    const wasm_memorytype_t* memory_type = wasm_externtype_as_memorytype_const(extern_type);
774                    const wasm_limits_t* memory_limits = wasm_memorytype_limits(memory_type);
775                    assert(memory_limits->min == 3);
776                    assert(memory_limits->max == 4);
777                }
778
779                wasm_importtype_vec_delete(&import_types);
780                wasm_module_delete(module);
781                wasm_byte_vec_delete(&wasm);
782                wasm_byte_vec_delete(&wat);
783                wasm_store_delete(store);
784                wasm_engine_delete(engine);
785
786                return 0;
787            }
788        })
789        .success();
790    }
791
792    #[allow(
793        unexpected_cfgs,
794        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
795    )]
796    #[cfg_attr(coverage, ignore)]
797    #[test]
798    fn test_module_serialize() {
799        (assert_c! {
800            #include "tests/wasmer.h"
801
802            int main() {
803                wasm_engine_t* engine = wasm_engine_new();
804                wasm_store_t* store = wasm_store_new(engine);
805
806                wasm_byte_vec_t wat;
807                wasmer_byte_vec_new_from_string(&wat, "(module)");
808                wasm_byte_vec_t wasm;
809                wat2wasm(&wat, &wasm);
810
811                wasm_module_t* module = wasm_module_new(store, &wasm);
812                assert(module);
813
814                wasm_byte_vec_t serialized_module;
815                wasm_module_serialize(module, &serialized_module);
816                assert(serialized_module.size > 0);
817
818                wasm_module_delete(module);
819                wasm_byte_vec_delete(&serialized_module);
820                wasm_byte_vec_delete(&wasm);
821                wasm_byte_vec_delete(&wat);
822                wasm_store_delete(store);
823                wasm_engine_delete(engine);
824
825                return 0;
826            }
827        })
828        .success();
829    }
830
831    #[allow(
832        unexpected_cfgs,
833        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
834    )]
835    #[cfg_attr(coverage, ignore)]
836    #[test]
837    fn test_module_serialize_and_deserialize() {
838        (assert_c! {
839            #include "tests/wasmer.h"
840
841            int main() {
842                wasm_engine_t* engine = wasm_engine_new();
843                wasm_store_t* store = wasm_store_new(engine);
844
845                wasm_byte_vec_t wat;
846                wasmer_byte_vec_new_from_string(
847                    &wat,
848                    "(module\n"
849                    "  (func (export \"function\") (param i32 i64))\n"
850                    "  (global (export \"global\") i32 (i32.const 7))\n"
851                    "  (table (export \"table\") 0 funcref)\n"
852                    "  (memory (export \"memory\") 1))"
853                );
854                wasm_byte_vec_t wasm;
855                wat2wasm(&wat, &wasm);
856
857                wasm_module_t* module = wasm_module_new(store, &wasm);
858                assert(module);
859
860                wasm_byte_vec_t serialized_module;
861                wasm_module_serialize(module, &serialized_module);
862                assert(serialized_module.size > 0);
863
864                wasm_module_delete(module);
865                wasm_module_t* deserialized_module = wasm_module_deserialize(
866                    store,
867                    &serialized_module
868                );
869                wasm_byte_vec_delete(&serialized_module);
870                assert(deserialized_module);
871
872                wasm_exporttype_vec_t export_types;
873                wasm_module_exports(deserialized_module, &export_types);
874
875                assert(export_types.size == 4);
876
877                wasm_exporttype_vec_delete(&export_types);
878                wasm_module_delete(deserialized_module);
879                wasm_byte_vec_delete(&wasm);
880                wasm_byte_vec_delete(&wat);
881                wasm_store_delete(store);
882                wasm_engine_delete(engine);
883
884                return 0;
885            }
886        })
887        .success();
888    }
889}