1pub mod dsl;
2mod resolver;
3mod vc_config;
4
5pub use anyhow;
6pub use dsl::VariantValue;
7pub use hashbrown;
8use hashbrown::HashMap;
9pub use log;
10pub use resolver::*;
11use serde::de::DeserializeOwned;
12pub use serde_json;
13pub use serde_yaml;
14use std::sync::Arc;
15pub use toml;
16pub use vc_config::*;
17
18pub struct VariantConfigStore {
19 resolver: Arc<JsonConfigResolver>,
20 pub global_variants: Arc<HashMap<String, VariantValue>>,
21 pub config: Arc<VariantConfigStoreConfig>,
22}
23
24impl VariantConfigStore {
25 pub fn new(
26 json: serde_json::Value,
27 global_variants: HashMap<String, VariantValue>,
28 ) -> anyhow::Result<Self> {
29 Self::new_with_config(json, global_variants, VariantConfigStoreConfig::default())
30 }
31
32 pub fn new_with_config(
33 json: serde_json::Value,
34 global_variants: HashMap<String, VariantValue>,
35 config: VariantConfigStoreConfig,
36 ) -> anyhow::Result<Self> {
37 let resolver = JsonConfigResolver::new_with_custom_path(
38 json,
39 config.condition_path.clone(),
40 config.value_path.clone(),
41 )?;
42
43 Ok(Self {
44 resolver: Arc::new(resolver),
45 global_variants: Arc::new(global_variants),
46 config: Arc::new(config),
47 })
48 }
49
50 pub fn new_from_yaml(
51 yaml: &str,
52 global_variants: HashMap<String, VariantValue>,
53 ) -> anyhow::Result<Self> {
54 Self::new_from_yaml_with_config(yaml, global_variants, VariantConfigStoreConfig::default())
55 }
56
57 pub fn new_from_yaml_with_config(
58 yaml: &str,
59 global_variants: HashMap<String, VariantValue>,
60 config: VariantConfigStoreConfig,
61 ) -> anyhow::Result<Self> {
62 let json = serde_yaml::from_str(yaml)?;
63 Self::new_with_config(json, global_variants, config)
64 }
65
66 pub fn new_from_toml(
67 toml: &str,
68 global_variants: HashMap<String, VariantValue>,
69 ) -> anyhow::Result<Self> {
70 Self::new_from_toml_with_config(toml, global_variants, VariantConfigStoreConfig::default())
71 }
72
73 pub fn new_from_toml_with_config(
74 toml: &str,
75 global_variants: HashMap<String, VariantValue>,
76 config: VariantConfigStoreConfig,
77 ) -> anyhow::Result<Self> {
78 let json = toml::from_str(toml)?;
79 Self::new_with_config(json, global_variants, config)
80 }
81
82 pub fn resolve(&self, variants: &HashMap<String, VariantValue>) -> serde_json::Value {
83 if !variants.is_empty() {
84 let mut merged = HashMap::with_capacity(self.global_variants.len() + variants.len());
85 for (k, v) in variants {
86 merged.insert(k.to_owned(), v.clone());
87 }
88 for (k, v) in &*self.global_variants {
89 if !merged.contains_key(k) {
90 merged.insert(k.to_owned(), v.clone());
91 }
92 }
93 self.resolver.resolve(&merged)
94 } else {
95 self.resolver.resolve(&self.global_variants)
96 }
97 }
98
99 pub fn resolve_typed<T: DeserializeOwned>(
100 &self,
101 variants: &HashMap<String, VariantValue>,
102 ) -> anyhow::Result<T> {
103 let json = self.resolve(variants);
104 let r = serde_json::from_value(json)?;
105 Ok(r)
106 }
107
108 pub fn update_json(&mut self, json: serde_json::Value) -> anyhow::Result<()> {
109 let resolver = JsonConfigResolver::new_with_custom_path(
110 json,
111 self.config.condition_path.clone(),
112 self.config.value_path.clone(),
113 )?;
114 self.resolver = Arc::new(resolver);
115 Ok(())
116 }
117
118 pub fn update_json_with_config(
119 &mut self,
120 json: serde_json::Value,
121 config: &VariantConfigStoreConfig,
122 ) -> anyhow::Result<()> {
123 let resolver = JsonConfigResolver::new_with_custom_path(
124 json,
125 config.condition_path.clone(),
126 config.value_path.clone(),
127 )?;
128 self.resolver = Arc::new(resolver);
129 self.config = Arc::new(config.clone());
130 Ok(())
131 }
132
133 pub fn update_global_variants(&mut self, global_variants: HashMap<String, VariantValue>) {
134 self.global_variants = Arc::new(global_variants);
135 }
136}