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
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
pub mod dsl;
mod resolver;
mod vc_config;

pub use dsl::VariantValue;
use hashbrown::HashMap;
pub use resolver::*;
use serde::de::DeserializeOwned;
use serde_json;
use std::sync::Arc;
pub use vc_config::*;

pub struct VariantConfigStore {
    resolver: Arc<JsonConfigResolver>,
    pub global_variants: Arc<HashMap<String, VariantValue>>,
    pub config: Arc<VariantConfigStoreConfig>,
}

impl VariantConfigStore {
    pub fn new(
        json: serde_json::Value,
        global_variants: HashMap<String, VariantValue>,
    ) -> anyhow::Result<Self> {
        Self::new_with_config(json, global_variants, VariantConfigStoreConfig::default())
    }

    pub fn new_with_config(
        json: serde_json::Value,
        global_variants: HashMap<String, VariantValue>,
        config: VariantConfigStoreConfig,
    ) -> anyhow::Result<Self> {
        let resolver = JsonConfigResolver::new_with_custom_path(
            json,
            config.condition_path.clone(),
            config.value_path.clone(),
        )?;

        Ok(Self {
            resolver: Arc::new(resolver),
            global_variants: Arc::new(global_variants),
            config: Arc::new(config),
        })
    }

    pub fn new_from_yaml(
        yaml: &str,
        global_variants: HashMap<String, VariantValue>,
    ) -> anyhow::Result<Self> {
        Self::new_from_yaml_with_config(yaml, global_variants, VariantConfigStoreConfig::default())
    }

    pub fn new_from_yaml_with_config(
        yaml: &str,
        global_variants: HashMap<String, VariantValue>,
        config: VariantConfigStoreConfig,
    ) -> anyhow::Result<Self> {
        let json = serde_yaml::from_str(yaml)?;
        Self::new_with_config(json, global_variants, config)
    }

    pub fn new_from_toml(
        toml: &str,
        global_variants: HashMap<String, VariantValue>,
    ) -> anyhow::Result<Self> {
        Self::new_from_toml_with_config(toml, global_variants, VariantConfigStoreConfig::default())
    }

    pub fn new_from_toml_with_config(
        toml: &str,
        global_variants: HashMap<String, VariantValue>,
        config: VariantConfigStoreConfig,
    ) -> anyhow::Result<Self> {
        let json = toml::from_str(toml)?;
        Self::new_with_config(json, global_variants, config)
    }

    pub fn resolve(&self, variants: &HashMap<String, VariantValue>) -> serde_json::Value {
        if variants.len() > 0 {
            let mut merged = HashMap::with_capacity(self.global_variants.len() + variants.len());
            for (k, v) in variants {
                merged.insert(k.to_owned(), v.clone());
            }
            for (k, v) in &*self.global_variants {
                if !merged.contains_key(k) {
                    merged.insert(k.to_owned(), v.clone());
                }
            }
            self.resolver.resolve(&merged)
        } else {
            self.resolver.resolve(&self.global_variants)
        }
    }

    pub fn resolve_typed<T: DeserializeOwned>(
        &self,
        variants: &HashMap<String, VariantValue>,
    ) -> anyhow::Result<T> {
        let json = self.resolve(variants);
        let r = serde_json::from_value(json)?;
        Ok(r)
    }

    pub fn update_json(&mut self, json: serde_json::Value) -> anyhow::Result<()> {
        let resolver = JsonConfigResolver::new_with_custom_path(
            json,
            self.config.condition_path.clone(),
            self.config.value_path.clone(),
        )?;
        self.resolver = Arc::new(resolver);
        Ok(())
    }

    pub fn update_json_with_config(
        &mut self,
        json: serde_json::Value,
        config: &VariantConfigStoreConfig,
    ) -> anyhow::Result<()> {
        let resolver = JsonConfigResolver::new_with_custom_path(
            json,
            config.condition_path.clone(),
            config.value_path.clone(),
        )?;
        self.resolver = Arc::new(resolver);
        self.config = Arc::new(config.clone());
        Ok(())
    }

    pub fn update_global_variants(&mut self, global_variants: HashMap<String, VariantValue>) {
        self.global_variants = Arc::new(global_variants);
    }
}