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
use std::{error::Error, fmt::Debug};

use crate::ConfigurationBuilder;

/// A source of configuration data.
pub trait Source: Debug {
    /// Whether this source is allowed to contain secret data.
    ///
    /// Implementations should be conservative and return `false` by default, allowing users to
    /// opt-in to storing secrets in this source.
    fn allows_secrets(&self) -> bool {
        false
    }

    /// Attempts to provide a partial configuration object from this source.
    fn provide<T: ConfigurationBuilder>(&self) -> Result<T, Box<dyn Error + Sync + Send>>;
}

pub(crate) trait DynSource<T>: Debug {
    fn allows_secrets(&self) -> bool;
    fn provide(&self) -> Result<T, Box<dyn Error + Sync + Send>>;
}

impl<S, T> DynSource<T> for S
where
    S: Source,
    T: ConfigurationBuilder,
{
    fn allows_secrets(&self) -> bool {
        <S as Source>::allows_secrets(self)
    }

    fn provide(&self) -> Result<T, Box<dyn Error + Sync + Send>> {
        <S as Source>::provide(self)
    }
}

#[derive(Debug)]
pub(crate) struct DefaultSource;

impl<T> DynSource<T> for DefaultSource
where
    T: ConfigurationBuilder,
{
    fn allows_secrets(&self) -> bool {
        true
    }

    fn provide(&self) -> Result<T, Box<dyn Error + Sync + Send>> {
        Ok(T::default())
    }
}

pub(crate) mod file_source;

#[cfg(feature = "toml")]
pub(crate) mod toml_source;

#[cfg(feature = "json")]
pub(crate) mod json_source;

#[cfg(feature = "env")]
pub(crate) mod env_source;