#![allow(unexpected_cfgs)]
pub mod config_value;
pub mod descriptor;
pub mod ffi;
pub mod mapper;
pub mod prelude;
pub mod registration;
pub mod resolver;
pub use config_value::ConfigValue;
pub use descriptor::{BootstrapPluginDescriptor, ReactionPluginDescriptor, SourcePluginDescriptor};
pub use mapper::{ConfigMapper, DtoMapper, MappingError};
pub use registration::{PluginRegistration, SDK_VERSION};
pub use resolver::{register_secret_resolver, ResolverError};
#[doc(hidden)]
pub use tokio as __tokio;
#[macro_export]
macro_rules! export_plugin {
(
plugin_id = $plugin_id:expr,
core_version = $core_ver:expr,
lib_version = $lib_ver:expr,
plugin_version = $plugin_ver:expr,
source_descriptors = [ $($source_desc:expr),* $(,)? ],
reaction_descriptors = [ $($reaction_desc:expr),* $(,)? ],
bootstrap_descriptors = [ $($bootstrap_desc:expr),* $(,)? ],
worker_threads = $workers:expr $(,)?
) => {
fn __auto_create_plugin_vtables() -> (
Vec<$crate::ffi::SourcePluginVtable>,
Vec<$crate::ffi::ReactionPluginVtable>,
Vec<$crate::ffi::BootstrapPluginVtable>,
) {
let source_descs = vec![
$( $crate::ffi::build_source_plugin_vtable(
$source_desc,
__plugin_executor,
__emit_lifecycle,
__plugin_runtime,
), )*
];
let reaction_descs = vec![
$( $crate::ffi::build_reaction_plugin_vtable(
$reaction_desc,
__plugin_executor,
__emit_lifecycle,
__plugin_runtime,
), )*
];
let bootstrap_descs = vec![
$( $crate::ffi::build_bootstrap_plugin_vtable(
$bootstrap_desc,
__plugin_executor,
__emit_lifecycle,
__plugin_runtime,
), )*
];
(source_descs, reaction_descs, bootstrap_descs)
}
$crate::export_plugin!(
@internal
plugin_id = $plugin_id,
core_version = $core_ver,
lib_version = $lib_ver,
plugin_version = $plugin_ver,
init_fn = __auto_create_plugin_vtables,
default_workers = $workers,
);
};
(
plugin_id = $plugin_id:expr,
core_version = $core_ver:expr,
lib_version = $lib_ver:expr,
plugin_version = $plugin_ver:expr,
source_descriptors = [ $($source_desc:expr),* $(,)? ],
reaction_descriptors = [ $($reaction_desc:expr),* $(,)? ],
bootstrap_descriptors = [ $($bootstrap_desc:expr),* $(,)? ] $(,)?
) => {
fn __auto_create_plugin_vtables() -> (
Vec<$crate::ffi::SourcePluginVtable>,
Vec<$crate::ffi::ReactionPluginVtable>,
Vec<$crate::ffi::BootstrapPluginVtable>,
) {
let source_descs = vec![
$( $crate::ffi::build_source_plugin_vtable(
$source_desc,
__plugin_executor,
__emit_lifecycle,
__plugin_runtime,
), )*
];
let reaction_descs = vec![
$( $crate::ffi::build_reaction_plugin_vtable(
$reaction_desc,
__plugin_executor,
__emit_lifecycle,
__plugin_runtime,
), )*
];
let bootstrap_descs = vec![
$( $crate::ffi::build_bootstrap_plugin_vtable(
$bootstrap_desc,
__plugin_executor,
__emit_lifecycle,
__plugin_runtime,
), )*
];
(source_descs, reaction_descs, bootstrap_descs)
}
$crate::export_plugin!(
@internal
plugin_id = $plugin_id,
core_version = $core_ver,
lib_version = $lib_ver,
plugin_version = $plugin_ver,
init_fn = __auto_create_plugin_vtables,
default_workers = 2usize,
);
};
(
@internal
plugin_id = $plugin_id:expr,
core_version = $core_ver:expr,
lib_version = $lib_ver:expr,
plugin_version = $plugin_ver:expr,
init_fn = $init_fn:ident,
default_workers = $default_workers:expr $(,)?
) => {
static __RT_INIT: ::std::sync::OnceLock<()> = ::std::sync::OnceLock::new();
static __RT_PTR: ::std::sync::atomic::AtomicPtr<$crate::__tokio::runtime::Runtime> =
::std::sync::atomic::AtomicPtr::new(::std::ptr::null_mut());
fn __init_plugin_runtime() {
let default_threads: usize = $default_workers;
let kind_var = format!(
"DRASI_PLUGIN_WORKERS_{}",
$plugin_id.to_uppercase().replace('-', "_")
);
let threads = ::std::env::var(&kind_var)
.ok()
.and_then(|v| v.parse().ok())
.or_else(|| {
::std::env::var("DRASI_PLUGIN_WORKERS")
.ok()
.and_then(|v| v.parse().ok())
})
.unwrap_or(default_threads);
let rt = Box::new(
$crate::__tokio::runtime::Builder::new_multi_thread()
.worker_threads(threads)
.enable_all()
.thread_name(concat!($plugin_id, "-worker"))
.build()
.expect("Failed to create plugin tokio runtime"),
);
__RT_PTR.store(Box::into_raw(rt), ::std::sync::atomic::Ordering::Release);
}
pub fn __plugin_runtime() -> &'static $crate::__tokio::runtime::Runtime {
__RT_INIT.get_or_init(|| __init_plugin_runtime());
unsafe { &*__RT_PTR.load(::std::sync::atomic::Ordering::Acquire) }
}
#[no_mangle]
pub extern "C" fn drasi_plugin_shutdown() {
__RT_PTR.swap(
::std::ptr::null_mut(),
::std::sync::atomic::Ordering::AcqRel,
);
}
struct __SendPtr(*mut ::std::ffi::c_void);
unsafe impl Send for __SendPtr {}
pub extern "C" fn __plugin_executor(
future_ptr: *mut ::std::ffi::c_void,
) -> *mut ::std::ffi::c_void {
let boxed: Box<
::std::pin::Pin<
Box<dyn ::std::future::Future<Output = *mut ::std::ffi::c_void> + Send>,
>,
> = unsafe { Box::from_raw(future_ptr as *mut _) };
let handle = __plugin_runtime().handle().clone();
let (tx, rx) = ::std::sync::mpsc::sync_channel::<__SendPtr>(0);
handle.spawn(async move {
let raw = (*boxed).await;
let _ = tx.send(__SendPtr(raw));
});
rx.recv().expect("Plugin executor task dropped").0
}
#[allow(dead_code)]
pub fn plugin_block_on<F>(f: F) -> F::Output
where
F: ::std::future::Future + Send + 'static,
F::Output: Send + 'static,
{
let handle = __plugin_runtime().handle().clone();
::std::thread::spawn(move || handle.block_on(f))
.join()
.expect("plugin_block_on: spawned thread panicked")
}
static __LOG_CB: ::std::sync::atomic::AtomicPtr<()> =
::std::sync::atomic::AtomicPtr::new(::std::ptr::null_mut());
static __LOG_CTX: ::std::sync::atomic::AtomicPtr<::std::ffi::c_void> =
::std::sync::atomic::AtomicPtr::new(::std::ptr::null_mut());
static __LIFECYCLE_CB: ::std::sync::atomic::AtomicPtr<()> =
::std::sync::atomic::AtomicPtr::new(::std::ptr::null_mut());
static __LIFECYCLE_CTX: ::std::sync::atomic::AtomicPtr<::std::ffi::c_void> =
::std::sync::atomic::AtomicPtr::new(::std::ptr::null_mut());
extern "C" fn __set_log_callback_impl(
ctx: *mut ::std::ffi::c_void,
callback: $crate::ffi::LogCallbackFn,
) {
__LOG_CTX.store(ctx, ::std::sync::atomic::Ordering::Release);
__LOG_CB.store(callback as *mut (), ::std::sync::atomic::Ordering::Release);
$crate::ffi::tracing_bridge::init_tracing_subscriber(
&__LOG_CB,
&__LOG_CTX,
$plugin_id,
);
}
extern "C" fn __set_lifecycle_callback_impl(
ctx: *mut ::std::ffi::c_void,
callback: $crate::ffi::LifecycleCallbackFn,
) {
__LIFECYCLE_CTX.store(ctx, ::std::sync::atomic::Ordering::Release);
__LIFECYCLE_CB.store(
callback as *mut (),
::std::sync::atomic::Ordering::Release,
);
}
pub fn __emit_lifecycle(
component_id: &str,
event_type: $crate::ffi::FfiLifecycleEventType,
message: &str,
) {
let ptr = __LIFECYCLE_CB.load(::std::sync::atomic::Ordering::Acquire);
if !ptr.is_null() {
let cb: $crate::ffi::LifecycleCallbackFn =
unsafe { ::std::mem::transmute(ptr) };
let ctx = __LIFECYCLE_CTX.load(::std::sync::atomic::Ordering::Acquire);
let event = $crate::ffi::FfiLifecycleEvent {
component_id: $crate::ffi::FfiStr::from_str(component_id),
component_type: $crate::ffi::FfiStr::from_str("plugin"),
event_type,
message: $crate::ffi::FfiStr::from_str(message),
timestamp_us: $crate::ffi::now_us(),
};
cb(ctx, &event);
}
}
static __PLUGIN_METADATA: $crate::ffi::PluginMetadata = $crate::ffi::PluginMetadata {
sdk_version: $crate::ffi::FfiStr {
ptr: $crate::ffi::FFI_SDK_VERSION.as_ptr() as *const ::std::os::raw::c_char,
len: $crate::ffi::FFI_SDK_VERSION.len(),
},
core_version: $crate::ffi::FfiStr {
ptr: $core_ver.as_ptr() as *const ::std::os::raw::c_char,
len: $core_ver.len(),
},
lib_version: $crate::ffi::FfiStr {
ptr: $lib_ver.as_ptr() as *const ::std::os::raw::c_char,
len: $lib_ver.len(),
},
plugin_version: $crate::ffi::FfiStr {
ptr: $plugin_ver.as_ptr() as *const ::std::os::raw::c_char,
len: $plugin_ver.len(),
},
target_triple: $crate::ffi::FfiStr {
ptr: $crate::ffi::TARGET_TRIPLE.as_ptr() as *const ::std::os::raw::c_char,
len: $crate::ffi::TARGET_TRIPLE.len(),
},
git_commit: $crate::ffi::FfiStr {
ptr: $crate::ffi::GIT_COMMIT_SHA.as_ptr() as *const ::std::os::raw::c_char,
len: $crate::ffi::GIT_COMMIT_SHA.len(),
},
build_timestamp: $crate::ffi::FfiStr {
ptr: $crate::ffi::BUILD_TIMESTAMP.as_ptr() as *const ::std::os::raw::c_char,
len: $crate::ffi::BUILD_TIMESTAMP.len(),
},
};
#[no_mangle]
pub extern "C" fn drasi_plugin_metadata() -> *const $crate::ffi::PluginMetadata {
&__PLUGIN_METADATA
}
#[no_mangle]
pub extern "C" fn drasi_plugin_init() -> *mut $crate::ffi::FfiPluginRegistration {
match ::std::panic::catch_unwind(|| {
let _ = __plugin_runtime();
let (mut source_descs, mut reaction_descs, mut bootstrap_descs) = $init_fn();
let registration = Box::new($crate::ffi::FfiPluginRegistration {
source_plugins: source_descs.as_mut_ptr(),
source_plugin_count: source_descs.len(),
reaction_plugins: reaction_descs.as_mut_ptr(),
reaction_plugin_count: reaction_descs.len(),
bootstrap_plugins: bootstrap_descs.as_mut_ptr(),
bootstrap_plugin_count: bootstrap_descs.len(),
set_log_callback: __set_log_callback_impl,
set_lifecycle_callback: __set_lifecycle_callback_impl,
});
::std::mem::forget(source_descs);
::std::mem::forget(reaction_descs);
::std::mem::forget(bootstrap_descs);
Box::into_raw(registration)
}) {
Ok(ptr) => ptr,
Err(_) => ::std::ptr::null_mut(),
}
}
};
}