//! Provides the plugin infrastructure. use event::{Event, Dispatcher, SendElement, Priority, Propagation}; use std::any::Any; use std::sync::{Arc, Mutex}; use std::mem; use minidom::Element; #[derive(Clone)] pub struct PluginProxyBinding { dispatcher: Arc>, } impl PluginProxyBinding { pub fn new(dispatcher: Arc>) -> PluginProxyBinding { PluginProxyBinding { dispatcher: dispatcher, } } } pub enum PluginProxy { Unbound, BoundTo(PluginProxyBinding), } impl PluginProxy { /// Returns a new `PluginProxy`. pub fn new() -> PluginProxy { PluginProxy::Unbound } /// Binds the `PluginProxy` to a `PluginProxyBinding`. pub fn bind(&mut self, inner: PluginProxyBinding) { if let PluginProxy::BoundTo(_) = *self { panic!("trying to bind an already bound plugin proxy!"); } mem::replace(self, PluginProxy::BoundTo(inner)); } fn with_binding R>(&self, f: F) -> R { match *self { PluginProxy::Unbound => { panic!("trying to use an unbound plugin proxy!"); }, PluginProxy::BoundTo(ref binding) => { f(binding) }, } } /// Dispatches an event. pub fn dispatch(&self, event: E) { self.with_binding(move |binding| { // TODO: proper error handling binding.dispatcher.lock().unwrap().dispatch(event); }); } /// Registers an event handler. pub fn register_handler(&self, priority: Priority, func: F) where E: Event, F: Fn(&E) -> Propagation + 'static { self.with_binding(move |binding| { // TODO: proper error handling binding.dispatcher.lock().unwrap().register(priority, func); }); } /// Sends a stanza. pub fn send(&self, elem: Element) { self.dispatch(SendElement(elem)); } } /// A trait whch all plugins should implement. pub trait Plugin: Any + PluginAny { /// Gets a mutable reference to the inner `PluginProxy`. fn get_proxy(&mut self) -> &mut PluginProxy; #[doc(hidden)] fn bind(&mut self, inner: PluginProxyBinding) { self.get_proxy().bind(inner); } } pub trait PluginInit { fn init(dispatcher: &mut Dispatcher, me: Arc>); } pub trait PluginAny { fn as_any(&self) -> &Any; } impl PluginAny for T { fn as_any(&self) -> &Any { self } }