1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/*!
<a href="https://github.com/Nercury/metafactory-rs">
    <img style="position: absolute; top: 0; left: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_left_red_aa0000.png" alt="Fork me on GitHub">
</a>
<style>.sidebar { margin-top: 53px }</style>
*/

//!
//!
//!`MetaFactory` can be used to construct value creation chains from
//! closures or other sources that produce values.
//!
//! Let's look at really small example first:
//!
//! ```
//! use metafactory::{ metafactory, argless_as_factory, AsFactoryExt };
//!
//! fn main() {
//!     let meta_sum = metafactory(
//!         |a: int, b: int| a + b
//!     );
//!
//!     let sum_factory = meta_sum.new(vec![
//!         argless_as_factory(5i),
//!         argless_as_factory(6i),
//!     ]).ok().unwrap();
//!
//!     let getter = sum_factory.as_factory_of::<int>().unwrap();
//!
//!     assert_eq!(getter.take(), 11);
//! }
//! ```
//!
//! What is going on? Well, first we use `metafactory` generic function to
//! convert arbitrary closure to `MetaFactory` object `meta_sum`.
//!
//! It has a method `new`, which is used above to return a real
//! concrete factory `sum_factory`. As argument, it takes other factories.
//! The method `argless_as_factory()` returns factories for clonable values
//! `5i` and `6i`.
//!
//! So, metafactories can be created from different sources: clonable
//! objects or closures. In this case `5i` is a clonable object.
//!
//! Returned `sum_factory` has a `Box<Any>` type, and can be downcasted to
//! a `Factory` of appropriate type with `as_factory_of` method.
//!
//! Then you can call `take()` on this factory `getter` to invoke your closure
//! and return a new value.
//!
//! Note a lot of `unwrap` calls. All the potential argument or type
//! mismatches produce correct errors that can be dealt with.
//!
//! Now, the example above might seem a bit involved, but consider what it
//! allows us to do: provided argument counts and types match, we can
//! connect any chain of factories together, at runtime.
//!
//! Let's expand example to add a new factory that uses `sum_factory` as an
//! argument, and creates our own struct:
//!
//! ```
//! use metafactory::{ metafactory, argless_as_factory, AsFactoryExt };
//!
//! /// Our own struct.
//! struct Foo {
//!     value: int,
//! }
//!
//! fn main() {
//!     // initialization
//!
//!     let meta_sum = metafactory(
//!         |a: int, b: int| a + b
//!     );
//!
//!     let meta_foo = metafactory(
//!         |sum: int| Foo { value: sum }
//!     );
//!
//!     // plugging in
//!
//!     let foo_factory = meta_foo.new(vec![
//!         meta_sum.new(vec![
//!             argless_as_factory(5i),
//!             argless_as_factory(6i),
//!         ]).ok().unwrap()
//!     ]).ok().unwrap();
//!
//!     // using
//!
//!     let getter = foo_factory.as_factory_of::<Foo>().unwrap();
//!
//!     assert_eq!(getter.take().value, 11);
//! }
//! ```
//!
//! So, the intention of this library is to have a mechanism to separate 3
//! things: creating the values, plugging-in the factories
//! values, and using them.
//!
//! Created metafactories can also be used to inspect closure argument types.
//! It is also possible to clone the created factory: in such case, all
//! the call tree is also cloned internally. This makes it possible to
//! pass a copy of a factory to a task.
//!
//! Factories intentionally do not produce any kind of singletons or
//! references, only new values. You can also look at them as configurable
//! stream of values.
//!
//! If this library looks a bit lower-level, it is because it is intended as
//! such: more convenient wrappers like dependency injection or plugin
//! architecture can be implemented on top of this.
//!
//! Finally, a more complete example of available functionality:
//!
//! ```
//! use metafactory::{ metafactory, AsFactoryExt };
//!
//! fn main() {
//!     // build argument-factory from cloneable source.
//!     let meta_arg1 = metafactory(5i);
//!
//!     // build argument-factory from lambda.
//!     let meta_arg2 = metafactory(|| 14i32);
//!
//!     // build a factory that uses other factories create added numbers.
//!     let meta_adder = metafactory(|a1: int, a2: i32| a1 + a2 as int);
//!
//!     // it knows the cloneable source returns int
//!     assert!(meta_arg1.get_type().is::<int>());
//!     // it knows the lambda source returns i32
//!     assert!(meta_arg2.get_type().is::<i32>());
//!     // it knows the lambda with 2 args returns int
//!     assert!(meta_adder.get_type().is::<int>());
//!
//!     // create a factory for adder, pass other 2 factories as arguments
//!     let boxany = meta_adder.new(vec![
//!         meta_arg1.new(Vec::new()).ok().unwrap(),
//!         meta_arg2.new(Vec::new()).ok().unwrap(),
//!     ]).ok().unwrap();
//!
//!     // conveniently downcast factory to callable instance
//!     let factory = boxany.as_factory_of::<int>().unwrap();
//!
//!     // value should be the sum.
//!     assert_eq!(19, factory.take());
//!
//!     // factory can be cloned
//!     let factory2 = factory.clone();
//!
//!     // both clones invoke the same construction path and return the same value
//!     assert_eq!(factory.take(), factory2.take());
//! }
//! ```

#![feature(macro_rules)]
#![feature(unboxed_closures)]

extern crate typedef;

use std::any::{ Any, AnyRefExt };
use std::boxed::{ BoxAny };

