use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, ffi::{c_char, c_void, CString}};
use thiserror::Error;
use crate::{message::{ChannelCapabilities, ChannelMessage}, PluginHandle};
#[derive(Debug, Copy, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
#[repr(C)]
pub enum ChannelState {
Starting,
Running,
Draining,
#[default]
Stopped }
#[repr(C)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "lowercase")]
pub enum LogLevel {
Trace = 0,
Debug = 1,
Info = 2,
Warn = 3,
Error = 4,
Critical = 5,
}
#[repr(C)]
pub struct PluginLogger {
pub ctx: *mut c_void,
pub log_fn: extern "C" fn(ctx: *mut c_void,
level: LogLevel,
context: *const c_char,
message: *const c_char),
}
impl PluginLogger {
pub fn log(&self, level: LogLevel, context: &str, message: &str) {
let c_ctx = CString::new(context).expect("context contained a NUL");
let c_message = CString::new(message).expect("message contained a NUL");
(self.log_fn)(
self.ctx,
level,
c_ctx.as_ptr(),
c_message.as_ptr(),
);
}
}
unsafe impl Send for PluginLogger {}
unsafe impl Sync for PluginLogger {}
pub type PluginSetLogger = unsafe extern "C" fn(PluginHandle, PluginLogger);
pub trait ChannelPlugin: Send + Sync {
fn name(&self) -> String;
fn set_logger(&mut self, logger: PluginLogger);
fn send(&mut self, msg: ChannelMessage) -> anyhow::Result<(),PluginError>;
fn poll(&self) -> anyhow::Result<ChannelMessage,PluginError>;
fn capabilities(&self) -> ChannelCapabilities;
fn set_config(&mut self, config: HashMap<String, String>);
fn list_config(&self) -> Vec<String>;
fn set_secrets(&mut self, secrets: HashMap<String, String>);
fn list_secrets(&self) -> Vec<String>;
fn state(&self) -> ChannelState;
fn start(&mut self) -> Result<(),PluginError>;
fn drain(&mut self) -> Result<(),PluginError>;
fn wait_until_drained(&mut self, timeout_ms: u64) -> Result<(),PluginError>;
fn stop(&mut self) -> Result<(),PluginError>;
}
#[derive(Error, Debug, Serialize, Deserialize, JsonSchema)]
#[repr(C)]
pub enum PluginError {
#[error("JSON error: {0}")]
Json(String),
#[error("invalid state for this operation")]
InvalidState,
#[error("operation timed out after {0} ms")]
Timeout(u64),
#[error("plugin error: {0}")]
Other(String),
}
impl From<serde_json::Error> for PluginError {
fn from(err: serde_json::Error) -> PluginError {
PluginError::Json(err.to_string())
}
}
impl From<anyhow::Error> for PluginError {
fn from(err: anyhow::Error) -> PluginError {
PluginError::Other(err.to_string())
}
}