Skip to main content

wasmedge_sys/
plugin.rs

1//! Defines PluginManager and Plugin structs.
2
3use super::ffi;
4use crate::{
5    instance::module::InnerInstance, types::WasmEdgeString, utils, Instance, WasmEdgeResult,
6};
7
8use std::ffi::CString;
9use wasmedge_types::error::{PluginError, WasmEdgeError};
10
11/// Defines the APIs for loading plugins and check the basic information of the loaded plugins.
12#[derive(Debug)]
13pub struct PluginManager {}
14impl PluginManager {
15    /// Load plugins from the default path. The default plugin path could be one of the following:
16    ///
17    /// * The environment variable "WASMEDGE_PLUGIN_PATH".
18    ///   
19    /// * The `../plugin/` directory related to the WasmEdge installation path.
20    ///
21    /// * The `wasmedge/` directory under the library path if the WasmEdge is installed under the "/usr".
22    pub fn load_plugins_from_default_paths() {
23        unsafe { ffi::WasmEdge_PluginLoadWithDefaultPaths() }
24    }
25
26    /// Load a single or multiple plugins from a given path.
27    ///
28    /// * If the path is pointing at a file , then it indicates that a single plugin will be loaded from the file.
29    ///
30    /// * If the path is pointing at a directory, then the method will load plugins from the files in the directory.
31    ///
32    /// # Argument
33    ///
34    /// * `param` - A path to a plugin file or a directory holding plugin files.
35    ///
36    /// # Error
37    ///
38    /// * If the path contains invalid characters, then an [WasmEdgeError::FoundNulByte](wasmedge_types::error::WasmEdgeError::FoundNulByte) error is returned.
39    pub fn load_plugins(path: impl AsRef<std::path::Path>) -> WasmEdgeResult<()> {
40        let c_path = utils::path_to_cstring(path.as_ref())?;
41        unsafe { ffi::WasmEdge_PluginLoadFromPath(c_path.as_ptr()) }
42
43        Ok(())
44    }
45
46    #[cfg(feature = "wasi_nn")]
47    #[cfg_attr(docsrs, doc(cfg(feature = "wasi_nn")))]
48    pub fn nn_preload(preloads: Vec<&str>) {
49        let c_args: Vec<CString> = preloads
50            .iter()
51            .map(|&x| std::ffi::CString::new(x).unwrap())
52            .collect();
53        let c_strs: Vec<*const ::std::os::raw::c_char> =
54            c_args.iter().map(|x| x.as_ptr()).collect();
55        let len = c_strs.len() as u32;
56        unsafe { ffi::WasmEdge_PluginInitWASINN(c_strs.as_ptr(), len) }
57    }
58
59    /// Returns the count of loaded plugins.
60    pub fn count() -> u32 {
61        unsafe { ffi::WasmEdge_PluginListPluginsLength() }
62    }
63
64    /// Returns the names of all loaded plugins.
65    pub fn names() -> Vec<String> {
66        let count = Self::count();
67        let mut names = Vec::with_capacity(count as usize);
68
69        unsafe {
70            ffi::WasmEdge_PluginListPlugins(names.as_mut_ptr(), count);
71            names.set_len(count as usize);
72        };
73
74        names.into_iter().map(|x| x.into()).collect::<Vec<String>>()
75    }
76
77    /// Returns the target plugin by its name.
78    ///
79    /// # Argument
80    ///
81    /// * `name` - The name of the target plugin.
82    ///
83    /// # Error
84    ///
85    /// If not found the plugin, then return [PluginError::NotFound](wasmedge_types::error::PluginError::NotFound) error.
86    pub fn find(name: impl AsRef<str>) -> WasmEdgeResult<Plugin> {
87        let plugin_name: WasmEdgeString = name.as_ref().into();
88
89        let ctx = unsafe { ffi::WasmEdge_PluginFind(plugin_name.as_raw()) };
90
91        match ctx.is_null() {
92            true => Err(Box::new(WasmEdgeError::Plugin(PluginError::NotFound(
93                name.as_ref().into(),
94            )))),
95            false => Ok(Plugin {
96                inner: InnerPlugin(ctx as *mut _),
97            }),
98        }
99    }
100
101    pub fn create_plugin_instance(
102        pname: impl AsRef<str>,
103        mname: impl AsRef<str>,
104    ) -> WasmEdgeResult<Instance> {
105        let plugin = Self::find(pname.as_ref())?;
106        plugin.mod_instance(mname.as_ref())
107    }
108
109    /// Initializes the `wasmedge_process` plugin module instance with the parameters.
110    ///
111    /// # Arguments
112    ///
113    /// * `allowed_cmds` - A white list of commands.
114    ///
115    /// * `allowed` - Determines if wasmedge_process is allowed to execute all commands on the white list.
116    #[cfg(all(
117        target_os = "linux",
118        feature = "wasmedge_process",
119        not(feature = "static")
120    ))]
121    #[cfg_attr(
122        docsrs,
123        doc(cfg(all(
124            target_os = "linux",
125            feature = "wasmedge_process",
126            not(feature = "static")
127        )))
128    )]
129    pub fn init_wasmedge_process(allowed_cmds: Option<Vec<&str>>, allowed: bool) {
130        // parse cmds
131        let cstr_cmds: Vec<_> = match allowed_cmds {
132            Some(cmds) => cmds
133                .iter()
134                .map(|&x| std::ffi::CString::new(x).unwrap())
135                .collect(),
136            None => vec![],
137        };
138        let mut p_cmds: Vec<_> = cstr_cmds.iter().map(|x| x.as_ptr()).collect();
139        let p_cmds_len = p_cmds.len();
140        p_cmds.push(std::ptr::null());
141
142        unsafe {
143            ffi::WasmEdge_ModuleInstanceInitWasmEdgeProcess(
144                p_cmds.as_ptr(),
145                p_cmds_len as u32,
146                allowed,
147            )
148        }
149    }
150}
151
152/// Represents a loaded plugin. It provides the APIs for accessing the plugin.
153#[derive(Debug, Clone, Copy)]
154pub struct Plugin {
155    pub(crate) inner: InnerPlugin,
156}
157impl Plugin {
158    /// Returns the name of this plugin.
159    pub fn name(&self) -> String {
160        let name = unsafe { ffi::WasmEdge_PluginGetPluginName(self.inner.0) };
161        name.into()
162    }
163
164    /// Returns the count of the module instances in this plugin.
165    pub fn mod_count(&self) -> u32 {
166        unsafe { ffi::WasmEdge_PluginListModuleLength(self.inner.0) }
167    }
168
169    /// Returns the names of all module instances in this plugin.
170    pub fn mod_names(&self) -> Vec<String> {
171        let count = self.mod_count();
172        let mut names = Vec::with_capacity(count as usize);
173
174        unsafe {
175            ffi::WasmEdge_PluginListModule(self.inner.0, names.as_mut_ptr(), count);
176            names.set_len(count as usize);
177        }
178
179        names.into_iter().map(|x| x.into()).collect::<Vec<String>>()
180    }
181
182    /// Returns a plugin module instance that is generated from the module with the given name in this plugin.
183    ///
184    /// # Argument
185    ///
186    /// * `name` - The name of the target module.
187    ///
188    /// # Error
189    ///
190    /// If failed to return the plugin module instance, then return [PluginError::Create](wasmedge_types::error::PluginError::Create) error.
191    pub fn mod_instance(&self, name: impl AsRef<str>) -> WasmEdgeResult<Instance> {
192        let mod_name: WasmEdgeString = name.as_ref().into();
193
194        let ctx = unsafe { ffi::WasmEdge_PluginCreateModule(self.inner.0, mod_name.as_raw()) };
195
196        match ctx.is_null() {
197            true => Err(Box::new(WasmEdgeError::Plugin(PluginError::Create(
198                name.as_ref().into(),
199            )))),
200            false => Ok(Instance {
201                inner: InnerInstance(ctx),
202            }),
203        }
204    }
205
206    /// # Safety
207    ///
208    /// The lifetime of the returned pointer must not exceed that of the object itself.
209    pub unsafe fn as_ptr(&self) -> *const ffi::WasmEdge_PluginContext {
210        self.inner.0 as *const _
211    }
212}
213
214#[derive(Debug, Clone, Copy)]
215pub(crate) struct InnerPlugin(pub(crate) *mut ffi::WasmEdge_PluginContext);
216unsafe impl Send for InnerPlugin {}
217unsafe impl Sync for InnerPlugin {}
218
219/// Defines the type of the program options.
220#[derive(Debug, Clone, Copy, PartialEq, Eq)]
221pub enum ProgramOptionType {
222    None = 0,
223    Toggle = 1,
224    I8 = 2,
225    I16 = 3,
226    I32 = 4,
227    I64 = 5,
228    U8 = 6,
229    U16 = 7,
230    U32 = 8,
231    U64 = 9,
232    F32 = 10,
233    F64 = 11,
234    String = 12,
235}
236impl From<ffi::WasmEdge_ProgramOptionType> for ProgramOptionType {
237    fn from(ty: ffi::WasmEdge_ProgramOptionType) -> Self {
238        match ty {
239            ffi::WasmEdge_ProgramOptionType_None => ProgramOptionType::None,
240            ffi::WasmEdge_ProgramOptionType_Toggle => ProgramOptionType::Toggle,
241            ffi::WasmEdge_ProgramOptionType_Int8 => ProgramOptionType::I8,
242            ffi::WasmEdge_ProgramOptionType_Int16 => ProgramOptionType::I16,
243            ffi::WasmEdge_ProgramOptionType_Int32 => ProgramOptionType::I32,
244            ffi::WasmEdge_ProgramOptionType_Int64 => ProgramOptionType::I64,
245            ffi::WasmEdge_ProgramOptionType_UInt8 => ProgramOptionType::U8,
246            ffi::WasmEdge_ProgramOptionType_UInt16 => ProgramOptionType::U16,
247            ffi::WasmEdge_ProgramOptionType_UInt32 => ProgramOptionType::U32,
248            ffi::WasmEdge_ProgramOptionType_UInt64 => ProgramOptionType::U64,
249            ffi::WasmEdge_ProgramOptionType_Float => ProgramOptionType::F32,
250            ffi::WasmEdge_ProgramOptionType_Double => ProgramOptionType::F64,
251            ffi::WasmEdge_ProgramOptionType_String => ProgramOptionType::String,
252            _ => {
253                panic!("[wasmedge-sys] Unsupported ffi::WasmEdge_ProgramOptionType value: {ty}");
254            }
255        }
256    }
257}
258impl From<ProgramOptionType> for ffi::WasmEdge_ProgramOptionType {
259    fn from(value: ProgramOptionType) -> Self {
260        match value {
261            ProgramOptionType::None => ffi::WasmEdge_ProgramOptionType_None,
262            ProgramOptionType::Toggle => ffi::WasmEdge_ProgramOptionType_Toggle,
263            ProgramOptionType::I8 => ffi::WasmEdge_ProgramOptionType_Int8,
264            ProgramOptionType::I16 => ffi::WasmEdge_ProgramOptionType_Int16,
265            ProgramOptionType::I32 => ffi::WasmEdge_ProgramOptionType_Int32,
266            ProgramOptionType::I64 => ffi::WasmEdge_ProgramOptionType_Int64,
267            ProgramOptionType::U8 => ffi::WasmEdge_ProgramOptionType_UInt8,
268            ProgramOptionType::U16 => ffi::WasmEdge_ProgramOptionType_UInt16,
269            ProgramOptionType::U32 => ffi::WasmEdge_ProgramOptionType_UInt32,
270            ProgramOptionType::U64 => ffi::WasmEdge_ProgramOptionType_UInt64,
271            ProgramOptionType::F32 => ffi::WasmEdge_ProgramOptionType_Float,
272            ProgramOptionType::F64 => ffi::WasmEdge_ProgramOptionType_Double,
273            ProgramOptionType::String => ffi::WasmEdge_ProgramOptionType_String,
274        }
275    }
276}
277
278/// Defines the program option for plugins.
279#[derive(Debug)]
280pub struct ProgramOption {
281    name: CString,
282    desc: CString,
283    pub inner: ffi::WasmEdge_ProgramOption,
284}
285impl ProgramOption {
286    /// Creates a new program option.
287    pub fn create(
288        name: impl AsRef<str>,
289        desc: impl AsRef<str>,
290        ty: ProgramOptionType,
291    ) -> WasmEdgeResult<Self> {
292        let name = std::ffi::CString::new(name.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
293
294        let desc = std::ffi::CString::new(desc.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
295
296        let mut po = Self {
297            name,
298            desc,
299            inner: ffi::WasmEdge_ProgramOption {
300                Name: std::ptr::null(),
301                Description: std::ptr::null(),
302                Type: ty.into(),
303                Storage: std::ptr::null_mut(),
304                DefaultValue: std::ptr::null(),
305            },
306        };
307        po.inner.Name = po.name.as_ptr();
308        po.inner.Description = po.desc.as_ptr();
309
310        Ok(po)
311    }
312}
313unsafe impl Send for ProgramOption {}
314unsafe impl Sync for ProgramOption {}
315
316/// Defines the module descriptor for plugins.
317#[derive(Debug)]
318pub struct ModuleDescriptor {
319    name: CString,
320    desc: CString,
321    create: Option<ModuleInstanceCreateFn>,
322    inner: ffi::WasmEdge_ModuleDescriptor,
323}
324impl ModuleDescriptor {
325    /// Creates a new module descriptor.
326    pub fn create(
327        name: impl AsRef<str>,
328        desc: impl AsRef<str>,
329        f: Option<ModuleInstanceCreateFn>,
330    ) -> WasmEdgeResult<Self> {
331        // module name
332        let name = std::ffi::CString::new(name.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
333
334        // module description
335        let desc = std::ffi::CString::new(desc.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
336
337        let mut md = Self {
338            name,
339            desc,
340            create: f,
341            inner: ffi::WasmEdge_ModuleDescriptor {
342                Name: std::ptr::null(),
343                Description: std::ptr::null(),
344                Create: None,
345            },
346        };
347        md.inner.Name = md.name.as_ptr();
348        md.inner.Description = md.desc.as_ptr();
349        md.inner.Create = md.create;
350
351        Ok(md)
352    }
353
354    /// Returns the raw pointer to the inner `WasmEdge_ModuleDescriptor`.
355    #[cfg(feature = "ffi")]
356    #[cfg_attr(docsrs, doc(cfg(feature = "ffi")))]
357    pub fn as_raw_ptr(&self) -> *const ffi::WasmEdge_ModuleDescriptor {
358        &self.inner
359    }
360}
361
362/// Defines the type of the function that creates a module instance for a plugin.
363pub type ModuleInstanceCreateFn = unsafe extern "C" fn(
364    arg1: *const ffi::WasmEdge_ModuleDescriptor,
365) -> *mut ffi::WasmEdge_ModuleInstanceContext;
366
367/// Defines the version of a plugin.
368#[derive(Debug)]
369pub struct PluginVersion {
370    pub major: u32,
371    pub minor: u32,
372    pub patch: u32,
373    pub build: u32,
374}
375impl PluginVersion {
376    /// Creates a new plugin version.
377    pub fn create(major: u32, minor: u32, patch: u32, build: u32) -> Self {
378        Self {
379            major,
380            minor,
381            patch,
382            build,
383        }
384    }
385}
386impl From<PluginVersion> for ffi::WasmEdge_PluginVersionData {
387    fn from(value: PluginVersion) -> Self {
388        Self {
389            Major: value.major,
390            Minor: value.minor,
391            Patch: value.patch,
392            Build: value.build,
393        }
394    }
395}
396
397/// Represents Plugin descriptor for plugins.
398#[derive(Debug)]
399pub struct PluginDescriptor {
400    name: CString,
401    desc: CString,
402    module_descriptors_name_desc: Vec<(CString, CString)>,
403    module_descriptors: Vec<ffi::WasmEdge_ModuleDescriptor>,
404    program_options_name_desc: Vec<(CString, CString)>,
405    program_options: Vec<ffi::WasmEdge_ProgramOption>,
406    inner: ffi::WasmEdge_PluginDescriptor,
407}
408impl PluginDescriptor {
409    pub fn create(
410        name: impl AsRef<str>,
411        desc: impl AsRef<str>,
412        version: PluginVersion,
413    ) -> WasmEdgeResult<Self> {
414        // plugin name
415        let name = std::ffi::CString::new(name.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
416
417        // plugin description
418        let desc = std::ffi::CString::new(desc.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
419
420        let mut pd = Self {
421            name,
422            desc,
423            module_descriptors_name_desc: Vec::new(),
424            module_descriptors: Vec::new(),
425            program_options_name_desc: Vec::new(),
426            program_options: Vec::new(),
427            inner: ffi::WasmEdge_PluginDescriptor {
428                Name: std::ptr::null(),
429                Description: std::ptr::null(),
430                APIVersion: ffi::WasmEdge_Plugin_CurrentAPIVersion,
431                Version: version.into(),
432                ModuleCount: 0,
433                ModuleDescriptions: std::ptr::null_mut(),
434                ProgramOptionCount: 0,
435                ProgramOptions: std::ptr::null_mut(),
436            },
437        };
438        pd.inner.Name = pd.name.as_ptr();
439        pd.inner.Description = pd.desc.as_ptr();
440
441        Ok(pd)
442    }
443
444    pub fn add_module_descriptor(
445        mut self,
446        name: impl AsRef<str>,
447        desc: impl AsRef<str>,
448        f: Option<ModuleInstanceCreateFn>,
449    ) -> WasmEdgeResult<Self> {
450        // module name
451        let name = std::ffi::CString::new(name.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
452
453        // module description
454        let desc = std::ffi::CString::new(desc.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
455
456        self.module_descriptors
457            .push(ffi::WasmEdge_ModuleDescriptor {
458                Name: name.as_ptr(),
459                Description: desc.as_ptr(),
460                Create: f,
461            });
462        self.module_descriptors_name_desc.push((name, desc));
463
464        self.inner.ModuleCount = self.module_descriptors.len() as u32;
465        self.inner.ModuleDescriptions = self.module_descriptors.as_mut_ptr();
466
467        Ok(self)
468    }
469
470    pub fn add_program_option(
471        mut self,
472        name: impl AsRef<str>,
473        desc: impl AsRef<str>,
474        ty: ProgramOptionType,
475    ) -> WasmEdgeResult<Self> {
476        let name = std::ffi::CString::new(name.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
477
478        let desc = std::ffi::CString::new(desc.as_ref()).map_err(WasmEdgeError::FoundNulByte)?;
479
480        self.program_options.push(ffi::WasmEdge_ProgramOption {
481            Name: name.as_ptr(),
482            Description: desc.as_ptr(),
483            Type: ty.into(),
484            Storage: std::ptr::null_mut(),
485            DefaultValue: std::ptr::null(),
486        });
487        self.program_options_name_desc.push((name, desc));
488
489        self.inner.ProgramOptionCount = self.program_options.len() as u32;
490        self.inner.ProgramOptions = self.program_options.as_mut_ptr();
491
492        Ok(self)
493    }
494
495    /// Returns the raw pointer to the inner `WasmEdge_PluginDescriptor`.
496    #[cfg(feature = "ffi")]
497    #[cfg_attr(docsrs, doc(cfg(feature = "ffi")))]
498    pub fn as_raw_ptr(&self) -> *const ffi::WasmEdge_PluginDescriptor {
499        &self.inner
500    }
501}
502
503/// Represents a Plugin module instance.
504pub type PluginModule = Instance;
505
506#[cfg(test)]
507mod tests {
508
509    #[cfg(all(
510        target_os = "linux",
511        feature = "wasmedge_process",
512        not(feature = "static")
513    ))]
514    #[test]
515    #[ignore]
516    fn test_plugin_wasmedge_process() {
517        use crate::AsInstance;
518
519        use super::*;
520
521        PluginManager::load_plugins_from_default_paths();
522        assert!(PluginManager::count() >= 1);
523        assert!(PluginManager::names()
524            .iter()
525            .any(|x| x == "wasmedge_process"));
526
527        // get `wasmedge_process` plugin
528        let result = PluginManager::find("wasmedge_process");
529        assert!(result.is_ok());
530        let plugin = result.unwrap();
531        assert_eq!(plugin.name(), "wasmedge_process");
532        assert_eq!(plugin.mod_count(), 1);
533        assert!(plugin.mod_names().iter().any(|x| x == "wasmedge_process"));
534
535        // get module instance from plugin
536        let result = plugin.mod_instance("wasmedge_process");
537        assert!(result.is_ok());
538        let instance = result.unwrap();
539
540        assert_eq!(instance.name().unwrap(), "wasmedge_process");
541        assert_eq!(instance.func_len(), 11);
542        assert_eq!(
543            instance.func_names().unwrap(),
544            [
545                "wasmedge_process_add_arg",
546                "wasmedge_process_add_env",
547                "wasmedge_process_add_stdin",
548                "wasmedge_process_get_exit_code",
549                "wasmedge_process_get_stderr",
550                "wasmedge_process_get_stderr_len",
551                "wasmedge_process_get_stdout",
552                "wasmedge_process_get_stdout_len",
553                "wasmedge_process_run",
554                "wasmedge_process_set_prog_name",
555                "wasmedge_process_set_timeout",
556            ]
557        );
558        assert_eq!(instance.mem_len(), 0);
559        assert_eq!(instance.table_len(), 0);
560        assert_eq!(instance.global_len(), 0);
561    }
562
563    #[cfg(all(target_os = "linux", feature = "wasi_crypto", not(feature = "static")))]
564    #[test]
565    fn test_plugin_wasi_crypto() {
566        use crate::AsInstance;
567
568        use super::*;
569
570        PluginManager::load_plugins_from_default_paths();
571        assert!(PluginManager::count() >= 1);
572        assert!(
573            PluginManager::names().iter().any(|x| x == "wasi_crypto"),
574            "Not found the `wasi_crypto` plugin"
575        );
576
577        // get `wasmedge_process` plugin
578        let result = PluginManager::find("wasi_crypto");
579        assert!(result.is_ok());
580        let plugin = result.unwrap();
581        assert_eq!(plugin.name(), "wasi_crypto");
582        assert_eq!(plugin.mod_count(), 5);
583        assert_eq!(
584            plugin.mod_names(),
585            [
586                "wasi_crypto_asymmetric_common",
587                "wasi_crypto_common",
588                "wasi_crypto_kx",
589                "wasi_crypto_signatures",
590                "wasi_crypto_symmetric",
591            ]
592        );
593
594        // get `wasi_crypto_asymmetric_common` module instance from plugin
595        {
596            let result = plugin.mod_instance("wasi_crypto_asymmetric_common");
597            assert!(result.is_ok());
598            let instance = result.unwrap();
599            assert_eq!(
600                instance.name().unwrap(),
601                "wasi_ephemeral_crypto_asymmetric_common"
602            );
603            assert_eq!(instance.func_len(), 20);
604            assert_eq!(
605                instance.func_names().unwrap(),
606                [
607                    "keypair_close",
608                    "keypair_export",
609                    "keypair_from_id",
610                    "keypair_from_pk_and_sk",
611                    "keypair_generate",
612                    "keypair_generate_managed",
613                    "keypair_id",
614                    "keypair_import",
615                    "keypair_publickey",
616                    "keypair_replace_managed",
617                    "keypair_secretkey",
618                    "keypair_store_managed",
619                    "publickey_close",
620                    "publickey_export",
621                    "publickey_from_secretkey",
622                    "publickey_import",
623                    "publickey_verify",
624                    "secretkey_close",
625                    "secretkey_export",
626                    "secretkey_import",
627                ],
628            );
629        }
630
631        // get `wasi_crypto_common` module instance from plugin
632        {
633            let result = plugin.mod_instance("wasi_crypto_common");
634            assert!(result.is_ok());
635            let instance = result.unwrap();
636            assert_eq!(instance.name().unwrap(), "wasi_ephemeral_crypto_common");
637            assert_eq!(instance.func_len(), 10);
638            assert_eq!(
639                instance.func_names().unwrap(),
640                [
641                    "array_output_len",
642                    "array_output_pull",
643                    "options_close",
644                    "options_open",
645                    "options_set",
646                    "options_set_guest_buffer",
647                    "options_set_u64",
648                    "secrets_manager_close",
649                    "secrets_manager_invalidate",
650                    "secrets_manager_open",
651                ],
652            );
653        }
654
655        // get `wasi_crypto_kx` module instance from plugin
656        {
657            let result = plugin.mod_instance("wasi_crypto_kx");
658            assert!(result.is_ok());
659            let instance = result.unwrap();
660            assert_eq!(instance.name().unwrap(), "wasi_ephemeral_crypto_kx");
661            assert_eq!(instance.func_len(), 3);
662            assert_eq!(
663                instance.func_names().unwrap(),
664                ["kx_decapsulate", "kx_dh", "kx_encapsulate",],
665            );
666        }
667
668        // get `wasi_crypto_signatures` module instance from plugin
669        {
670            let result = plugin.mod_instance("wasi_crypto_signatures");
671            assert!(result.is_ok());
672            let instance = result.unwrap();
673            assert_eq!(instance.name().unwrap(), "wasi_ephemeral_crypto_signatures");
674            assert_eq!(instance.func_len(), 11);
675            assert_eq!(
676                instance.func_names().unwrap(),
677                [
678                    "signature_close",
679                    "signature_export",
680                    "signature_import",
681                    "signature_state_close",
682                    "signature_state_open",
683                    "signature_state_sign",
684                    "signature_state_update",
685                    "signature_verification_state_close",
686                    "signature_verification_state_open",
687                    "signature_verification_state_update",
688                    "signature_verification_state_verify",
689                ],
690            );
691        }
692
693        // get `wasi_crypto_symmetric` module instance from plugin
694        {
695            let result = plugin.mod_instance("wasi_crypto_symmetric");
696            assert!(result.is_ok());
697            let instance = result.unwrap();
698            assert_eq!(instance.name().unwrap(), "wasi_ephemeral_crypto_symmetric");
699            assert_eq!(instance.func_len(), 28);
700            assert_eq!(
701                instance.func_names().unwrap(),
702                [
703                    "symmetric_key_close",
704                    "symmetric_key_export",
705                    "symmetric_key_from_id",
706                    "symmetric_key_generate",
707                    "symmetric_key_generate_managed",
708                    "symmetric_key_id",
709                    "symmetric_key_import",
710                    "symmetric_key_replace_managed",
711                    "symmetric_key_store_managed",
712                    "symmetric_state_absorb",
713                    "symmetric_state_clone",
714                    "symmetric_state_close",
715                    "symmetric_state_decrypt",
716                    "symmetric_state_decrypt_detached",
717                    "symmetric_state_encrypt",
718                    "symmetric_state_encrypt_detached",
719                    "symmetric_state_max_tag_len",
720                    "symmetric_state_open",
721                    "symmetric_state_options_get",
722                    "symmetric_state_options_get_u64",
723                    "symmetric_state_ratchet",
724                    "symmetric_state_squeeze",
725                    "symmetric_state_squeeze_key",
726                    "symmetric_state_squeeze_tag",
727                    "symmetric_tag_close",
728                    "symmetric_tag_len",
729                    "symmetric_tag_pull",
730                    "symmetric_tag_verify",
731                ],
732            );
733        }
734    }
735}