wasm_link/
plugin_instance.rs1use thiserror::Error ;
2use wasmtime::component::{ Component, Instance, Val };
3use wasmtime::Store ;
4
5use crate::plugin::PluginData ;
6use crate::interface::InterfaceData ;
7use crate::loading::{ ResourceCreationError, ResourceReceiveError };
8
9
10
11pub struct PluginInstance<P: PluginData + 'static> {
12 pub(crate) id: P::Id,
13 pub(crate) _component: Component,
14 pub(crate) store: Store<P>,
15 pub(crate) instance: Instance,
16}
17
18impl<P: PluginData + std::fmt::Debug> std::fmt::Debug for PluginInstance<P> {
19 fn fmt( &self, f: &mut std::fmt::Formatter<'_> ) -> std::result::Result<(), std::fmt::Error> {
20 f.debug_struct( "Plugin Instance" )
21 .field( "id", &self.id )
22 .field( "data", &self.store.data() )
23 .field( "store", &self.store )
24 .finish_non_exhaustive()
25 }
26}
27
28#[derive( Error, Debug )]
36pub enum DispatchError<I: InterfaceData> {
37 #[error( "Deadlock" )] Deadlock,
39 #[error( "Interface Error: {0}")] WitParserError( I::Error ),
41 #[error( "Invalid Interface: {0}" )] InvalidInterface( String ),
43 #[error( "Invalid Function: {0}" )] InvalidFunction( String ),
45 #[error( "Missing Response" )] MissingResponse,
47 #[error( "Runtime Exception" )] RuntimeException( wasmtime::Error ),
49 #[error( "Invalid Argument List" )] InvalidArgumentList,
51 #[error( "Unsupported type: {0}" )] UnsupportedType( String ),
53 #[error( "Resource Create Error: {0}" )] ResourceCreationError( #[from] ResourceCreationError ),
55 #[error( "Resource Receive Error: {0}" )] ResourceReceiveError( #[from] ResourceReceiveError ),
57}
58
59impl<I: InterfaceData> From<DispatchError<I>> for Val {
60 fn from( error: DispatchError<I> ) -> Val { match error {
61 DispatchError::Deadlock => Val::Variant( "deadlock".to_string(), None ),
62 DispatchError::WitParserError( err ) => Val::Variant( "wit-parser-error".to_string(), Some( Box::new( Val::String( err.to_string() )))),
63 DispatchError::InvalidInterface( package ) => Val::Variant( "invalid-interface".to_string(), Some( Box::new( Val::String( package )))),
64 DispatchError::InvalidFunction( function ) => Val::Variant( "invalid-function".to_string(), Some( Box::new( Val::String( function )))),
65 DispatchError::MissingResponse => Val::Variant( "missing-response".to_string(), None ),
66 DispatchError::RuntimeException( exception ) => Val::Variant( "runtime-exception".to_string(), Some( Box::new( Val::String( exception.to_string() )))),
67 DispatchError::InvalidArgumentList => Val::Variant( "invalid-argument-list".to_string(), None ),
68 DispatchError::UnsupportedType( name ) => Val::Variant( "unsupported-type".to_string(), Some( Box::new( Val::String( name )))),
69 DispatchError::ResourceCreationError( err ) => err.into(),
70 DispatchError::ResourceReceiveError( err ) => err.into(),
71 }}
72}
73
74impl<P: PluginData> PluginInstance<P> {
75
76 pub fn id( &self ) -> &P::Id { &self.id }
77
78 const PLACEHOLDER_VAL: Val = Val::Tuple( vec![] );
79
80 pub(crate) fn dispatch<I: InterfaceData>(
81 &mut self,
82 interface_path: &str,
83 function: &str,
84 returns: bool,
85 data: &[Val],
86 ) -> Result<Val, DispatchError<I>> {
87
88 let mut buffer = match returns {
89 true => vec![ Self::PLACEHOLDER_VAL ],
90 false => Vec::with_capacity( 0 ),
91 };
92
93 let interface_index = self.instance
94 .get_export_index( &mut self.store, None, interface_path )
95 .ok_or( DispatchError::InvalidInterface( interface_path.to_string() ))?;
96 let func_index = self.instance
97 .get_export_index( &mut self.store, Some( &interface_index ), function )
98 .ok_or( DispatchError::InvalidFunction( format!( "{}:{}", interface_path, function )))?;
99 let func = self.instance
100 .get_func( &mut self.store, func_index )
101 .ok_or( DispatchError::InvalidFunction( format!( "{}:{}", interface_path, function )))?;
102 func
103 .call( &mut self.store, data, &mut buffer )
104 .map_err( DispatchError::RuntimeException )?;
105 let _ = func.post_return( &mut self.store );
106
107 Ok( match returns {
108 true => buffer.pop().ok_or( DispatchError::MissingResponse )?,
109 false => Self::PLACEHOLDER_VAL,
110 })
111
112 }
113}