1use std::error::Error;
4
5use std::any::Any;
6
7pub const OP_GET_CAPABILITY_DESCRIPTOR: &str = "GetCapabilityDescriptor";
10
11#[deprecated = "The capability provider functionality from this crate has been moved to wasmcloud-provider-core"]
14pub trait Dispatcher: Any + Send + Sync {
15 fn dispatch(
16 &self,
17 actor: &str,
18 op: &str,
19 msg: &[u8],
20 ) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>>;
21}
22
23#[deprecated = "The capability provider functionality from this crate has been moved to wasmcloud-provider-core"]
25#[repr(C)]
26#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
27pub struct CapabilityDescriptor {
28 pub id: String,
30 pub name: String,
32 pub version: String,
34 pub revision: u32,
36 pub long_description: String,
38 pub supported_operations: Vec<OperationDescriptor>,
40}
41
42impl CapabilityDescriptor {
43 pub fn builder() -> CapabilityDescriptorBuilder {
44 CapabilityDescriptorBuilder::new()
45 }
46}
47
48#[derive(Default)]
50pub struct CapabilityDescriptorBuilder {
51 descriptor: CapabilityDescriptor,
52}
53
54impl CapabilityDescriptorBuilder {
55 fn new() -> CapabilityDescriptorBuilder {
57 CapabilityDescriptorBuilder::default()
58 }
59
60 pub fn id(self, id: &str) -> Self {
62 CapabilityDescriptorBuilder {
63 descriptor: CapabilityDescriptor {
64 id: id.to_string(),
65 ..self.descriptor
66 },
67 }
68 }
69
70 pub fn name(self, name: &str) -> Self {
72 CapabilityDescriptorBuilder {
73 descriptor: CapabilityDescriptor {
74 name: name.to_string(),
75 ..self.descriptor
76 },
77 }
78 }
79
80 pub fn long_description(self, desc: &str) -> Self {
82 CapabilityDescriptorBuilder {
83 descriptor: CapabilityDescriptor {
84 long_description: desc.to_string(),
85 ..self.descriptor
86 },
87 }
88 }
89
90 pub fn version(self, ver: &str) -> Self {
92 CapabilityDescriptorBuilder {
93 descriptor: CapabilityDescriptor {
94 version: ver.to_string(),
95 ..self.descriptor
96 },
97 }
98 }
99
100 pub fn revision(self, rev: u32) -> Self {
102 CapabilityDescriptorBuilder {
103 descriptor: CapabilityDescriptor {
104 revision: rev,
105 ..self.descriptor
106 },
107 }
108 }
109
110 pub fn with_operation(self, name: &str, direction: OperationDirection, doctext: &str) -> Self {
112 let mut newops = self.descriptor.supported_operations;
113 newops.push(OperationDescriptor::new(name, direction, doctext));
114 CapabilityDescriptorBuilder {
115 descriptor: CapabilityDescriptor {
116 supported_operations: newops,
117 ..self.descriptor
118 },
119 }
120 }
121
122 pub fn build(self) -> CapabilityDescriptor {
124 self.descriptor
125 }
126}
127
128#[deprecated = "The capability provider functionality from this crate has been moved to wasmcloud-provider-core"]
130#[repr(C)]
131#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
132pub struct OperationDescriptor {
133 pub name: String,
135 pub direction: OperationDirection,
137 pub doctext: String,
139}
140
141impl OperationDescriptor {
142 pub fn new(name: &str, direction: OperationDirection, doctext: &str) -> OperationDescriptor {
144 OperationDescriptor {
145 name: name.to_string(),
146 direction,
147 doctext: doctext.to_string(),
148 }
149 }
150}
151
152#[deprecated = "The capability provider functionality from this crate has been moved to wasmcloud-provider-core"]
154#[repr(C)]
155#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
156#[serde(rename_all = "snake_case")]
157pub enum OperationDirection {
158 ToActor,
159 ToProvider,
160 Both,
161}
162
163#[deprecated = "The capability provider functionality from this crate has been moved to wasmcloud-provider-core"]
167#[derive(Default)]
168pub struct NullDispatcher {}
169
170impl NullDispatcher {
171 pub fn new() -> NullDispatcher {
172 NullDispatcher {}
173 }
174}
175
176impl Dispatcher for NullDispatcher {
177 fn dispatch(
178 &self,
179 _actor: &str,
180 _op: &str,
181 _msg: &[u8],
182 ) -> Result<Vec<u8>, Box<dyn Error + Send + Sync>> {
183 unimplemented!()
184 }
185}
186
187pub trait CapabilityProvider: CloneProvider + Send + Sync {
190 fn configure_dispatch(
193 &self,
194 dispatcher: Box<dyn Dispatcher>,
195 ) -> Result<(), Box<dyn Error + Send + Sync>>;
196 fn handle_call(
198 &self,
199 actor: &str,
200 op: &str,
201 msg: &[u8],
202 ) -> Result<Vec<u8>, Box<dyn Error + Send + Sync>>;
203 fn stop(&self);
207}
208
209pub trait CloneProvider {
210 fn clone_provider(&self) -> Box<dyn CapabilityProvider>;
211}
212
213impl<T> CloneProvider for T
214where
215 T: CapabilityProvider + Clone + 'static,
216{
217 fn clone_provider(&self) -> Box<dyn CapabilityProvider> {
218 Box::new(self.clone())
219 }
220}
221
222impl Clone for Box<dyn CapabilityProvider> {
223 fn clone(&self) -> Self {
224 self.clone_provider()
225 }
226}
227
228#[macro_export]
231macro_rules! capability_provider {
232 ($provider_type:ty, $constructor:path) => {
233 #[no_mangle]
234 pub extern "C" fn __capability_provider_create(
235 ) -> *mut $crate::capabilities::CapabilityProvider {
236 let constructor: fn() -> $provider_type = $constructor;
237 let object = constructor();
238 let boxed: Box<$crate::capabilities::CapabilityProvider> = Box::new(object);
239 Box::into_raw(boxed)
240 }
241 };
242}
243
244#[cfg(test)]
245mod test {
246 use super::{CapabilityDescriptor, OperationDescriptor, OperationDirection};
247 #[test]
248 fn descriptor_certify_desired_json_format() {
249 let d = CapabilityDescriptor {
250 name: "test".to_string(),
251 id: "wascc:testing".to_string(),
252 version: "0.0.1".to_string(),
253 revision: 1,
254 long_description: "this is a test".to_string(),
255 supported_operations: vec![OperationDescriptor {
256 direction: OperationDirection::ToActor,
257 doctext: "this is a test".to_string(),
258 name: "OperationDumboDrop".to_string(),
259 }],
260 };
261 let s = serde_json::to_string(&d).unwrap();
262 assert_eq!(s, "{\"id\":\"wascc:testing\",\"name\":\"test\",\"version\":\"0.0.1\",\"revision\":1,\"long_description\":\"this is a test\",\"supported_operations\":[{\"name\":\"OperationDumboDrop\",\"direction\":\"to_actor\",\"doctext\":\"this is a test\"}]}".to_string());
263 }
264}