1use serde::Serialize;
2use serde::de::DeserializeOwned;
3use std::fs::File;
4use std::path::Path;
5use thiserror::Error;
6
7#[derive(Debug)]
8pub struct HandlerConfig<C>
9where
10 C: Default + DeserializeOwned,
11{
12 id: String,
13 enabled: bool,
14 timeout: Option<u64>,
15 retry_count: Option<u32>,
16 retry_delay: Option<u64>,
17 config: Config<C>,
18}
19
20impl<C> Default for HandlerConfig<C>
21where
22 C: Default + DeserializeOwned,
23{
24 fn default() -> Self {
25 Self {
26 id: "unknown".to_string(),
27 enabled: true,
28 timeout: Some(30000),
29 retry_count: None,
30 retry_delay: None,
31 config: Config::default(),
32 }
33 }
34}
35
36impl<C> HandlerConfig<C>
37where
38 C: Default + DeserializeOwned,
39{
40 pub fn new(id: String, config: Config<C>) -> Self {
41 Self {
42 id,
43 config,
44 ..Default::default()
45 }
46 }
47
48 pub fn id(&self) -> &String {
49 &self.id
50 }
51
52 pub fn enabled(&self) -> bool {
53 self.enabled
54 }
55
56 pub fn timeout(&self) -> Option<u64> {
57 self.timeout
58 }
59
60 pub fn retry_count(&self) -> Option<u32> {
61 self.retry_count
62 }
63
64 pub fn retry_delay(&self) -> Option<u64> {
65 self.retry_delay
66 }
67
68 pub fn config(&self) -> &Config<C> {
69 &self.config
70 }
71
72 pub fn set_config(&mut self, config: Config<C>) {
73 self.config = config;
74 }
75
76 pub fn set_enabled(&mut self, enabled: bool) {
77 self.enabled = enabled;
78 }
79
80 pub fn set_timeout(&mut self, timeout: Option<u64>) {
81 self.timeout = timeout;
82 }
83
84 pub fn set_retry_count(&mut self, retry_count: Option<u32>) {
85 self.retry_count = retry_count;
86 }
87
88 pub fn set_retry_delay(&mut self, retry_delay: Option<u64>) {
89 self.retry_delay = retry_delay;
90 }
91
92 pub fn set_id(&mut self, id: String) {
93 self.id = id;
94 }
95
96 pub fn builder() -> HandlerConfigBuilder<C> {
97 HandlerConfigBuilder::new()
98 }
99}
100
101pub struct HandlerConfigBuilder<C>
102where
103 C: Default + DeserializeOwned,
104{
105 config: HandlerConfig<C>,
106}
107
108impl<C> HandlerConfigBuilder<C>
109where
110 C: Default + DeserializeOwned,
111{
112 pub fn new() -> Self {
113 Self {
114 config: HandlerConfig::<C>::default(),
115 }
116 }
117
118 pub fn id(&mut self, id: impl Into<String>) -> &mut Self {
119 self.config.id = id.into();
120 self
121 }
122
123 pub fn enabled(&mut self, enabled: bool) -> &mut Self {
124 self.config.enabled = enabled;
125 self
126 }
127
128 pub fn timeout(&mut self, timeout: Option<u64>) -> &mut Self {
129 self.config.timeout = timeout;
130 self
131 }
132
133 pub fn retry_count(&mut self, retry_count: Option<u32>) -> &mut Self {
134 self.config.retry_count = retry_count;
135 self
136 }
137
138 pub fn retry_delay(&mut self, retry_delay: Option<u64>) -> &mut Self {
139 self.config.retry_delay = retry_delay;
140 self
141 }
142
143 pub fn handler_config(&mut self, config: Config<C>) -> &mut Self {
144 self.config.config = config;
145 self
146 }
147
148 pub fn build(self) -> HandlerConfig<C> {
149 self.config
150 }
151}
152
153#[derive(Debug, Default)]
154pub struct Config<C> {
155 config: C,
156}
157
158impl<C> Config<C>
159where
160 C: Default + DeserializeOwned,
161{
162 pub fn new(provider: impl ConfigProvider<C>) -> Result<Self, ()> {
163 provider
164 .load()
165 .map(|config| Config { config })
166 .map_err(|_| ())
167 }
168
169 pub fn get(&self) -> &C {
170 &self.config
171 }
172
173 pub fn get_mut(&mut self) -> &mut C {
174 &mut self.config
175 }
176}
177
178pub trait ConfigProvider<C>
179where
180 C: Default + DeserializeOwned,
181{
182 fn load(&self) -> Result<C, ConfigProviderError>;
183}
184
185pub struct DefaultConfigProvider;
186
187impl<C> ConfigProvider<C> for DefaultConfigProvider
188where
189 C: Default + DeserializeOwned,
190{
191 fn load(&self) -> Result<C, ConfigProviderError> {
192 Ok(C::default())
193 }
194}
195
196pub struct FileConfigProvider {
197 pub base_path: String,
198 pub config_name: String,
199}
200
201impl<C> ConfigProvider<C> for FileConfigProvider
202where
203 C: Default + DeserializeOwned,
204{
205 fn load(&self) -> Result<C, ConfigProviderError> {
206 let config_path = Path::new(&self.base_path).join(&self.config_name);
207 let file = File::open(config_path).map_err(|e| {
208 let msg = format!("Could not open config file: {}", e);
209 ConfigProviderError::load_error(msg)
210 })?;
211 serde_json::from_reader(file).map_err(|e| {
212 let msg = format!("Could not load config file from reader: {}", e);
213 ConfigProviderError::load_error(msg)
214 })
215 }
216}
217
218pub struct ProgrammaticConfigProvider<C> {
219 pub config: C,
220}
221
222impl<C> ConfigProvider<C> for ProgrammaticConfigProvider<C>
223where
224 C: Default + DeserializeOwned + Clone + Serialize,
225{
226 fn load(&self) -> Result<C, ConfigProviderError> {
227 Ok(self.config.clone())
228 }
229}
230
231pub enum ProviderType {
232 File,
233 Default,
234}
235
236#[derive(Error, Debug)]
237pub enum ConfigProviderError {
238 #[error("Could not load config file. {message}")]
239 Load { message: String },
240}
241
242impl ConfigProviderError {
243 #[inline]
244 pub(crate) fn load_error(msg: impl Into<String>) -> Self {
245 Self::Load {
246 message: msg.into(),
247 }
248 }
249}