zng_ext_config/
yaml.rs
1use super::*;
2
3impl ConfigMap for indexmap::IndexMap<ConfigKey, serde_yaml::Value> {
4 fn empty() -> Self {
5 Self::new()
6 }
7
8 fn read(mut file: WatchFile) -> io::Result<Self> {
9 file.yaml().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
10 }
11
12 fn write(self, file: &mut WriteFile) -> io::Result<()> {
13 file.write_yaml(&self)
14 }
15
16 fn get_raw(&self, key: &ConfigKey) -> Result<Option<RawConfigValue>, Arc<dyn std::error::Error + Send + Sync>> {
17 match self.get(key) {
18 Some(e) => Ok(Some(RawConfigValue::try_from(e.clone())?)),
19 None => Ok(None),
20 }
21 }
22
23 fn set_raw(map: &mut VarModify<Self>, key: ConfigKey, value: RawConfigValue) -> Result<(), Arc<dyn std::error::Error + Send + Sync>> {
24 let value = value.try_into()?;
25 if map.get(&key) != Some(&value) {
26 map.to_mut().insert(key, value);
27 }
28 Ok(())
29 }
30
31 fn contains_key(&self, key: &ConfigKey) -> bool {
32 self.contains_key(key)
33 }
34
35 fn get<O: ConfigValue>(&self, key: &ConfigKey) -> Result<Option<O>, Arc<dyn std::error::Error + Send + Sync>> {
36 if let Some(value) = self.get(key) {
37 match serde_yaml::from_value(value.clone()) {
38 Ok(v) => Ok(Some(v)),
39 Err(e) => Err(Arc::new(e)),
40 }
41 } else {
42 Ok(None)
43 }
44 }
45
46 fn set<O: ConfigValue>(map: &mut VarModify<Self>, key: ConfigKey, value: O) -> Result<(), Arc<dyn std::error::Error + Send + Sync>> {
47 match serde_yaml::to_value(&value) {
48 Ok(value) => {
49 if map.get(&key) != Some(&value) {
50 map.to_mut().insert(key, value);
51 }
52 Ok(())
53 }
54 Err(e) => Err(Arc::new(e)),
55 }
56 }
57
58 fn remove(map: &mut VarModify<Self>, key: &ConfigKey) {
59 if map.contains_key(key) {
60 map.to_mut().shift_remove(key);
61 }
62 }
63}
64
65pub type YamlConfig = SyncConfig<indexmap::IndexMap<ConfigKey, serde_yaml::Value>>;
67
68impl TryFrom<serde_yaml::Value> for RawConfigValue {
69 type Error = YamlValueRawError;
70
71 fn try_from(value: serde_yaml::Value) -> Result<Self, Self::Error> {
72 let ok = match value {
73 serde_yaml::Value::Null => serde_json::Value::Null,
74 serde_yaml::Value::Bool(b) => serde_json::Value::Bool(b),
75 serde_yaml::Value::Number(n) => {
76 serde_json::Value::Number(if let Some(n) = n.as_i64() {
78 n.into()
79 } else if let Some(n) = n.as_u64() {
80 n.into()
81 } else if let Some(n) = n.as_f64() {
82 match serde_json::Number::from_f64(n) {
83 Some(n) => n,
84 None => return Err(YamlValueRawError::InvalidFloat(n)),
85 }
86 } else {
87 unreachable!()
88 })
89 }
90 serde_yaml::Value::String(s) => serde_json::Value::String(s),
91 serde_yaml::Value::Sequence(s) => serde_json::Value::Array({
92 let mut r = Vec::with_capacity(s.len());
93 for v in s {
94 r.push(RawConfigValue::try_from(v)?.0);
95 }
96 r
97 }),
98 serde_yaml::Value::Mapping(m) => serde_json::Value::Object({
99 let mut o = serde_json::Map::with_capacity(m.len());
100 for (key, value) in m {
101 o.insert(yaml_map_key(key)?, RawConfigValue::try_from(value)?.0);
102 }
103 o
104 }),
105 serde_yaml::Value::Tagged(v) => RawConfigValue::try_from(v.value)?.0,
106 };
107
108 Ok(Self(ok))
109 }
110}
111impl TryFrom<RawConfigValue> for serde_yaml::Value {
112 type Error = YamlValueRawError;
113
114 fn try_from(value: RawConfigValue) -> Result<Self, Self::Error> {
115 let ok = match value.0 {
116 serde_json::Value::Null => serde_yaml::Value::Null,
117 serde_json::Value::Bool(b) => serde_yaml::Value::Bool(b),
118 serde_json::Value::Number(n) => {
119 serde_yaml::Value::Number(if let Some(f) = n.as_i64() {
121 serde_yaml::Number::from(f)
122 } else if let Some(n) = n.as_u64() {
123 serde_yaml::Number::from(n)
124 } else if let Some(n) = n.as_f64() {
125 serde_yaml::Number::from(n)
126 } else {
127 unreachable!()
128 })
129 }
130 serde_json::Value::String(s) => serde_yaml::Value::String(s),
131 serde_json::Value::Array(a) => serde_yaml::Value::Sequence({
132 let mut r = Vec::with_capacity(a.len());
133 for v in a {
134 r.push(RawConfigValue(v).try_into()?);
135 }
136 r
137 }),
138 serde_json::Value::Object(o) => serde_yaml::Value::Mapping({
139 let mut r = serde_yaml::Mapping::with_capacity(o.len());
140 for (k, v) in o {
141 r.insert(serde_yaml::Value::String(k), RawConfigValue(v).try_into()?);
142 }
143 r
144 }),
145 };
146 Ok(ok)
147 }
148}
149
150fn yaml_map_key(key: serde_yaml::Value) -> Result<String, YamlValueRawError> {
151 let ok = match key {
152 serde_yaml::Value::Null => String::new(),
153 serde_yaml::Value::Bool(b) => b.to_string(),
154 serde_yaml::Value::Number(n) => n.to_string(),
155 serde_yaml::Value::String(s) => s,
156 serde_yaml::Value::Sequence(_) | serde_yaml::Value::Mapping(_) | serde_yaml::Value::Tagged(_) => {
157 return Err(YamlValueRawError::InvalidMapKey);
158 }
159 };
160 Ok(ok)
161}
162
163#[derive(Debug, Clone, Copy)]
165pub enum YamlValueRawError {
166 InvalidFloat(f64),
168 InvalidMapKey,
170}
171impl fmt::Display for YamlValueRawError {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 match self {
174 Self::InvalidFloat(fl) => write!(f, "json does not support float `{fl}`"),
175 Self::InvalidMapKey => write!(f, "json does not support non-display keys"),
176 }
177 }
178}
179impl std::error::Error for YamlValueRawError {}
180impl From<YamlValueRawError> for Arc<dyn std::error::Error + Send + Sync> {
181 fn from(value: YamlValueRawError) -> Self {
182 Arc::new(value)
183 }
184}