1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use crate::Result;
use libloading::Library;
use libloading::Symbol;
use std::ffi::OsStr;
use wascc_codec::{
capabilities::{CapabilityDescriptor, CapabilityProvider, OP_GET_CAPABILITY_DESCRIPTOR},
deserialize, SYSTEM_ACTOR,
};
pub struct NativeCapability {
pub(crate) plugin: Box<dyn CapabilityProvider>,
pub(crate) binding_name: String,
pub(crate) descriptor: CapabilityDescriptor,
#[allow(dead_code)]
library: Option<Library>,
}
impl NativeCapability {
pub fn from_file<P: AsRef<OsStr>>(
filename: P,
binding_target_name: Option<String>,
) -> Result<Self> {
type PluginCreate = unsafe fn() -> *mut dyn CapabilityProvider;
let library = Library::new(filename.as_ref())?;
let plugin = unsafe {
let constructor: Symbol<PluginCreate> = library.get(b"__capability_provider_create")?;
let boxed_raw = constructor();
Box::from_raw(boxed_raw)
};
let descriptor = get_descriptor(&plugin)?;
let binding = binding_target_name.unwrap_or("default".to_string());
info!(
"Loaded native capability provider '{}' v{} ({}) for {}/{}",
descriptor.name, descriptor.version, descriptor.revision, descriptor.id, binding
);
Ok(NativeCapability {
plugin,
descriptor,
binding_name: binding,
library: Some(library),
})
}
pub fn from_instance(
instance: impl CapabilityProvider,
binding_target_name: Option<String>,
) -> Result<Self> {
let b: Box<dyn CapabilityProvider> = Box::new(instance);
let descriptor = get_descriptor(&b)?;
let binding = binding_target_name.unwrap_or("default".to_string());
info!(
"Loaded native capability provider '{}' v{} ({}) for {}/{}",
descriptor.name, descriptor.version, descriptor.revision, descriptor.id, binding
);
Ok(NativeCapability {
descriptor,
plugin: b,
binding_name: binding,
library: None,
})
}
pub fn id(&self) -> String {
self.descriptor.id.to_string()
}
pub fn name(&self) -> String {
self.descriptor.name.to_string()
}
pub fn descriptor(&self) -> &CapabilityDescriptor {
&self.descriptor
}
}
fn get_descriptor(plugin: &Box<dyn CapabilityProvider>) -> Result<CapabilityDescriptor> {
let res = plugin.handle_call(SYSTEM_ACTOR, OP_GET_CAPABILITY_DESCRIPTOR, &[])?;
let descriptor: CapabilityDescriptor = deserialize(&res)?;
Ok(descriptor)
}