1use std::marker::PhantomData;
48use std::path::PathBuf;
49
50pub use config;
51use config::builder::{AsyncState, BuilderState, DefaultState};
52use config::{Config, ConfigBuilder, ConfigError};
53use either::Either;
54
55pub use crate::load::Load;
56pub use crate::location::Location;
57pub use crate::location::file::FileLocation;
58
59pub mod load;
60pub mod location;
61
62pub type Result<T> = std::result::Result<T, ConfigError>;
63
64#[derive(Debug, Clone)]
65pub struct ConfigLoader<S: BuilderState = DefaultState> {
66 config_paths: Vec<PathBuf>,
67 _state: PhantomData<S>,
68}
69
70impl<S: BuilderState> ConfigLoader<S> {
71 pub fn new() -> Self {
72 Self {
73 config_paths: Vec::new(),
74 _state: PhantomData,
75 }
76 }
77
78 pub fn add(mut self, location: impl Location) -> Self {
79 match location.try_into_path() {
80 Either::Left(path) => self.config_paths.push(path),
81 Either::Right(_) => (),
82 }
83 self
84 }
85
86 pub fn exclude_not_exists(mut self) -> Self {
87 self.config_paths.retain(|path| path.is_file());
88 self
89 }
90}
91
92impl Default for ConfigLoader<DefaultState> {
93 fn default() -> Self {
94 Self::new_default()
95 }
96}
97
98impl ConfigLoader<DefaultState> {
99 pub fn new_default() -> Self {
100 Self::new()
101 }
102
103 pub fn builder(self) -> ConfigBuilder<DefaultState> {
104 let mut config_builder = Config::builder();
105 for path in self.config_paths {
106 config_builder = config_builder.add_source(config::File::from(path))
107 }
108 config_builder
109 }
110
111 pub fn load<T: Load<DefaultState>>(self) -> Result<T> {
112 let config_builder = self.builder();
113 T::load(config_builder)
114 }
115}
116
117impl ConfigLoader<AsyncState> {
118 pub fn new_async() -> Self {
119 Self::new()
120 }
121
122 pub fn builder(self) -> ConfigBuilder<AsyncState> {
123 let mut config_builder = ConfigBuilder::<AsyncState>::default();
124 for path in self.config_paths {
125 config_builder = config_builder.add_source(config::File::from(path))
126 }
127 config_builder
128 }
129
130 pub fn load<T: Load<AsyncState>>(self) -> Result<T> {
131 let config_builder = self.builder();
132 T::load(config_builder)
133 }
134}