1pub mod api_traits;
2pub mod error;
3pub mod headers;
4pub mod key_types;
5
6use abi_stable::type_layout::TypeLayout;
7use abi_stable::StableAbi;
8use api_traits::{ControllerFeatures, Loadable};
9use cglue::prelude::v1::{trait_group::compare_layouts, *};
10use core::mem::MaybeUninit;
11use ::std::ffi::CString;
12use error::{InputFlowError, Result};
13use headers::PluginHeader;
14use libloading::{library_filename, Library, Symbol};
15
16#[cglue_trait]
17pub trait PluginInner<'a> {
18 #[wrap_with_group(ControllerFeatures)]
19 type BorrowedType: Loadable + 'a;
20 #[wrap_with_group(ControllerFeatures)]
21 type OwnedType: Loadable + 'static;
22 #[wrap_with_group_mut(ControllerFeatures)]
23 type OwnedTypeMut: Loadable + 'a;
24
25 fn borrow_features(&'a mut self) -> Self::BorrowedType;
26
27 fn into_features(self) -> Self::OwnedType;
28
29 fn mut_features(&'a mut self) -> &'a mut Self::OwnedTypeMut;
30}
31
32pub trait Plugin: for<'a> PluginInner<'a> {}
36impl<T: for<'a> PluginInner<'a>> Plugin for T {}
37
38#[no_mangle]
54pub unsafe extern "C" fn load_plugin(
55 name: ReprCStr<'_>,
56 args: ReprCStr<'_>,
57 ok_out: &mut MaybeUninit<PluginInnerArcBox<'static>>,
58) -> i32 {
59 load_plugin_impl(name.as_ref(), args.as_ref()).into_int_out_result(ok_out)
60}
61
62unsafe fn load_plugin_impl(name: &str, args: &str) -> Result<PluginInnerArcBox<'static>> {
63 let mut current_exe = std::env::current_exe().map_err(|_| InputFlowError::Path)?;
64 current_exe.set_file_name(library_filename(name));
65 let lib = Library::new(current_exe).map_err(|e| {
66 println!("{}", e);
67 InputFlowError::Loading
68 })?;
69
70 let header: Symbol<&'static PluginHeader> = lib.get(b"IF_PLUGIN_HEAD\0").map_err(|e| {
71 println!("{}", e);
72 InputFlowError::Symbol
73 })?;
74 let header = header.into_raw();
75
76 if !compare_layouts(Some(ROOT_LAYOUT), Some(header.layout)).is_valid_strict() {
77 return Err(InputFlowError::Abi);
78 }
79
80 let arc = CArc::from(lib);
81 (header.create)(&arc.into_opaque(), CString::new(args).unwrap().into_raw())
82}
83
84#[no_mangle]
89pub static ROOT_LAYOUT: &TypeLayout = PluginInnerArcBox::LAYOUT;
90
91#[doc(hidden)]
92pub mod cglue {
93 pub use ::cglue::prelude::v1::*;
94}
95
96#[doc(hidden)]
97pub mod abi_stable {
98 pub use abi_stable::*;
99}
100
101#[doc(hidden)]
102#[allow(ambiguous_glob_reexports)]
103pub mod prelude {
104 pub mod v1 {
105 pub use crate::abi_stable;
106 pub use crate::api_traits::*;
107 pub use crate::cglue::*;
108 pub use crate::error::*;
109 pub use crate::headers::*;
110 pub use crate::iter::*;
111 pub use crate::key_types::*;
112 pub use crate::*;
113 }
114 pub use v1::*;
115}