plugin.rs

  1//! Provides the plugin infrastructure.
  2
  3use event::{Event, Dispatcher, SendElement, Priority, Propagation};
  4
  5use std::any::Any;
  6
  7use std::sync::Arc;
  8
  9use std::mem;
 10
 11use minidom::Element;
 12
 13#[derive(Clone)]
 14pub struct PluginProxyBinding {
 15    dispatcher: Arc<Dispatcher>,
 16}
 17
 18impl PluginProxyBinding {
 19    pub fn new(dispatcher: Arc<Dispatcher>) -> PluginProxyBinding {
 20        PluginProxyBinding {
 21            dispatcher: dispatcher,
 22        }
 23    }
 24}
 25
 26pub enum PluginProxy {
 27    Unbound,
 28    BoundTo(PluginProxyBinding),
 29}
 30
 31impl PluginProxy {
 32    /// Returns a new `PluginProxy`.
 33    pub fn new() -> PluginProxy {
 34        PluginProxy::Unbound
 35    }
 36
 37    /// Binds the `PluginProxy` to a `PluginProxyBinding`.
 38    pub fn bind(&mut self, inner: PluginProxyBinding) {
 39        if let PluginProxy::BoundTo(_) = *self {
 40            panic!("trying to bind an already bound plugin proxy!");
 41        }
 42        mem::replace(self, PluginProxy::BoundTo(inner));
 43    }
 44
 45    fn with_binding<R, F: FnOnce(&PluginProxyBinding) -> R>(&self, f: F) -> R {
 46        match *self {
 47            PluginProxy::Unbound => {
 48                panic!("trying to use an unbound plugin proxy!");
 49            },
 50            PluginProxy::BoundTo(ref binding) => {
 51                f(binding)
 52            },
 53        }
 54    }
 55
 56    /// Dispatches an event.
 57    pub fn dispatch<E: Event>(&self, event: E) {
 58        self.with_binding(move |binding| {
 59            // TODO: proper error handling
 60            binding.dispatcher.dispatch(event);
 61        });
 62    }
 63
 64    /// Registers an event handler.
 65    pub fn register_handler<E, F>(&self, priority: Priority, func: F)
 66        where
 67            E: Event,
 68            F: Fn(&E) -> Propagation + 'static {
 69        self.with_binding(move |binding| {
 70            // TODO: proper error handling
 71            binding.dispatcher.register(priority, func);
 72        });
 73    }
 74
 75    /// Sends a stanza.
 76    pub fn send(&self, elem: Element) {
 77        self.dispatch(SendElement(elem));
 78    }
 79}
 80
 81/// A trait whch all plugins should implement.
 82pub trait Plugin: Any + PluginAny {
 83    /// Gets a mutable reference to the inner `PluginProxy`.
 84    fn get_proxy(&mut self) -> &mut PluginProxy;
 85
 86    #[doc(hidden)]
 87    fn bind(&mut self, inner: PluginProxyBinding) {
 88        self.get_proxy().bind(inner);
 89    }
 90}
 91
 92pub trait PluginInit {
 93    fn init(dispatcher: &Dispatcher, me: Arc<Box<Plugin>>);
 94}
 95
 96pub trait PluginAny {
 97    fn as_any(&self) -> &Any;
 98}
 99
100impl<T: Any + Sized + Plugin> PluginAny for T {
101    fn as_any(&self) -> &Any { self }
102}