factory/
lib.rs

1//! This crate provides `Factory` trait and its implementations.
2//!
3//! The trait makes it possible to create any number of instances of a specific type.
4//!
5//! # Examples
6//!
7//! Creates default instances of `u8` type:
8//!
9//! ```
10//! use factory::{DefaultFactory, Factory};
11//!
12//! let f = DefaultFactory::<u8>::new();
13//! assert_eq!(f.create(), 0);
14//! assert_eq!(f.create(), 0);
15//! ```
16#![warn(missing_docs)]
17
18#[cfg(feature = "swappable")]
19extern crate atomic_immut;
20
21#[cfg(feature = "swappable")]
22pub use swappable::SwappableFactory;
23
24use std::marker::PhantomData;
25
26#[cfg(feature = "swappable")]
27mod swappable;
28
29/// This trait allows for creating any number of instances of the `Item` type.
30pub trait Factory {
31    /// The type of instances created by this factory.
32    type Item;
33
34    /// Creates an instance.
35    fn create(&self) -> Self::Item;
36}
37impl<T: ?Sized + Factory> Factory for &T {
38    type Item = T::Item;
39
40    fn create(&self) -> Self::Item {
41        (**self).create()
42    }
43}
44impl<T: ?Sized + Factory> Factory for Box<T> {
45    type Item = T::Item;
46
47    fn create(&self) -> Self::Item {
48        (**self).create()
49    }
50}
51
52/// This trait allows for creating any number of instances of the `Item` type with the given parameter.
53pub trait ParameterizedFactory {
54    /// The type of instances created by this factory.
55    type Item;
56
57    /// The type of parameter.
58    type Parameter;
59
60    /// Creates an instance.
61    fn create(&self, param: Self::Parameter) -> Self::Item;
62}
63impl<T: ?Sized + ParameterizedFactory> ParameterizedFactory for &T {
64    type Item = T::Item;
65    type Parameter = T::Parameter;
66
67    fn create(&self, param: Self::Parameter) -> Self::Item {
68        (**self).create(param)
69    }
70}
71impl<T: ?Sized + ParameterizedFactory> ParameterizedFactory for Box<T> {
72    type Item = T::Item;
73    type Parameter = T::Parameter;
74
75    fn create(&self, param: Self::Parameter) -> Self::Item {
76        (**self).create(param)
77    }
78}
79
80/// A `Factory` that creates instances using `T::default()` function.
81///
82/// # Examples
83///
84/// ```
85/// use factory::{DefaultFactory, Factory};
86///
87/// let f = DefaultFactory::<u8>::new();
88/// assert_eq!(f.create(), 0);
89/// ```
90#[derive(Debug, Default)]
91pub struct DefaultFactory<T>(PhantomData<T>);
92impl<T: Default> DefaultFactory<T> {
93    /// Makes a new `DefaultFactory`.
94    pub fn new() -> Self {
95        DefaultFactory(PhantomData)
96    }
97}
98impl<T: Default> Factory for DefaultFactory<T> {
99    type Item = T;
100
101    fn create(&self) -> Self::Item {
102        T::default()
103    }
104}
105impl<T> Clone for DefaultFactory<T> {
106    fn clone(&self) -> Self {
107        DefaultFactory(PhantomData)
108    }
109}
110unsafe impl<T> Send for DefaultFactory<T> {}
111unsafe impl<T> Sync for DefaultFactory<T> {}
112
113/// A `Factory` that creates instances using `T::clone()` method.
114///
115/// # Examples
116///
117/// ```
118/// use factory::{CloneFactory, Factory};
119///
120/// let f = CloneFactory::new(10);
121/// assert_eq!(f.create(), 10);
122/// ```
123#[derive(Debug, Default, Clone)]
124pub struct CloneFactory<T>(T);
125impl<T: Clone> CloneFactory<T> {
126    /// Makes a new `CloneFactory`.
127    ///
128    /// The instances the factory creates are copied from `original`.
129    pub fn new(original: T) -> Self {
130        CloneFactory(original)
131    }
132
133    /// Returns a reference to the original instance.
134    pub fn get_ref(&self) -> &T {
135        &self.0
136    }
137
138    /// Returns a mutable reference to the original instance.
139    pub fn get_mut(&mut self) -> &mut T {
140        &mut self.0
141    }
142}
143impl<T: Clone> Factory for CloneFactory<T> {
144    type Item = T;
145
146    fn create(&self) -> Self::Item {
147        self.0.clone()
148    }
149}
150
151#[cfg(test)]
152mod test {
153    use super::*;
154
155    #[test]
156    fn default_factory_works() {
157        let f = DefaultFactory::<u8>::new();
158        assert_eq!(f.create(), 0);
159        assert_eq!(f.clone().create(), 0);
160    }
161
162    #[test]
163    fn clone_factory_works() {
164        let mut f = CloneFactory::new(32);
165        assert_eq!(f.get_ref(), &32);
166        assert_eq!(f.create(), 32);
167
168        *f.get_mut() = 50;
169        assert_eq!(f.create(), 50);
170    }
171}