wasmcloud_provider_core/capabilities.rs
1//! # Common types used for managing native capability providers
2
3use std::error::Error;
4
5use std::any::Any;
6
7/// The dispatcher is used by a native capability provider to send commands to an actor, expecting
8/// a result containing a byte array in return
9pub trait Dispatcher: Any + Send + Sync {
10 fn dispatch(
11 &self,
12 actor: &str,
13 op: &str,
14 msg: &[u8],
15 ) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>>;
16}
17
18/// The NullDispatcher is as its name implies--a dispatcher that does nothing. This is convenient for
19/// initializing a capability provider with a null dispatcher, and then swapping it for a real dispatcher
20/// when the host runtime provides one configured with the appropriate channels
21#[derive(Default)]
22pub struct NullDispatcher {}
23
24impl NullDispatcher {
25 pub fn new() -> NullDispatcher {
26 NullDispatcher {}
27 }
28}
29
30impl Dispatcher for NullDispatcher {
31 fn dispatch(
32 &self,
33 _actor: &str,
34 _op: &str,
35 _msg: &[u8],
36 ) -> Result<Vec<u8>, Box<dyn Error + Send + Sync>> {
37 unimplemented!()
38 }
39}
40
41/// Every native capability provider must implement this trait. Both portable and native capability providers
42/// must respond to the following operations: `OP_BIND_ACTOR`, `OP_REMOVE_ACTOR`
43pub trait CapabilityProvider: CloneProvider + Send + Sync {
44 /// This function will be called on the provider when the host runtime is ready and has configured a dispatcher. This function is only ever
45 /// called _once_ for a capability provider, regardless of the number of actors being managed in the host
46 fn configure_dispatch(
47 &self,
48 dispatcher: Box<dyn Dispatcher>,
49 ) -> Result<(), Box<dyn Error + Send + Sync>>;
50 /// Invoked when an actor has requested that a provider perform a given operation
51 fn handle_call(
52 &self,
53 actor: &str,
54 op: &str,
55 msg: &[u8],
56 ) -> Result<Vec<u8>, Box<dyn Error + Send + Sync>>;
57 /// This function is called to let the capability provider know that it is being removed
58 /// from the host runtime. This gives the provider an opportunity to clean up any
59 /// resources and stop any running threads.
60 /// WARNING: do not do anything in this function that can
61 /// cause a panic, including attempting to write to STDOUT while the host process is terminating
62 fn stop(&self);
63}
64
65#[doc(hidden)]
66pub trait CloneProvider {
67 fn clone_provider(&self) -> Box<dyn CapabilityProvider>;
68}
69
70impl<T> CloneProvider for T
71where
72 T: CapabilityProvider + Clone + 'static,
73{
74 fn clone_provider(&self) -> Box<dyn CapabilityProvider> {
75 Box::new(self.clone())
76 }
77}
78
79impl Clone for Box<dyn CapabilityProvider> {
80 fn clone(&self) -> Self {
81 self.clone_provider()
82 }
83}
84
85/// Wraps a constructor inside an FFI function to allow the `CapabilityProvider` trait implementation
86/// to be instantiated and used by the host runtime
87#[macro_export]
88macro_rules! capability_provider {
89 ($provider_type:ty, $constructor:path) => {
90 #[no_mangle]
91 pub extern "C" fn __capability_provider_create(
92 ) -> *mut $crate::capabilities::CapabilityProvider {
93 let constructor: fn() -> $provider_type = $constructor;
94 let object = constructor();
95 let boxed: Box<$crate::capabilities::CapabilityProvider> = Box::new(object);
96 Box::into_raw(boxed)
97 }
98 };
99}