use crate::descriptor::{
BootstrapPluginDescriptor, ReactionPluginDescriptor, SourcePluginDescriptor,
};
pub const SDK_VERSION: &str = env!("CARGO_PKG_VERSION");
pub const TOKIO_VERSION: &str = "1.44.1";
pub const BUILD_HASH: &str = env!("DRASI_BUILD_HASH");
pub struct PluginRegistration {
pub sdk_version: &'static str,
pub rust_version: &'static str,
pub tokio_version: &'static str,
pub build_hash: &'static str,
pub sources: Vec<Box<dyn SourcePluginDescriptor>>,
pub reactions: Vec<Box<dyn ReactionPluginDescriptor>>,
pub bootstrappers: Vec<Box<dyn BootstrapPluginDescriptor>>,
}
impl PluginRegistration {
pub fn new() -> Self {
Self {
sdk_version: SDK_VERSION,
rust_version: env!("DRASI_RUSTC_VERSION"),
tokio_version: TOKIO_VERSION,
build_hash: BUILD_HASH,
sources: Vec::new(),
reactions: Vec::new(),
bootstrappers: Vec::new(),
}
}
#[must_use]
pub fn with_source(mut self, descriptor: Box<dyn SourcePluginDescriptor>) -> Self {
self.sources.push(descriptor);
self
}
#[must_use]
pub fn with_reaction(mut self, descriptor: Box<dyn ReactionPluginDescriptor>) -> Self {
self.reactions.push(descriptor);
self
}
#[must_use]
pub fn with_bootstrapper(mut self, descriptor: Box<dyn BootstrapPluginDescriptor>) -> Self {
self.bootstrappers.push(descriptor);
self
}
pub fn is_empty(&self) -> bool {
self.sources.is_empty() && self.reactions.is_empty() && self.bootstrappers.is_empty()
}
pub fn descriptor_count(&self) -> usize {
self.sources.len() + self.reactions.len() + self.bootstrappers.len()
}
}
impl Default for PluginRegistration {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for PluginRegistration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PluginRegistration")
.field("sdk_version", &self.sdk_version)
.field("rust_version", &self.rust_version)
.field("tokio_version", &self.tokio_version)
.field("build_hash", &self.build_hash)
.field(
"sources",
&self.sources.iter().map(|s| s.kind()).collect::<Vec<_>>(),
)
.field(
"reactions",
&self.reactions.iter().map(|r| r.kind()).collect::<Vec<_>>(),
)
.field(
"bootstrappers",
&self
.bootstrappers
.iter()
.map(|b| b.kind())
.collect::<Vec<_>>(),
)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::descriptor::SourcePluginDescriptor;
use async_trait::async_trait;
struct DummySource;
#[async_trait]
impl SourcePluginDescriptor for DummySource {
fn kind(&self) -> &str {
"dummy"
}
fn config_version(&self) -> &str {
"1.0.0"
}
fn config_schema_json(&self) -> String {
"{}".to_string()
}
fn config_schema_name(&self) -> &str {
"DummySourceConfig"
}
async fn create_source(
&self,
_id: &str,
_config_json: &serde_json::Value,
_auto_start: bool,
) -> anyhow::Result<Box<dyn drasi_lib::sources::Source>> {
anyhow::bail!("not implemented")
}
}
#[test]
fn test_registration_new_is_empty() {
let reg = PluginRegistration::new();
assert!(reg.is_empty());
assert_eq!(reg.descriptor_count(), 0);
}
#[test]
fn test_registration_with_source() {
let reg = PluginRegistration::new().with_source(Box::new(DummySource));
assert!(!reg.is_empty());
assert_eq!(reg.descriptor_count(), 1);
assert_eq!(reg.sources[0].kind(), "dummy");
}
#[test]
fn test_registration_sdk_version() {
let reg = PluginRegistration::new();
assert_eq!(reg.sdk_version, SDK_VERSION);
}
#[test]
fn test_registration_debug() {
let reg = PluginRegistration::new().with_source(Box::new(DummySource));
let debug = format!("{reg:?}");
assert!(debug.contains("dummy"));
assert!(debug.contains("sdk_version"));
}
}