1use crate::util::context::value;
4use crate::util::context::{ConfigError, ConfigKey, GlobalContext};
5use crate::util::context::{ConfigValue as CV, Definition, Value};
6use serde::{de, de::IntoDeserializer};
7use std::collections::HashSet;
8use std::vec;
9
10#[derive(Clone)]
13pub(super) struct Deserializer<'gctx> {
14 pub(super) gctx: &'gctx GlobalContext,
15 pub(super) key: ConfigKey,
17 pub(super) env_prefix_ok: bool,
24}
25
26macro_rules! deserialize_method {
27 ($method:ident, $visit:ident, $getter:ident) => {
28 fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
29 where
30 V: de::Visitor<'de>,
31 {
32 let v = self
33 .gctx
34 .$getter(&self.key)?
35 .ok_or_else(|| ConfigError::missing(&self.key))?;
36 let Value { val, definition } = v;
37 let res: Result<V::Value, ConfigError> = visitor.$visit(val);
38 res.map_err(|e| e.with_key_context(&self.key, Some(definition)))
39 }
40 };
41}
42
43impl<'de, 'gctx> de::Deserializer<'de> for Deserializer<'gctx> {
44 type Error = ConfigError;
45
46 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
47 where
48 V: de::Visitor<'de>,
49 {
50 let cv = self.gctx.get_cv_with_env(&self.key)?;
51 if let Some(cv) = cv {
52 let res: (Result<V::Value, ConfigError>, Definition) = match cv {
53 CV::Integer(i, def) => (visitor.visit_i64(i), def),
54 CV::String(s, def) => (visitor.visit_string(s), def),
55 CV::List(_, def) => (visitor.visit_seq(ConfigSeqAccess::new(self.clone())?), def),
56 CV::Table(_, def) => (
57 visitor.visit_map(ConfigMapAccess::new_map(self.clone())?),
58 def,
59 ),
60 CV::Boolean(b, def) => (visitor.visit_bool(b), def),
61 };
62 let (res, def) = res;
63 return res.map_err(|e| e.with_key_context(&self.key, Some(def)));
64 }
65
66 if self.gctx.has_key(&self.key, self.env_prefix_ok)? {
68 return visitor.visit_some(self);
69 }
70
71 Err(ConfigError::missing(&self.key))
72 }
73
74 deserialize_method!(deserialize_bool, visit_bool, get_bool);
75 deserialize_method!(deserialize_i8, visit_i64, get_integer);
76 deserialize_method!(deserialize_i16, visit_i64, get_integer);
77 deserialize_method!(deserialize_i32, visit_i64, get_integer);
78 deserialize_method!(deserialize_i64, visit_i64, get_integer);
79 deserialize_method!(deserialize_u8, visit_i64, get_integer);
80 deserialize_method!(deserialize_u16, visit_i64, get_integer);
81 deserialize_method!(deserialize_u32, visit_i64, get_integer);
82 deserialize_method!(deserialize_u64, visit_i64, get_integer);
83 deserialize_method!(deserialize_string, visit_string, get_string_priv);
84
85 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
86 where
87 V: de::Visitor<'de>,
88 {
89 if self.gctx.has_key(&self.key, self.env_prefix_ok)? {
90 visitor.visit_some(self)
91 } else {
92 visitor.visit_none()
94 }
95 }
96
97 fn deserialize_struct<V>(
98 self,
99 name: &'static str,
100 fields: &'static [&'static str],
101 visitor: V,
102 ) -> Result<V::Value, Self::Error>
103 where
104 V: de::Visitor<'de>,
105 {
106 if name == value::NAME && fields == value::FIELDS {
111 return visitor.visit_map(ValueDeserializer::new(self)?);
112 }
113 visitor.visit_map(ConfigMapAccess::new_struct(self, fields)?)
114 }
115
116 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
117 where
118 V: de::Visitor<'de>,
119 {
120 visitor.visit_map(ConfigMapAccess::new_map(self)?)
121 }
122
123 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
124 where
125 V: de::Visitor<'de>,
126 {
127 visitor.visit_seq(ConfigSeqAccess::new(self)?)
128 }
129
130 fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
131 where
132 V: de::Visitor<'de>,
133 {
134 visitor.visit_seq(ConfigSeqAccess::new(self)?)
135 }
136
137 fn deserialize_tuple_struct<V>(
138 self,
139 _name: &'static str,
140 _len: usize,
141 visitor: V,
142 ) -> Result<V::Value, Self::Error>
143 where
144 V: de::Visitor<'de>,
145 {
146 visitor.visit_seq(ConfigSeqAccess::new(self)?)
147 }
148
149 fn deserialize_newtype_struct<V>(
150 self,
151 name: &'static str,
152 visitor: V,
153 ) -> Result<V::Value, Self::Error>
154 where
155 V: de::Visitor<'de>,
156 {
157 if name == "StringList" {
158 let vals = self.gctx.get_list_or_string(&self.key)?;
159 let vals: Vec<String> = vals.into_iter().map(|vd| vd.0).collect();
160 visitor.visit_newtype_struct(vals.into_deserializer())
161 } else {
162 visitor.visit_newtype_struct(self)
163 }
164 }
165
166 fn deserialize_enum<V>(
167 self,
168 _name: &'static str,
169 _variants: &'static [&'static str],
170 visitor: V,
171 ) -> Result<V::Value, Self::Error>
172 where
173 V: de::Visitor<'de>,
174 {
175 let value = self
176 .gctx
177 .get_string_priv(&self.key)?
178 .ok_or_else(|| ConfigError::missing(&self.key))?;
179
180 let Value { val, definition } = value;
181 visitor
182 .visit_enum(val.into_deserializer())
183 .map_err(|e: ConfigError| e.with_key_context(&self.key, Some(definition)))
184 }
185
186 serde::forward_to_deserialize_any! {
188 f32 f64 char str bytes
189 byte_buf unit unit_struct
190 identifier ignored_any
191 }
192}
193
194struct ConfigMapAccess<'gctx> {
195 de: Deserializer<'gctx>,
196 fields: Vec<KeyKind>,
198 field_index: usize,
200}
201
202#[derive(Debug, PartialEq, Eq, Hash)]
203enum KeyKind {
204 Normal(String),
205 CaseSensitive(String),
206}
207
208impl<'gctx> ConfigMapAccess<'gctx> {
209 fn new_map(de: Deserializer<'gctx>) -> Result<ConfigMapAccess<'gctx>, ConfigError> {
210 let mut fields = Vec::new();
211 if let Some(mut v) = de.gctx.get_table(&de.key)? {
212 for (key, _value) in v.val.drain() {
214 fields.push(KeyKind::CaseSensitive(key));
215 }
216 }
217 if de.gctx.cli_unstable().advanced_env {
218 let env_prefix = format!("{}_", de.key.as_env_key());
220 for env_key in de.gctx.env_keys() {
221 if let Some(rest) = env_key.strip_prefix(&env_prefix) {
223 let part = rest.splitn(2, '_').next().unwrap();
225 fields.push(KeyKind::CaseSensitive(part.to_string()));
227 }
228 }
229 }
230 Ok(ConfigMapAccess {
231 de,
232 fields,
233 field_index: 0,
234 })
235 }
236
237 fn new_struct(
238 de: Deserializer<'gctx>,
239 given_fields: &'static [&'static str],
240 ) -> Result<ConfigMapAccess<'gctx>, ConfigError> {
241 let table = de.gctx.get_table(&de.key)?;
242
243 if let Some(v) = table.as_ref() {
248 let unused_keys = v
249 .val
250 .iter()
251 .filter(|(k, _v)| !given_fields.iter().any(|gk| gk == k));
252 for (unused_key, unused_value) in unused_keys {
253 de.gctx.shell().warn(format!(
254 "unused config key `{}.{}` in `{}`",
255 de.key,
256 unused_key,
257 unused_value.definition()
258 ))?;
259 }
260 }
261
262 let mut fields = HashSet::new();
263
264 for field in given_fields {
267 let mut field_key = de.key.clone();
268 field_key.push(field);
269 for env_key in de.gctx.env_keys() {
270 let Some(nested_field) = env_key.strip_prefix(field_key.as_env_key()) else {
271 continue;
272 };
273 if nested_field.is_empty() || nested_field.starts_with('_') {
279 fields.insert(KeyKind::Normal(field.to_string()));
280 }
281 }
282 }
283
284 if let Some(v) = table {
287 for key in v.val.keys() {
288 fields.insert(KeyKind::Normal(key.clone()));
289 }
290 }
291
292 Ok(ConfigMapAccess {
293 de,
294 fields: fields.into_iter().collect(),
295 field_index: 0,
296 })
297 }
298}
299
300impl<'de, 'gctx> de::MapAccess<'de> for ConfigMapAccess<'gctx> {
301 type Error = ConfigError;
302
303 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
304 where
305 K: de::DeserializeSeed<'de>,
306 {
307 if self.field_index >= self.fields.len() {
308 return Ok(None);
309 }
310 let field = match &self.fields[self.field_index] {
311 KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),
312 };
313 seed.deserialize(field.into_deserializer()).map(Some)
314 }
315
316 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
317 where
318 V: de::DeserializeSeed<'de>,
319 {
320 let field = &self.fields[self.field_index];
321 self.field_index += 1;
322 let field = match field {
324 KeyKind::Normal(field) => {
325 self.de.key.push(field);
326 field
327 }
328 KeyKind::CaseSensitive(field) => {
329 self.de.key.push_sensitive(field);
330 field
331 }
332 };
333 let env_prefix = format!("{}_", field).replace('-', "_");
351 let env_prefix_ok = !self.fields.iter().any(|field| {
352 let field = match field {
353 KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),
354 };
355 field.replace('-', "_").starts_with(&env_prefix)
356 });
357
358 let result = seed
359 .deserialize(Deserializer {
360 gctx: self.de.gctx,
361 key: self.de.key.clone(),
362 env_prefix_ok,
363 })
364 .map_err(|e| {
365 if !e.is_missing_field() {
366 return e;
367 }
368 e.with_key_context(
369 &self.de.key,
370 self.de
371 .gctx
372 .get_cv_with_env(&self.de.key)
373 .ok()
374 .and_then(|cv| cv.map(|cv| cv.get_definition().clone())),
375 )
376 });
377 self.de.key.pop();
378 result
379 }
380}
381
382struct ConfigSeqAccess {
383 list_iter: vec::IntoIter<(String, Definition)>,
384}
385
386impl ConfigSeqAccess {
387 fn new(de: Deserializer<'_>) -> Result<ConfigSeqAccess, ConfigError> {
388 let mut res = Vec::new();
389 if let Some(v) = de.gctx._get_list(&de.key)? {
390 res.extend(v.val);
391 }
392
393 de.gctx.get_env_list(&de.key, &mut res)?;
394
395 Ok(ConfigSeqAccess {
396 list_iter: res.into_iter(),
397 })
398 }
399}
400
401impl<'de> de::SeqAccess<'de> for ConfigSeqAccess {
402 type Error = ConfigError;
403
404 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
405 where
406 T: de::DeserializeSeed<'de>,
407 {
408 match self.list_iter.next() {
409 Some((value, def)) => {
411 let maybe_value_de = ValueDeserializer::new_with_string(value, def);
414 seed.deserialize(maybe_value_de).map(Some)
415 }
416 None => Ok(None),
417 }
418 }
419}
420
421struct ValueDeserializer<'gctx> {
429 hits: u32,
430 definition: Definition,
431 de: Option<Deserializer<'gctx>>,
434 str_value: Option<String>,
442}
443
444impl<'gctx> ValueDeserializer<'gctx> {
445 fn new(de: Deserializer<'gctx>) -> Result<ValueDeserializer<'gctx>, ConfigError> {
446 let definition = {
448 let env = de.key.as_env_key();
449 let env_def = Definition::Environment(env.to_string());
450 match (de.gctx.env.contains_key(env), de.gctx.get_cv(&de.key)?) {
451 (true, Some(cv)) => {
452 if env_def.is_higher_priority(cv.definition()) {
454 env_def
455 } else {
456 cv.definition().clone()
457 }
458 }
459 (false, Some(cv)) => cv.definition().clone(),
460 (_, None) => env_def,
464 }
465 };
466 Ok(ValueDeserializer {
467 hits: 0,
468 definition,
469 de: Some(de),
470 str_value: None,
471 })
472 }
473
474 fn new_with_string(s: String, definition: Definition) -> ValueDeserializer<'gctx> {
475 ValueDeserializer {
476 hits: 0,
477 definition,
478 de: None,
479 str_value: Some(s),
480 }
481 }
482}
483
484impl<'de, 'gctx> de::MapAccess<'de> for ValueDeserializer<'gctx> {
485 type Error = ConfigError;
486
487 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
488 where
489 K: de::DeserializeSeed<'de>,
490 {
491 self.hits += 1;
492 match self.hits {
493 1 => seed
494 .deserialize(value::VALUE_FIELD.into_deserializer())
495 .map(Some),
496 2 => seed
497 .deserialize(value::DEFINITION_FIELD.into_deserializer())
498 .map(Some),
499 _ => Ok(None),
500 }
501 }
502
503 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
504 where
505 V: de::DeserializeSeed<'de>,
506 {
507 if self.hits == 1 {
510 if let Some(de) = &self.de {
511 return seed
512 .deserialize(de.clone())
513 .map_err(|e| e.with_key_context(&de.key, Some(self.definition.clone())));
514 } else {
515 return seed
516 .deserialize(self.str_value.as_ref().unwrap().clone().into_deserializer());
517 }
518 }
519
520 match &self.definition {
523 Definition::Path(path) => {
524 seed.deserialize(Tuple2Deserializer(0i32, path.to_string_lossy()))
525 }
526 Definition::Environment(env) => {
527 seed.deserialize(Tuple2Deserializer(1i32, env.as_str()))
528 }
529 Definition::Cli(path) => {
530 let s = path
531 .as_ref()
532 .map(|p| p.to_string_lossy())
533 .unwrap_or_default();
534 seed.deserialize(Tuple2Deserializer(2i32, s))
535 }
536 }
537 }
538}
539
540impl<'de, 'gctx> de::Deserializer<'de> for ValueDeserializer<'gctx> {
545 type Error = ConfigError;
546
547 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
548 where
549 V: de::Visitor<'de>,
550 {
551 visitor.visit_str(&self.str_value.expect("string expected"))
552 }
553
554 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
555 where
556 V: de::Visitor<'de>,
557 {
558 visitor.visit_string(self.str_value.expect("string expected"))
559 }
560
561 fn deserialize_struct<V>(
562 self,
563 name: &'static str,
564 fields: &'static [&'static str],
565 visitor: V,
566 ) -> Result<V::Value, Self::Error>
567 where
568 V: de::Visitor<'de>,
569 {
570 if name == value::NAME && fields == value::FIELDS {
575 return visitor.visit_map(self);
576 }
577 unimplemented!("only strings and Value can be deserialized from a sequence");
578 }
579
580 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
581 where
582 V: de::Visitor<'de>,
583 {
584 visitor.visit_string(self.str_value.expect("string expected"))
585 }
586
587 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
588 where
589 V: de::Visitor<'de>,
590 {
591 visitor.visit_unit()
592 }
593
594 serde::forward_to_deserialize_any! {
595 i8 i16 i32 i64
596 u8 u16 u32 u64
597 option
598 newtype_struct seq tuple tuple_struct map enum bool
599 f32 f64 char bytes
600 byte_buf unit unit_struct
601 identifier
602 }
603}
604
605struct Tuple2Deserializer<T, U>(T, U);
609
610impl<'de, T, U> de::Deserializer<'de> for Tuple2Deserializer<T, U>
611where
612 T: IntoDeserializer<'de, ConfigError>,
613 U: IntoDeserializer<'de, ConfigError>,
614{
615 type Error = ConfigError;
616
617 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, ConfigError>
618 where
619 V: de::Visitor<'de>,
620 {
621 struct SeqVisitor<T, U> {
622 first: Option<T>,
623 second: Option<U>,
624 }
625 impl<'de, T, U> de::SeqAccess<'de> for SeqVisitor<T, U>
626 where
627 T: IntoDeserializer<'de, ConfigError>,
628 U: IntoDeserializer<'de, ConfigError>,
629 {
630 type Error = ConfigError;
631 fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
632 where
633 K: de::DeserializeSeed<'de>,
634 {
635 if let Some(first) = self.first.take() {
636 return seed.deserialize(first.into_deserializer()).map(Some);
637 }
638 if let Some(second) = self.second.take() {
639 return seed.deserialize(second.into_deserializer()).map(Some);
640 }
641 Ok(None)
642 }
643 }
644
645 visitor.visit_seq(SeqVisitor {
646 first: Some(self.0),
647 second: Some(self.1),
648 })
649 }
650
651 serde::forward_to_deserialize_any! {
652 bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
653 bytes byte_buf map struct option unit newtype_struct
654 ignored_any unit_struct tuple_struct tuple enum identifier
655 }
656}