use typedef::{ TypeDef };
use error::{ FactoryErrorKind };
use aggregate::Aggregate;

pub mod aggregate;
pub mod error;

mod factory;
mod from_clone;
mod from_closure;

/// Gettable value trait.
#[experimental]
pub trait Getter<T> {
    /// Produce a new value.
    fn take(&self) -> T;

    /// Create a clone for this getter.
    ///
    /// This is kind of experimental solution - can not return plain traits
    /// as function result.
    fn boxed_clone(&self) -> Box<Getter<T> + 'static>;
}

/// A factory proxy.
///
/// `Factory` proxy is used to return a concrete value from
/// unknown source. `Factory` will always produce a new owned value -
/// any other pattern can be implemented on top of that.
#[stable]
pub struct Factory<T:'static> {
    getter: Box<Getter<T> + 'static>,
}

#[stable]
impl<'a, T: 'static> Factory<T> {
    /// Create a new `Factory`.
    ///
    /// Create a new factory from any type that implements `Getter` trait.
    pub fn new(getter: Box<Getter<T> + 'static>) -> Factory<T> {
        Factory::<T> {
            getter: getter,
        }
    }

    /// Get a new owned value.
    pub fn take(&self) -> T {
        self.getter.take()
    }
}

impl<'a, T: 'static> Clone for Factory<T> {
    fn clone(&self) -> Factory<T> {
        Factory::<T> {
            getter: self.getter.boxed_clone(),
        }
    }
}

/// Downcast value to `Factory`.
pub trait AsFactoryExt {
    /// Downcast to factory and consume `Box<Any>`.
    fn as_factory_of<T>(self) -> Option<Factory<T>>;
    /// Downcast to factory by creating factory clone.
    fn as_factory_clone_of<T>(&self) -> Option<Factory<T>>;
}

impl AsFactoryExt for Box<Any> {
    fn as_factory_of<'a, T: 'static>(self) -> Option<Factory<T>> {
        match self.downcast::<Factory<T>>().ok() {
            Some(val) => Some(*val),
            None => None
        }
    }

    fn as_factory_clone_of<'a, T: 'static>(&self) -> Option<Factory<T>> {
        match self.downcast_ref::<Factory<T>>() {
            Some(val) => Some(val.clone()),
            None => None
        }
    }
}

/// Implements reflection and initiation of any abstract object constructor.
///
/// ## Information about constructor
///
/// The first goal of this trait is being able to inspect the construction
/// mechanism at the runtime.
///
/// `MetaFactory` contains information about the constructor source: the
/// return type and argument types. It also contains a method `new`
/// that can create a function to invoke this source and get the values.
///
/// ## Factory initiation
///
/// The second goal is to avoid donwcasting construction arguments on every
/// `Factory` invocation.
///
/// There are separate traits for `MetaFactory` and "real" `Factory`.
/// `MetaFactory` is used to build a real `Factory` by passing all the
/// required constructor arguments as factories under `Vec<Box<Any>>`.
///
/// Internaly, all parent `Factory`s will be downcasted to correct types
/// and stored inside returned `Factory`'s scope, so that all of them
/// can be invoked with a simple `take()` call.
///
/// ## Simple value as constructor
///
/// This library allows to use many sources as "constructors", the simplest
/// of which is a cloneable value. In this example we will use such value to
/// create a new constructor metadata, check if argument and return types are
/// correct, and then create an actual getter for the value:
///
/// ```
/// use metafactory::{ metafactory, AsFactoryExt };
///
/// let metafactory = metafactory(5i);
/// assert!(metafactory.get_type().is::<int>());
/// assert!(metafactory.get_arg_types().len() == 0); // clonable int has no arguments
///
/// let factory = metafactory
///     .new(
///         Vec::new() // No arguments in this case.
///     )
///     .ok().unwrap()
///     .as_factory_of::<int>()
///     .unwrap();
///
/// assert_eq!(factory.take(), 5i);
/// ```
#[unstable]
pub trait MetaFactory {
    #[unstable]
    fn get_type(&self) -> TypeDef;
    #[unstable]
    fn get_arg_types(&self) -> Vec<TypeDef>;
    #[unstable]
    fn new(&self, arg_getters: Vec<Box<Any>>) -> Result<Box<Any>, FactoryErrorKind>;
    #[unstable]
    fn new_aggregate(&self) -> Aggregate<'static>;
}

/// Trait for values convertable to `MetaFactory`.
///
/// This trait is implemented for values that can be used as
/// sources for object creation.
#[unstable]
pub trait ToMetaFactory {
    /// Creates a `MetaFactory` that has information about object
    /// constructor: produced object type, argument types, and
    /// a method to get this getter.
    #[unstable]
    fn to_metafactory<'a>(self) -> Box<MetaFactory + 'a>;
}

/// Create a new `MetaFactory` for any compatible value source.
///
/// Compatible value type must have `ToMetaFactory` implementation.
/// Supported sources are in submodules, look at "clone" for simpliest example.
pub fn metafactory<'r, T: ToMetaFactory>(any: T) -> Box<MetaFactory + 'r> {
    any.to_metafactory()
}

/// Create a new `MetaFactory` and return `Factory` in `Box<Any>` for source with no arguments.
///
/// Compatible value type must have `ToMetaFactory` implementation.
/// Supported sources are in submodules, look at "clone" for simpliest example.
pub fn argless_as_factory<T: ToMetaFactory>(any: T) -> Box<Any> {
    any.to_metafactory().new(Vec::new()).ok().unwrap()
}