Skip to main content

options/
factory.rs

1use crate::{
2    validation::{Error, Validate},
3    Configure, PostConfigure, Ref, Value,
4};
5
6/// Defines the behavior of a configuration options factory.
7#[cfg_attr(feature = "async", maybe_impl::traits(Send, Sync))]
8pub trait Factory<T: Value> {
9    /// Creates and returns new configuration options.
10    ///
11    /// # Arguments
12    ///
13    /// * `name` - The optional name of the configuration options to create
14    fn create(&self, name: &str) -> Result<T, Error>;
15}
16
17/// Represents the default factory used to create configuration options.
18#[derive(Default)]
19pub struct DefaultFactory<T: Value + Default> {
20    configurations: Vec<Ref<dyn Configure<T>>>,
21    post_configurations: Vec<Ref<dyn PostConfigure<T>>>,
22    validations: Vec<Ref<dyn Validate<T>>>,
23}
24
25impl<T: Value + Default> DefaultFactory<T> {
26    /// Initializes a new options factory.
27    ///
28    /// # Arguments
29    ///
30    /// * `configurations` - The configurations used to [configure options](Configure)
31    /// * `post_configurations` - The configurations used to [post-configure options](PostConfigure)
32    /// * `validations` - The validations used to [validate options](Validate)
33    pub fn new(
34        configurations: Vec<Ref<dyn Configure<T>>>,
35        post_configurations: Vec<Ref<dyn PostConfigure<T>>>,
36        validations: Vec<Ref<dyn Validate<T>>>,
37    ) -> Self {
38        Self {
39            configurations,
40            post_configurations,
41            validations,
42        }
43    }
44}
45
46impl<T: Value + Default> Factory<T> for DefaultFactory<T> {
47    fn create(&self, name: &str) -> Result<T, Error> {
48        let mut options = Default::default();
49
50        for configuration in &self.configurations {
51            configuration.run(name, &mut options);
52        }
53
54        for configuration in &self.post_configurations {
55            configuration.run(name, &mut options);
56        }
57
58        let mut failures = Vec::new();
59
60        for validation in &self.validations {
61            if let Err(error) = validation.run(name, &options) {
62                failures.extend_from_slice(error.failures());
63            }
64        }
65
66        if failures.is_empty() {
67            Ok(options)
68        } else {
69            Err(Error::many(failures))
70        }
71    }
72}