Skip to main content

miwa_core/core/
config.rs

1use std::ops::Deref;
2
3use config::{Config, ConfigError, Environment, FileFormat, Format, Source};
4use serde::de::DeserializeOwned;
5use serde_json::Value;
6
7use crate::{FromMiwaContext, MiwaResult};
8
9use super::MiwaId;
10
11#[derive(Debug, Clone)]
12pub struct MiwaConfig {
13    cfg: Config,
14}
15
16impl MiwaConfig {
17    pub fn default_cfg() -> MiwaResult<Self> {
18        let prefix = "MIWA".to_string();
19        Ok(MiwaConfig {
20            cfg: Config::builder()
21                .add_source(Environment::with_prefix(&prefix).separator("_"))
22                .build()?,
23        })
24    }
25
26    pub fn with_config(cfg: Config) -> MiwaResult<Self> {
27        Ok(MiwaConfig { cfg })
28    }
29
30    pub fn get<T: DeserializeOwned>(&self, key: &str) -> MiwaResult<T> {
31        self.cfg.get(key).map(Ok)?
32    }
33}
34
35pub struct ExtensionConfig<T>(pub T);
36
37impl<T> Deref for ExtensionConfig<T> {
38    type Target = T;
39
40    fn deref(&self) -> &Self::Target {
41        &self.0
42    }
43}
44
45pub trait Configurable {
46    fn prefix() -> &'static str;
47}
48
49impl<'a, T: Configurable + DeserializeOwned> FromMiwaContext<'a> for ExtensionConfig<T> {
50    fn from_context(context: &'a crate::MiwaContext) -> crate::MiwaResult<Self> {
51        let cfg = context.config().get::<T>(T::prefix())?;
52        Ok(ExtensionConfig(cfg))
53    }
54}
55
56impl<T: 'static> MiwaId for ExtensionConfig<T> {
57    fn component_id() -> std::any::TypeId {
58        std::any::TypeId::of::<ExtensionConfig<T>>()
59    }
60}
61
62#[derive(Debug, Clone)]
63pub struct JsonSource(pub Value);
64
65impl Source for JsonSource {
66    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
67        Box::new((*self).clone())
68    }
69
70    fn collect(&self) -> Result<config::Map<String, config::Value>, ConfigError> {
71        let json_str = serde_json::to_string(&self.0).unwrap();
72
73        FileFormat::Json
74            .parse(None, &json_str)
75            .map_err(ConfigError::Foreign)
76    }
77}