pub mod operation_walker; use std::{ any::type_name, collections::HashMap, fmt::Debug, mem::transmute, ptr::null_mut, sync::Arc, }; use semver::Version; use tracing::{debug, debug_span, field::DebugValue, span, trace, trace_span, warn, Level}; use crate::{ callback::{ OperationHandlerCallback, SettingChangeCallback, SettingGetterCallback, ValueChangeCallback, ValueGetterCallback, }, handle::{PluginHandle, PluginInitializationState}, AnyObject, AnyOperation, FFIBox, NewAnySetting, NewAnyValue, ObjectVtable, OperationVTable, SettingVtable, ValueVTable, }; use self::operation_walker::OperationHandlerRules; #[derive(Default)] pub struct TypeMetadata { pub objects: HashMap<&'static str, ObjectVtable>, pub operations: HashMap, OperationVTable>, pub settings: HashMap, SettingVtable>, pub values: HashMap, ValueVTable>, } impl TypeMetadata { pub fn register_object(&mut self, object_kind: &'static str, vtable: ObjectVtable) { trace!("Registering type metadata for {}", object_kind); self.objects.insert(object_kind, vtable); } pub fn register_operation( &mut self, object_kind: &'static str, operation_name: &'static str, vtable: OperationVTable, ) { trace!( "Registering operation metadata for {}::{}", object_kind, operation_name ); self.operations.insert( ObjectOperationPair { object_kind, operation_name, }, vtable, ); } pub fn register_setting( &mut self, object_kind: &'static str, setting_name: &'static str, vtable: SettingVtable, ) { trace!("Registering setting {}::{}", object_kind, setting_name); self.settings.insert( ObjectSettingPair { object_kind, setting_name, }, vtable, ); } pub fn register_value( &mut self, object_kind: &'static str, value_name: &'static str, vtable: ValueVTable, ) { trace!("Registering value {}::{}", object_kind, value_name); self.values.insert( ObjectValuePair { object_kind, value_name, }, vtable, ); } } #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub struct ObjectOperationPair<'s> { pub object_kind: &'s str, pub operation_name: &'s str, } impl<'s> ObjectOperationPair<'s> { pub fn new(object_kind: &'s str, operation_name: &'s str) -> Self { Self { object_kind, operation_name, } } } #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] pub struct ObjectSettingPair<'s> { pub object_kind: &'s str, pub setting_name: &'s str, } impl<'s> ObjectSettingPair<'s> { pub fn new(object_kind: &'s str, setting_name: &'s str) -> Self { Self { object_kind, setting_name, } } } #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] pub struct ObjectValuePair<'s> { pub object_kind: &'s str, pub value_name: &'s str, } impl<'s> ObjectValuePair<'s> { pub fn new(object_kind: &'s str, value_name: &'s str) -> Self { Self { object_kind, value_name, } } } #[derive(Clone, Copy)] #[repr(C)] pub struct PluginState { pub inner: *mut (), } impl PluginState { pub unsafe fn transmute_owned(&mut self) -> Box { Box::from_raw(self.inner as *mut T) } pub unsafe fn transmute_ref(&self) -> &T { let ptr: *const T = transmute(self.inner); ptr.as_ref().unwrap() } } impl PluginState { pub fn null() -> Self { Self { inner: null_mut() } } } #[derive(Default)] pub struct Runtime { plugins: Vec<(PluginMeta, PluginHandle)>, handlers: RuntimeHandlers, } impl Runtime { pub fn insert_plugin(&mut self, mut plugin: PluginHandle) { let _guard = debug_span!("inserting plugin", meta = debug(&plugin.meta)).entered(); for (pair, callback) in &plugin.initialization.operation_handlers { let _guard = trace_span!("processing operation handler callbacks", pair = debug(pair)).entered(); if self .handlers .operation_handlers .insert(*pair, (RuntimeDomain::from_plugin(&plugin), *callback)) .is_some() { warn!("Warning! Insertion of handler for overwrote a previous handler.") } trace!("Insertion of operation handler successful") } for (pair, callback) in &plugin.initialization.value_getters { let _guard = trace_span!("processing value getter callbacks", pair = debug(pair)).entered(); if self .handlers .value_getters .insert(*pair, (RuntimeDomain::from_plugin(&plugin), *callback)) .is_some() { warn!("Warning! Insertion of handler for overwrote a previous handler.") } trace!("Insertion of operation handler successful") } for (pair, callback) in &plugin.initialization.setting_getters { let _guard = trace_span!("processing setting getter callbacks", pair = debug(pair)).entered(); if self .handlers .setting_getters .insert(*pair, (RuntimeDomain::from_plugin(&plugin), *callback)) .is_some() { warn!("Warning! Insertion of setting handler for overwrote a previous handler.") } trace!("Insertion of setting handler successful") } } pub fn handle( &self, object_kind: &str, operation_name: &str, object: &str, operation_payload: &[u8], ) -> Result<(), HandlerError> { let rules = self.handlers.handle_operation(object_kind, operation_name); rules.handle(object, operation_payload) } } #[derive(Default)] pub struct RuntimeHandlers { operation_handlers: HashMap, (RuntimeDomain, OperationHandlerCallback)>, value_getters: HashMap, (RuntimeDomain, ValueGetterCallback)>, setting_getters: HashMap, (RuntimeDomain, SettingGetterCallback)>, value_change: HashMap, (RuntimeDomain, ValueChangeCallback)>, setting_change: HashMap, (RuntimeDomain, SettingChangeCallback)>, } impl RuntimeHandlers { pub fn operation_handler( &mut self, pair: ObjectOperationPair<'static>, handler: OperationHandlerCallback, domain: RuntimeDomain, ) { trace!( "Inserting operation handler for {}::{}", pair.object_kind, pair.operation_name ); // There can only be one handler per operation (at least for now?), send a warning if // a newly registered handler overwrites the previous handler. if self .operation_handlers .insert(pair, (domain, handler)) .is_some() { debug!("Warning! A newly inserted operation handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.operation_name); } } pub fn value_getter( &mut self, pair: ObjectValuePair<'static>, handler: ValueGetterCallback, domain: RuntimeDomain, ) { trace!( "Inserting value getter for {}::{}", pair.object_kind, pair.value_name ); if self.value_getters.insert(pair, (domain, handler)).is_some() { debug!( "Warning! A newly inserted value getter for {}::{} overwrites a previous handler.", pair.object_kind, pair.value_name ); } } pub fn setting_getter( &mut self, pair: ObjectSettingPair<'static>, handler: SettingGetterCallback, domain: RuntimeDomain, ) { trace!( "Inserting setting getter for {}::{}", pair.object_kind, pair.setting_name ); if self .setting_getters .insert(pair, (domain, handler)) .is_some() { debug!("Warning! A newly inserted setting getter for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name); } } pub fn value_change( &mut self, pair: ObjectValuePair<'static>, handler: ValueChangeCallback, domain: RuntimeDomain, ) { trace!( "Inserting value change handler for {}::{}", pair.object_kind, pair.value_name ); if self.value_change.insert(pair, (domain, handler)).is_some() { debug!("Warning! A newly inserted value change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.value_name); panic!("Not intended"); } } pub fn setting_change( &mut self, pair: ObjectSettingPair<'static>, handler: SettingChangeCallback, domain: RuntimeDomain, ) { trace!( "Inserting setting change handler for {}::{}", pair.object_kind, pair.setting_name ); if self .setting_change .insert(pair, (domain, handler)) .is_some() { debug!("Warning! A newly inserted setting change handler for {}::{} overwrites a previous handler.", pair.object_kind, pair.setting_name); panic!("Not intended"); } } } impl RuntimeHandlers { pub fn handle_operation<'o>( &'o self, object_kind: &'o str, operation_name: &'o str, ) -> OperationHandlerRules<'o> { OperationHandlerRules::new(object_kind, operation_name, self) } } pub struct RuntimeDomain { plugin: PluginHandle, } impl RuntimeDomain { pub fn from_plugin(plugin: &PluginHandle) -> Self { Self { plugin: plugin.clone(), } } pub fn object_vtable(&self, object_kind: &str) -> Option { self.plugin .initialization .type_metadata .objects .get(object_kind) .copied() } pub fn operation_vtable( &self, object_kind: &str, operation_name: &str, ) -> Option { self.plugin .initialization .type_metadata .operations .get(&ObjectOperationPair::new(object_kind, operation_name)) .copied() } pub fn setting_vtable(&self, object_kind: &str, setting_name: &str) -> Option { self.plugin .initialization .type_metadata .settings .get(&ObjectSettingPair::new(object_kind, setting_name)) .copied() } pub fn value_vtable(&self, object_kind: &str, value_name: &str) -> Option { self.plugin .initialization .type_metadata .values .get(&ObjectValuePair::new(object_kind, value_name)) .copied() } } #[derive(Clone, Debug)] pub struct PluginMeta { pub name: String, pub version: Version, } #[repr(C)] pub struct FFIPluginMeta { pub name: *const u8, pub name_len: usize, pub version: *const u8, pub version_len: usize, } pub struct RuntimePlugin { handle: PluginHandle, type_metadata: Arc, } impl RuntimePlugin { pub fn plugin_meta(&self) -> PluginMeta { let meta = unsafe { self.handle.raw.plugin_meta() }; let name = unsafe { std::slice::from_raw_parts(meta.name, meta.name_len) }; let version = unsafe { std::slice::from_raw_parts(meta.version, meta.version_len) }; let name = std::str::from_utf8(name).unwrap(); let version = std::str::from_utf8(version).unwrap(); PluginMeta { name: String::from(name), version: Version::parse(version).unwrap(), } } } pub enum HandlerError { Failure(()), Internal(()), Unhandled, }