plugin.rs

 1//! Provides the plugin infrastructure.
 2
 3use event::{Event, EventHandler, Dispatcher, SendElement, Priority};
 4
 5use std::any::Any;
 6
 7use std::sync::{Arc, Mutex};
 8
 9use std::mem;
10
11use minidom::Element;
12
13#[derive(Clone)]
14pub struct PluginProxyBinding {
15    dispatcher: Arc<Mutex<Dispatcher>>,
16}
17
18impl PluginProxyBinding {
19    pub fn new(dispatcher: Arc<Mutex<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.lock().unwrap().dispatch(event);
61        });
62    }
63
64    /// Registers an event handler.
65    pub fn register_handler<E, H>(&self, priority: Priority, handler: H) where E: Event, H: EventHandler<E> {
66        self.with_binding(move |binding| {
67            // TODO: proper error handling
68            binding.dispatcher.lock().unwrap().register(priority, handler);
69        });
70    }
71
72    /// Sends a stanza.
73    pub fn send(&self, elem: Element) {
74        self.dispatch(SendElement(elem));
75    }
76}
77
78/// A trait whch all plugins should implement.
79pub trait Plugin: Any + PluginAny {
80    /// Gets a mutable reference to the inner `PluginProxy`.
81    fn get_proxy(&mut self) -> &mut PluginProxy;
82
83    #[doc(hidden)]
84    fn bind(&mut self, inner: PluginProxyBinding) {
85        self.get_proxy().bind(inner);
86    }
87}
88
89pub trait PluginInit {
90    fn init(dispatcher: &mut Dispatcher, me: Arc<Box<Plugin>>);
91}
92
93pub trait PluginAny {
94    fn as_any(&self) -> &Any;
95}
96
97impl<T: Any + Sized + Plugin> PluginAny for T {
98    fn as_any(&self) -> &Any { self }
99}