Struct metafactory::aggregate::Aggregate [-]  [+] [src]

pub struct Aggregate<'a> {
    // some fields omitted
}

Proxy for initializing aggregate factory without caring about the type used.

Its intended use is as a container of factories that produce a value of the same type. Then it can itself be used to create a new factory that aggregates values from all its childs and returns all of them in a Vec<T> type for single take.

The most convenient way to initialize a new aggregate is to use new_aggregate method on a metafactory. It will make a correctly typed aggregate based on the metafactory type.

use metafactory::{ metafactory, AsFactoryExt };

fn main() {
    let true_metafactory = metafactory(|| true);
    let false_metafactory = metafactory(|| false);

    // Use any of metafactories to create an aggregate for bool.
    let mut aggregate = false_metafactory.new_aggregate();

    // We can then add both factories to the aggregate.
    // and make a factory from aggregate.
    let true_and_false = aggregate
        .new_factory(vec![
            true_metafactory.new(Vec::new()).ok().unwrap(),
            false_metafactory.new(Vec::new()).ok().unwrap(),
        ])
        .as_factory_of::<Vec<bool>>().unwrap();

    assert_eq!(vec![true, false], true_and_false.take());
}

The example bellow show how to initialize and use aggregate without a metafactory.

use std::any::Any;
use metafactory::{ metafactory, argless_as_factory, AsFactoryExt };
use metafactory::aggregate::Aggregate;

fn main() {
    // Let's say we know that we will have bunch of `bool` factories.
    // In that case we create a new aggregate for them:
    let mut aggregate = Aggregate::new::<bool>();

    // Once we actually have our factories, we can inject them into aggregate
    // without dealing with types. Of course, we should make sure that types
    // actually match before doing that in the code that is using this
    // implementation.
    // Then we can call `new_factory` to convert all dynamic stuff to
    // statically constructed call hierarchy:
    let anyed_bool_array_factory = aggregate
        .new_factory(vec![
            argless_as_factory(|| true),
            argless_as_factory(true),
            argless_as_factory(|| 4i == 8),
        ]);

    // Of course, that returns it anyed (`Box<Any>`), but we can easily get un-anyed version
    // by downcasting to `Factory<Vec<bool>>` or using a convenience extension
    // method for that:
    let bool_array_factory = anyed_bool_array_factory
        .as_factory_of::<Vec<bool>>().unwrap();

    // Calling it should produce expected boolean vector:
    assert_eq!(bool_array_factory.take(), vec![true, true, false]);

    // Of course, the aggregate itself should be usable as argument
    // for other factories:
    let metafactory_all_true = metafactory(|values: Vec<bool>| {
        values.iter().fold(true, |a, &i| a & i)
    });

    // We can pass it when constructing a factory for this lambda metafactory:
    let factory_all_true = metafactory_all_true.new(vec![
        box bool_array_factory.clone() as Box<Any>
    ])
        .ok().unwrap() // check for errors here
        .as_factory_of::<bool>().unwrap() // same story with downcasting
    ;

    assert_eq!(factory_all_true.take(), false); // not all values are true
}

Methods

impl<'a> Aggregate<'a>

fn new<T: 'static>() -> Aggregate<'a>

Create new aggregate instance for specified type.

fn get_arg_type(&self) -> TypeDef

Return aggregated type.

fn get_container_type(&self) -> TypeDef

Return container type.

fn new_factory(&self, items: Vec<Box<Any>>) -> Box<Any>

Produces factory usable as argument for other factories.

If inner factories make int values, this method will make factory that makes Vec<int> values.