1use config::{self};
2use std::collections::HashMap;
3
4use crate::schema::metadata::OptionsMetadata;
5
6pub(crate) type SourceValue = config::File<config::FileSourceString, config::FileFormat>;
11
12pub(crate) type Aliases = HashMap<unicase::UniCase<String>, String>;
13pub(crate) type Features = HashMap<String, OptionsMetadata>;
14pub(crate) type Sources = HashMap<String, SourceValue>;
15
16pub struct GetOptionsPreferences {
17 pub skip_feature_name_conversion: bool,
18}
19
20pub struct CacheOptions {}
21
22pub struct OptionsProvider {
25 aliases: Aliases,
26 features: Features,
27 sources: Sources,
28}
29
30impl OptionsProvider {
31 pub(crate) fn new(aliases: &Aliases, features: &Features, sources: &Sources) -> Self {
32 OptionsProvider {
33 aliases: aliases.clone(),
34 features: features.clone(),
35 sources: sources.clone(),
36 }
37 }
38
39 pub fn get_all_options(
40 &self,
41 feature_names: &Vec<String>,
42 cache_options: &Option<CacheOptions>,
43 preferences: &Option<GetOptionsPreferences>,
44 ) -> Result<serde_json::Value, String> {
45 let config = self._get_entire_config(feature_names, cache_options, preferences)?;
46
47 match config {
48 Ok(cfg) => match cfg.try_deserialize() {
49 Ok(value) => Ok(value),
50 Err(e) => Err(e.to_string()),
51 },
52 Err(e) => Err(e.to_string()),
53 }
54 }
55
56 pub fn get_canonical_feature_name(&self, feature_name: &str) -> Result<&String, String> {
62 let feature_name = unicase::UniCase::new(feature_name.to_owned());
64 match self.aliases.get(&feature_name) {
65 Some(canonical_name) => Ok(canonical_name),
66 None => Err(format!(
67 "The given feature {:?} was not found.",
68 feature_name
69 )),
70 }
71 }
72
73 pub fn get_feature_metadata(&self, canonical_feature_name: &str) -> Option<&OptionsMetadata> {
74 self.features.get(canonical_feature_name)
75 }
76
77 pub fn get_features(&self) -> Vec<String> {
78 self.sources.keys().map(|s| s.to_owned()).collect()
79 }
80
81 pub fn get_features_with_metadata(&self) -> &Features {
82 &self.features
83 }
84
85 pub fn get_options(
86 &self,
87 key: &str,
88 feature_names: &Vec<String>,
89 ) -> Result<serde_json::Value, String> {
90 self.get_options_with_preferences(key, feature_names, &None, &None)
91 }
92
93 pub fn get_options_with_preferences(
94 &self,
95 key: &str,
96 feature_names: &Vec<String>,
97 cache_options: &Option<CacheOptions>,
98 preferences: &Option<GetOptionsPreferences>,
99 ) -> Result<serde_json::Value, String> {
100 let config = self._get_entire_config(feature_names, cache_options, preferences)?;
101
102 match config {
103 Ok(cfg) => match cfg.get(key) {
104 Ok(value) => Ok(value),
105 Err(e) => Err(e.to_string()),
106 },
107 Err(e) => Err(e.to_string()),
108 }
109 }
110
111 fn _get_entire_config(
112 &self,
113 feature_names: &Vec<String>,
114 cache_options: &Option<CacheOptions>,
115 preferences: &Option<GetOptionsPreferences>,
116 ) -> Result<Result<config::Config, config::ConfigError>, String> {
117 if let Some(_cache_options) = cache_options {
118 return Err("Caching is not supported yet.".to_owned());
119 };
120 let mut config_builder = config::Config::builder();
121 let mut skip_feature_name_conversion = false;
122 if let Some(_preferences) = preferences {
123 skip_feature_name_conversion = _preferences.skip_feature_name_conversion;
124 }
125 for feature_name in feature_names {
126 let mut canonical_feature_name = feature_name;
129 if !skip_feature_name_conversion {
130 canonical_feature_name = self.get_canonical_feature_name(feature_name)?;
131 }
132
133 let source = match self.sources.get(canonical_feature_name) {
134 Some(src) => src,
135 None => {
139 return Err(format!(
140 "Feature name {:?} was not found.",
141 canonical_feature_name
142 ))
143 }
144 };
145 config_builder = config_builder.add_source(source.clone());
146 }
147 Ok(config_builder.build())
148 }
149}