persistent/
lib.rs

1#![cfg_attr(test, deny(warnings))]
2#![deny(missing_docs)]
3
4//! A set of middleware for sharing data between requests in the Iron
5//! framework.
6
7extern crate iron;
8extern crate plugin;
9
10use iron::{Request, Response, BeforeMiddleware, AfterMiddleware, IronResult};
11use iron::typemap::Key;
12use std::sync::{Arc, RwLock, Mutex};
13use std::fmt;
14use std::error::Error;
15use plugin::Plugin;
16
17/// The type that can be returned by `eval` to indicate error.
18#[derive(Clone, Debug)]
19pub enum PersistentError {
20    /// The value was not found.
21    NotFound
22}
23
24impl Error for PersistentError {
25    fn description(&self) -> &str {
26        match *self {
27            PersistentError::NotFound => "Value not found in extensions."
28        }
29    }
30}
31
32impl fmt::Display for PersistentError {
33    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
34        self.description().fmt(f)
35    }
36}
37
38/// Helper trait for overloading the constructors of `Read`/`Write`/`State`.
39/// This is an implementation detail, and should not be used for any other
40/// purpose.
41///
42/// For example, this trait lets you construct a `Read<T>` from either a `T` or
43/// an `Arc<T>`.
44pub trait PersistentInto<T> {
45    /// Convert `self` into a value of type `T`.
46    fn persistent_into(self) -> T;
47}
48
49impl<T> PersistentInto<T> for T {
50    fn persistent_into(self) -> T { self }
51}
52
53impl<T> PersistentInto<Arc<T>> for T {
54    fn persistent_into(self) -> Arc<T> {
55        Arc::new(self)
56    }
57}
58
59impl<T> PersistentInto<Arc<Mutex<T>>> for T {
60    fn persistent_into(self) -> Arc<Mutex<T>> {
61        Arc::new(Mutex::new(self))
62    }
63}
64
65impl<T> PersistentInto<Arc<RwLock<T>>> for T {
66    fn persistent_into(self) -> Arc<RwLock<T>> {
67        Arc::new(RwLock::new(self))
68    }
69}
70
71/// Middleware for data that persists between requests with read and write capabilities.
72///
73/// The data is stored behind a `RwLock`, so multiple read locks
74/// can be taken out concurrently.
75///
76/// If most threads need to take out a write lock, you may want to
77/// consider `Write`, which stores the data behind a `Mutex`, which
78/// has a faster locking speed.
79///
80/// `State` can be linked as `BeforeMiddleware` to add data to the `Request`
81/// extensions and it can be linked as an `AfterMiddleware` to add data to
82/// the `Response` extensions.
83///
84/// `State` also implements `Plugin`, so the data stored within can be
85/// accessed through `request.get::<State<P>>()` as an `Arc<RwLock<P::Value>>`.
86pub struct State<P: Key> {
87    data: Arc<RwLock<P::Value>>
88}
89
90/// Middleware for data that persists between Requests with read-only capabilities.
91///
92/// The data is stored behind an Arc, so multiple threads can have
93/// concurrent, non-blocking access.
94///
95/// `Read` can be linked as `BeforeMiddleware` to add data to the `Request`
96/// extensions and it can be linked as an `AfterMiddleware` to add data to
97/// the `Response` extensions.
98///
99/// `Read` also implements `Plugin`, so the data stored within can be
100/// accessed through `request.get::<Read<P>>()` as an `Arc<P::Value>`.
101pub struct Read<P: Key> {
102    data: Arc<P::Value>
103}
104
105/// Middleware for data that persists between Requests for data which mostly
106/// needs to be written instead of read.
107///
108/// The data is stored behind a `Mutex`, so only one request at a time can
109/// access the data. This is more performant than `State` in the case where
110/// most uses of the data require a write lock.
111///
112/// `Write` can be linked as `BeforeMiddleware` to add data to the `Request`
113/// extensions and it can be linked as an `AfterMiddleware` to add data to
114/// the `Response` extensions.
115///
116/// `Write` also implements `Plugin`, so the data stored within can be
117/// accessed through `request.get::<Write<P>>()` as an `Arc<Mutex<P::Value>>`.
118pub struct Write<P: Key> {
119    data: Arc<Mutex<P::Value>>
120}
121
122impl<P: Key> Clone for Read<P> where P::Value: Send + Sync {
123    fn clone(&self) -> Read<P> {
124        Read { data: self.data.clone() }
125    }
126}
127
128impl<P: Key> Clone for State<P> where P::Value: Send + Sync {
129    fn clone(&self) -> State<P> {
130        State { data: self.data.clone() }
131    }
132}
133
134impl<P: Key> Clone for Write<P> where P::Value: Send {
135    fn clone(&self) -> Write<P> {
136        Write { data: self.data.clone() }
137    }
138}
139
140impl<P: Key> Key for State<P> where P::Value: 'static {
141    type Value = Arc<RwLock<P::Value>>;
142}
143
144impl<P: Key> Key for Read<P> where P::Value: 'static {
145    type Value = Arc<P::Value>;
146}
147
148impl<P: Key> Key for Write<P> where P::Value: 'static {
149    type Value = Arc<Mutex<P::Value>>;
150}
151
152impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for State<P> where P::Value: Send + Sync {
153    type Error = PersistentError;
154    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<RwLock<P::Value>>, PersistentError> {
155        req.extensions.get::<State<P>>().cloned().ok_or(PersistentError::NotFound)
156    }
157}
158
159impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Read<P> where P::Value: Send + Sync {
160    type Error = PersistentError;
161    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<P::Value>, PersistentError> {
162        req.extensions.get::<Read<P>>().cloned().ok_or(PersistentError::NotFound)
163    }
164}
165
166impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Write<P> where P::Value: Send {
167    type Error = PersistentError;
168    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<Mutex<P::Value>>, PersistentError> {
169        req.extensions.get::<Write<P>>().cloned().ok_or(PersistentError::NotFound)
170    }
171}
172
173impl<P: Key> BeforeMiddleware for State<P> where P::Value: Send + Sync {
174    fn before(&self, req: &mut Request) -> IronResult<()> {
175        req.extensions.insert::<State<P>>(self.data.clone());
176        Ok(())
177    }
178}
179
180impl<P: Key> BeforeMiddleware for Read<P> where P::Value: Send + Sync {
181    fn before(&self, req: &mut Request) -> IronResult<()> {
182        req.extensions.insert::<Read<P>>(self.data.clone());
183        Ok(())
184    }
185}
186
187impl<P: Key> BeforeMiddleware for Write<P> where P::Value: Send {
188    fn before(&self, req: &mut Request) -> IronResult<()> {
189        req.extensions.insert::<Write<P>>(self.data.clone());
190        Ok(())
191    }
192}
193
194impl<P: Key> AfterMiddleware for State<P> where P::Value: Send + Sync {
195    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
196        res.extensions.insert::<State<P>>(self.data.clone());
197        Ok(res)
198    }
199}
200
201impl<P: Key> AfterMiddleware for Read<P> where P::Value: Send + Sync {
202    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
203        res.extensions.insert::<Read<P>>(self.data.clone());
204        Ok(res)
205    }
206}
207
208impl<P: Key> AfterMiddleware for Write<P> where P::Value: Send {
209    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
210        res.extensions.insert::<Write<P>>(self.data.clone());
211        Ok(res)
212    }
213}
214
215impl<P: Key> State<P> where P::Value: Send + Sync {
216    /// Construct a new pair of `State` that can be passed directly to `Chain::link`.
217    ///
218    /// The data is initialized with the passed-in value.
219    pub fn both<T>(start: T) -> (State<P>, State<P>) where T: PersistentInto<Arc<RwLock<P::Value>>> {
220        let x = State { data: start.persistent_into() };
221        (x.clone(), x)
222    }
223
224    /// Construct a new `State` that can be passed directly to
225    /// `Chain::link_before` or `Chain::link_after`.
226    ///
227    /// The data is initialized with the passed-in value.
228    pub fn one<T>(start: T) -> State<P> where T: PersistentInto<Arc<RwLock<P::Value>>> {
229        State { data: start.persistent_into() }
230    }
231}
232
233impl<P: Key> Read<P> where P::Value: Send + Sync {
234    /// Construct a new pair of `Read` that can be passed directly to `Chain::link`.
235    ///
236    /// The data is initialized with the passed-in value.
237    pub fn both<T>(start: T) -> (Read<P>, Read<P>) where T: PersistentInto<Arc<P::Value>> {
238        let x = Read { data: start.persistent_into() };
239        (x.clone(), x)
240    }
241
242    /// Construct a new `Read` that can be passed directly to
243    /// `Chain::link_before` or `Chain::link_after`.
244    ///
245    /// The data is initialized with the passed-in value.
246    pub fn one<T>(start: T) -> Read<P> where T: PersistentInto<Arc<P::Value>> {
247        Read { data: start.persistent_into() }
248    }
249}
250
251impl<P: Key> Write<P> where P::Value: Send {
252    /// Construct a new pair of `Write` that can be passed directly to `Chain::link`.
253    ///
254    /// The data is initialized with the passed-in value.
255    pub fn both<T>(start: T) -> (Write<P>, Write<P>) where T: PersistentInto<Arc<Mutex<P::Value>>> {
256        let x = Write { data: start.persistent_into() };
257        (x.clone(), x)
258    }
259
260    /// Construct a new `Write` that can be passed directly to
261    /// `Chain::link_before` or `Chain::link_after`.
262    ///
263    /// The data is initialized with the passed-in value.
264    pub fn one<T>(start: T) -> Write<P> where T: PersistentInto<Arc<Mutex<P::Value>>> {
265        Write { data: start.persistent_into() }
266    }
267}