1use crate::util::context::key::ArrayItemKeyPath;
25use crate::util::context::value;
26use crate::util::context::{ConfigError, ConfigKey, GlobalContext};
27use crate::util::context::{ConfigValue as CV, Definition, Value};
28use serde::{de, de::IntoDeserializer};
29use std::collections::HashSet;
30use std::vec;
31
32#[derive(Clone)]
35pub(super) struct Deserializer<'gctx> {
36 pub(super) gctx: &'gctx GlobalContext,
37 pub(super) key: ConfigKey,
39 pub(super) env_prefix_ok: bool,
46}
47
48macro_rules! deserialize_method {
49 ($method:ident, $visit:ident, $getter:ident) => {
50 fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
51 where
52 V: de::Visitor<'de>,
53 {
54 let v = self
55 .gctx
56 .$getter(&self.key)?
57 .ok_or_else(|| ConfigError::missing(&self.key))?;
58 let Value { val, definition } = v;
59 let res: Result<V::Value, ConfigError> = visitor.$visit(val);
60 res.map_err(|e| e.with_key_context(&self.key, Some(definition)))
61 }
62 };
63}
64
65impl<'de, 'gctx> de::Deserializer<'de> for Deserializer<'gctx> {
66 type Error = ConfigError;
67
68 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
69 where
70 V: de::Visitor<'de>,
71 {
72 let cv = self.gctx.get_cv_with_env(&self.key)?;
73 if let Some(cv) = cv {
74 let res: (Result<V::Value, ConfigError>, Definition) = match cv {
75 CV::Integer(i, def) => (visitor.visit_i64(i), def),
76 CV::String(s, def) => (visitor.visit_string(s), def),
77 CV::List(_, def) => (visitor.visit_seq(ConfigSeqAccess::new(self.clone())?), def),
78 CV::Table(_, def) => (
79 visitor.visit_map(ConfigMapAccess::new_map(self.clone())?),
80 def,
81 ),
82 CV::Boolean(b, def) => (visitor.visit_bool(b), def),
83 };
84 let (res, def) = res;
85 return res.map_err(|e| e.with_key_context(&self.key, Some(def)));
86 }
87
88 if self.gctx.has_key(&self.key, self.env_prefix_ok)? {
90 return visitor.visit_some(self);
91 }
92
93 Err(ConfigError::missing(&self.key))
94 }
95
96 deserialize_method!(deserialize_bool, visit_bool, get_bool);
97 deserialize_method!(deserialize_i8, visit_i64, get_integer);
98 deserialize_method!(deserialize_i16, visit_i64, get_integer);
99 deserialize_method!(deserialize_i32, visit_i64, get_integer);
100 deserialize_method!(deserialize_i64, visit_i64, get_integer);
101 deserialize_method!(deserialize_u8, visit_i64, get_integer);
102 deserialize_method!(deserialize_u16, visit_i64, get_integer);
103 deserialize_method!(deserialize_u32, visit_i64, get_integer);
104 deserialize_method!(deserialize_u64, visit_i64, get_integer);
105 deserialize_method!(deserialize_string, visit_string, get_string_priv);
106
107 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
108 where
109 V: de::Visitor<'de>,
110 {
111 if self.gctx.has_key(&self.key, self.env_prefix_ok)? {
112 visitor.visit_some(self)
113 } else {
114 visitor.visit_none()
116 }
117 }
118
119 fn deserialize_struct<V>(
120 self,
121 name: &'static str,
122 fields: &'static [&'static str],
123 visitor: V,
124 ) -> Result<V::Value, Self::Error>
125 where
126 V: de::Visitor<'de>,
127 {
128 if name == value::NAME && fields == value::FIELDS {
133 let source = ValueSource::with_deserializer(self)?;
134 return visitor.visit_map(ValueDeserializer::new(source));
135 }
136 visitor.visit_map(ConfigMapAccess::new_struct(self, fields)?)
137 }
138
139 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
140 where
141 V: de::Visitor<'de>,
142 {
143 visitor.visit_map(ConfigMapAccess::new_map(self)?)
144 }
145
146 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
147 where
148 V: de::Visitor<'de>,
149 {
150 visitor.visit_seq(ConfigSeqAccess::new(self)?)
151 }
152
153 fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
154 where
155 V: de::Visitor<'de>,
156 {
157 visitor.visit_seq(ConfigSeqAccess::new(self)?)
158 }
159
160 fn deserialize_tuple_struct<V>(
161 self,
162 _name: &'static str,
163 _len: usize,
164 visitor: V,
165 ) -> Result<V::Value, Self::Error>
166 where
167 V: de::Visitor<'de>,
168 {
169 visitor.visit_seq(ConfigSeqAccess::new(self)?)
170 }
171
172 fn deserialize_newtype_struct<V>(
173 self,
174 name: &'static str,
175 visitor: V,
176 ) -> Result<V::Value, Self::Error>
177 where
178 V: de::Visitor<'de>,
179 {
180 if name == "StringList" {
181 let mut res = Vec::new();
182
183 match self.gctx.get_cv(&self.key)? {
184 Some(CV::List(val, _def)) => res.extend(val),
185 Some(CV::String(val, def)) => {
186 let split_vs = val
187 .split_whitespace()
188 .map(|s| CV::String(s.to_string(), def.clone()));
189 res.extend(split_vs);
190 }
191 Some(val) => {
192 self.gctx
193 .expected("string or array of strings", &self.key, &val)?;
194 }
195 None => {}
196 }
197
198 self.gctx.get_env_list(&self.key, &mut res)?;
199
200 let vals: Vec<String> = res
201 .into_iter()
202 .map(|val| match val {
203 CV::String(s, _definition) => Ok(s),
204 other => Err(ConfigError::expected(&self.key, "string", &other)),
205 })
206 .collect::<Result<_, _>>()?;
207 visitor.visit_newtype_struct(vals.into_deserializer())
208 } else {
209 visitor.visit_newtype_struct(self)
210 }
211 }
212
213 fn deserialize_enum<V>(
214 self,
215 _name: &'static str,
216 _variants: &'static [&'static str],
217 visitor: V,
218 ) -> Result<V::Value, Self::Error>
219 where
220 V: de::Visitor<'de>,
221 {
222 let value = self
223 .gctx
224 .get_string_priv(&self.key)?
225 .ok_or_else(|| ConfigError::missing(&self.key))?;
226
227 let Value { val, definition } = value;
228 visitor
229 .visit_enum(val.into_deserializer())
230 .map_err(|e: ConfigError| e.with_key_context(&self.key, Some(definition)))
231 }
232
233 serde::forward_to_deserialize_any! {
235 f32 f64 char str bytes
236 byte_buf unit unit_struct
237 identifier ignored_any
238 }
239}
240
241struct ConfigMapAccess<'gctx> {
242 de: Deserializer<'gctx>,
243 fields: Vec<KeyKind>,
245 field_index: usize,
247}
248
249#[derive(Debug, PartialEq, Eq, Hash)]
250enum KeyKind {
251 Normal(String),
252 CaseSensitive(String),
253}
254
255impl<'gctx> ConfigMapAccess<'gctx> {
256 fn new_map(de: Deserializer<'gctx>) -> Result<ConfigMapAccess<'gctx>, ConfigError> {
257 let mut fields = Vec::new();
258 if let Some(mut v) = de.gctx.get_table(&de.key)? {
259 for (key, _value) in v.val.drain() {
261 fields.push(KeyKind::CaseSensitive(key));
262 }
263 }
264 if de.gctx.cli_unstable().advanced_env {
265 let env_prefix = format!("{}_", de.key.as_env_key());
267 for env_key in de.gctx.env_keys() {
268 if let Some(rest) = env_key.strip_prefix(&env_prefix) {
270 let part = rest.splitn(2, '_').next().unwrap();
272 fields.push(KeyKind::CaseSensitive(part.to_string()));
274 }
275 }
276 }
277 Ok(ConfigMapAccess {
278 de,
279 fields,
280 field_index: 0,
281 })
282 }
283
284 fn new_struct(
285 de: Deserializer<'gctx>,
286 given_fields: &'static [&'static str],
287 ) -> Result<ConfigMapAccess<'gctx>, ConfigError> {
288 let table = de.gctx.get_table(&de.key)?;
289
290 if let Some(v) = table.as_ref() {
295 let unused_keys = v
296 .val
297 .iter()
298 .filter(|(k, _v)| !given_fields.iter().any(|gk| gk == k));
299 for (unused_key, unused_value) in unused_keys {
300 de.gctx.shell().warn(format!(
301 "unused config key `{}.{}` in `{}`",
302 de.key,
303 unused_key,
304 unused_value.definition()
305 ))?;
306 }
307 }
308
309 let mut fields = HashSet::new();
310
311 for field in given_fields {
314 let mut field_key = de.key.clone();
315 field_key.push(field);
316 for env_key in de.gctx.env_keys() {
317 let Some(nested_field) = env_key.strip_prefix(field_key.as_env_key()) else {
318 continue;
319 };
320 if nested_field.is_empty() || nested_field.starts_with('_') {
326 fields.insert(KeyKind::Normal(field.to_string()));
327 }
328 }
329 }
330
331 if let Some(v) = table {
334 for key in v.val.keys() {
335 fields.insert(KeyKind::Normal(key.clone()));
336 }
337 }
338
339 Ok(ConfigMapAccess {
340 de,
341 fields: fields.into_iter().collect(),
342 field_index: 0,
343 })
344 }
345}
346
347impl<'de, 'gctx> de::MapAccess<'de> for ConfigMapAccess<'gctx> {
348 type Error = ConfigError;
349
350 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
351 where
352 K: de::DeserializeSeed<'de>,
353 {
354 if self.field_index >= self.fields.len() {
355 return Ok(None);
356 }
357 let field = match &self.fields[self.field_index] {
358 KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),
359 };
360 seed.deserialize(field.into_deserializer()).map(Some)
361 }
362
363 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
364 where
365 V: de::DeserializeSeed<'de>,
366 {
367 let field = &self.fields[self.field_index];
368 self.field_index += 1;
369 let field = match field {
371 KeyKind::Normal(field) => {
372 self.de.key.push(field);
373 field
374 }
375 KeyKind::CaseSensitive(field) => {
376 self.de.key.push_sensitive(field);
377 field
378 }
379 };
380 let env_prefix = format!("{}_", field).replace('-', "_");
398 let env_prefix_ok = !self.fields.iter().any(|field| {
399 let field = match field {
400 KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),
401 };
402 field.replace('-', "_").starts_with(&env_prefix)
403 });
404
405 let result = seed
406 .deserialize(Deserializer {
407 gctx: self.de.gctx,
408 key: self.de.key.clone(),
409 env_prefix_ok,
410 })
411 .map_err(|e| {
412 if !e.is_missing_field() {
413 return e;
414 }
415 e.with_key_context(
416 &self.de.key,
417 self.de
418 .gctx
419 .get_cv_with_env(&self.de.key)
420 .ok()
421 .and_then(|cv| cv.map(|cv| cv.definition().clone())),
422 )
423 });
424 self.de.key.pop();
425 result
426 }
427}
428
429struct ConfigSeqAccess<'gctx> {
430 de: Deserializer<'gctx>,
431 list_iter: std::iter::Enumerate<vec::IntoIter<CV>>,
432}
433
434impl ConfigSeqAccess<'_> {
435 fn new(de: Deserializer<'_>) -> Result<ConfigSeqAccess<'_>, ConfigError> {
436 let mut res = Vec::new();
437
438 match de.gctx.get_cv(&de.key)? {
439 Some(CV::List(val, _definition)) => {
440 res.extend(val);
441 }
442 Some(val) => {
443 de.gctx.expected("list", &de.key, &val)?;
444 }
445 None => {}
446 }
447
448 de.gctx.get_env_list(&de.key, &mut res)?;
449
450 Ok(ConfigSeqAccess {
451 de,
452 list_iter: res.into_iter().enumerate(),
453 })
454 }
455}
456
457impl<'de, 'gctx> de::SeqAccess<'de> for ConfigSeqAccess<'gctx> {
458 type Error = ConfigError;
459
460 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
461 where
462 T: de::DeserializeSeed<'de>,
463 {
464 let Some((i, cv)) = self.list_iter.next() else {
465 return Ok(None);
466 };
467
468 let mut key_path = ArrayItemKeyPath::new(self.de.key.clone());
469 let definition = Some(cv.definition().clone());
470 let de = ArrayItemDeserializer {
471 cv,
472 key_path: &mut key_path,
473 };
474 seed.deserialize(de)
475 .map_err(|e| {
476 key_path.push_index(i);
480 e.with_array_item_key_context(&key_path, definition)
481 })
482 .map(Some)
483 }
484}
485
486enum ValueSource<'gctx, 'err> {
488 Deserializer {
490 de: Deserializer<'gctx>,
491 definition: Definition,
492 },
493 ConfigValue {
500 cv: CV,
501 key_path: &'err mut ArrayItemKeyPath,
502 },
503}
504
505impl<'gctx, 'err> ValueSource<'gctx, 'err> {
506 fn with_deserializer(de: Deserializer<'gctx>) -> Result<ValueSource<'gctx, 'err>, ConfigError> {
507 let definition = {
509 let env = de.key.as_env_key();
510 let env_def = Definition::Environment(env.to_string());
511 match (de.gctx.env.contains_key(env), de.gctx.get_cv(&de.key)?) {
512 (true, Some(cv)) => {
513 if env_def.is_higher_priority(cv.definition()) {
515 env_def
516 } else {
517 cv.definition().clone()
518 }
519 }
520 (false, Some(cv)) => cv.definition().clone(),
521 (_, None) => env_def,
525 }
526 };
527
528 Ok(Self::Deserializer { de, definition })
529 }
530
531 fn with_cv(cv: CV, key_path: &'err mut ArrayItemKeyPath) -> ValueSource<'gctx, 'err> {
532 ValueSource::ConfigValue { cv, key_path }
533 }
534}
535
536struct ValueDeserializer<'gctx, 'err> {
544 hits: u32,
545 source: ValueSource<'gctx, 'err>,
546}
547
548impl<'gctx, 'err> ValueDeserializer<'gctx, 'err> {
549 fn new(source: ValueSource<'gctx, 'err>) -> ValueDeserializer<'gctx, 'err> {
550 Self { hits: 0, source }
551 }
552
553 fn definition(&self) -> &Definition {
554 match &self.source {
555 ValueSource::Deserializer { definition, .. } => definition,
556 ValueSource::ConfigValue { cv, .. } => cv.definition(),
557 }
558 }
559}
560
561impl<'de, 'gctx, 'err> de::MapAccess<'de> for ValueDeserializer<'gctx, 'err> {
562 type Error = ConfigError;
563
564 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
565 where
566 K: de::DeserializeSeed<'de>,
567 {
568 self.hits += 1;
569 match self.hits {
570 1 => seed
571 .deserialize(value::VALUE_FIELD.into_deserializer())
572 .map(Some),
573 2 => seed
574 .deserialize(value::DEFINITION_FIELD.into_deserializer())
575 .map(Some),
576 _ => Ok(None),
577 }
578 }
579
580 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
581 where
582 V: de::DeserializeSeed<'de>,
583 {
584 if self.hits == 1 {
587 return match &mut self.source {
588 ValueSource::Deserializer { de, definition } => seed
589 .deserialize(de.clone())
590 .map_err(|e| e.with_key_context(&de.key, Some(definition.clone()))),
591 ValueSource::ConfigValue { cv, key_path } => {
592 let de = ArrayItemDeserializer {
593 cv: cv.clone(),
594 key_path,
595 };
596 seed.deserialize(de)
597 }
598 };
599 }
600
601 match self.definition() {
604 Definition::BuiltIn => seed.deserialize(0.into_deserializer()),
605 Definition::Path(path) => {
606 seed.deserialize(Tuple2Deserializer(1i32, path.to_string_lossy()))
607 }
608 Definition::Environment(env) => {
609 seed.deserialize(Tuple2Deserializer(2i32, env.as_str()))
610 }
611 Definition::Cli(path) => {
612 let s = path
613 .as_ref()
614 .map(|p| p.to_string_lossy())
615 .unwrap_or_default();
616 seed.deserialize(Tuple2Deserializer(3i32, s))
617 }
618 }
619 }
620}
621
622struct ArrayItemDeserializer<'err> {
627 cv: CV,
628 key_path: &'err mut ArrayItemKeyPath,
629}
630
631impl<'de, 'err> de::Deserializer<'de> for ArrayItemDeserializer<'err> {
632 type Error = ConfigError;
633
634 fn deserialize_struct<V>(
635 self,
636 name: &'static str,
637 fields: &'static [&'static str],
638 visitor: V,
639 ) -> Result<V::Value, Self::Error>
640 where
641 V: de::Visitor<'de>,
642 {
643 if name == value::NAME && fields == value::FIELDS {
648 let source = ValueSource::with_cv(self.cv, self.key_path);
649 return visitor.visit_map(ValueDeserializer::new(source));
650 }
651 visitor.visit_map(ArrayItemMapAccess::with_struct(
652 self.cv,
653 fields,
654 self.key_path,
655 ))
656 }
657
658 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
659 where
660 V: de::Visitor<'de>,
661 {
662 match self.cv {
663 CV::String(s, _) => visitor.visit_string(s),
664 CV::Integer(i, _) => visitor.visit_i64(i),
665 CV::Boolean(b, _) => visitor.visit_bool(b),
666 l @ CV::List(_, _) => visitor.visit_seq(ArrayItemSeqAccess::new(l, self.key_path)),
667 t @ CV::Table(_, _) => visitor.visit_map(ArrayItemMapAccess::new(t, self.key_path)),
668 }
669 }
670
671 serde::forward_to_deserialize_any! {
673 bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
674 bytes byte_buf map option unit newtype_struct
675 ignored_any unit_struct tuple_struct tuple enum identifier
676 }
677}
678
679struct ArrayItemSeqAccess<'err> {
681 items: std::iter::Enumerate<vec::IntoIter<CV>>,
682 key_path: &'err mut ArrayItemKeyPath,
683}
684
685impl<'err> ArrayItemSeqAccess<'err> {
686 fn new(cv: CV, key_path: &'err mut ArrayItemKeyPath) -> ArrayItemSeqAccess<'err> {
687 let items = match cv {
688 CV::List(list, _) => list.into_iter().enumerate(),
689 _ => unreachable!("must be a list"),
690 };
691 Self { items, key_path }
692 }
693}
694
695impl<'de, 'err> de::SeqAccess<'de> for ArrayItemSeqAccess<'err> {
696 type Error = ConfigError;
697
698 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
699 where
700 T: de::DeserializeSeed<'de>,
701 {
702 match self.items.next() {
703 Some((i, cv)) => {
704 let de = ArrayItemDeserializer {
705 cv,
706 key_path: self.key_path,
707 };
708 seed.deserialize(de)
709 .inspect_err(|_| self.key_path.push_index(i))
710 .map(Some)
711 }
712 None => Ok(None),
713 }
714 }
715}
716
717struct ArrayItemMapAccess<'err> {
719 cv: CV,
720 keys: vec::IntoIter<String>,
721 current_key: Option<String>,
722 key_path: &'err mut ArrayItemKeyPath,
723}
724
725impl<'err> ArrayItemMapAccess<'err> {
726 fn new(cv: CV, key_path: &'err mut ArrayItemKeyPath) -> Self {
727 let keys = match &cv {
728 CV::Table(map, _) => map.keys().cloned().collect::<Vec<_>>().into_iter(),
729 _ => unreachable!("must be a map"),
730 };
731 Self {
732 cv,
733 keys,
734 current_key: None,
735 key_path,
736 }
737 }
738
739 fn with_struct(cv: CV, given_fields: &[&str], key_path: &'err mut ArrayItemKeyPath) -> Self {
740 let keys = given_fields
743 .into_iter()
744 .map(|s| s.to_string())
745 .collect::<Vec<_>>()
746 .into_iter();
747 Self {
748 cv,
749 keys,
750 current_key: None,
751 key_path,
752 }
753 }
754}
755
756impl<'de, 'err> de::MapAccess<'de> for ArrayItemMapAccess<'err> {
757 type Error = ConfigError;
758
759 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
760 where
761 K: de::DeserializeSeed<'de>,
762 {
763 match self.keys.next() {
764 Some(key) => {
765 self.current_key = Some(key.clone());
766 seed.deserialize(key.into_deserializer()).map(Some)
767 }
768 None => Ok(None),
769 }
770 }
771
772 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
773 where
774 V: de::DeserializeSeed<'de>,
775 {
776 let key = self.current_key.take().unwrap();
777 match &self.cv {
778 CV::Table(map, _) => {
779 if let Some(cv) = map.get(&key) {
780 let de = ArrayItemDeserializer {
781 cv: cv.clone(),
782 key_path: self.key_path,
783 };
784 seed.deserialize(de)
785 .inspect_err(|_| self.key_path.push_key(key))
786 } else {
787 Err(ConfigError::new(
788 format!("missing config key `{key}`"),
789 self.cv.definition().clone(),
790 ))
791 }
792 }
793 _ => Err(ConfigError::new(
794 "expected table".to_string(),
795 self.cv.definition().clone(),
796 )),
797 }
798 }
799}
800
801struct Tuple2Deserializer<T, U>(T, U);
805
806impl<'de, T, U> de::Deserializer<'de> for Tuple2Deserializer<T, U>
807where
808 T: IntoDeserializer<'de, ConfigError>,
809 U: IntoDeserializer<'de, ConfigError>,
810{
811 type Error = ConfigError;
812
813 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, ConfigError>
814 where
815 V: de::Visitor<'de>,
816 {
817 struct SeqVisitor<T, U> {
818 first: Option<T>,
819 second: Option<U>,
820 }
821 impl<'de, T, U> de::SeqAccess<'de> for SeqVisitor<T, U>
822 where
823 T: IntoDeserializer<'de, ConfigError>,
824 U: IntoDeserializer<'de, ConfigError>,
825 {
826 type Error = ConfigError;
827 fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
828 where
829 K: de::DeserializeSeed<'de>,
830 {
831 if let Some(first) = self.first.take() {
832 return seed.deserialize(first.into_deserializer()).map(Some);
833 }
834 if let Some(second) = self.second.take() {
835 return seed.deserialize(second.into_deserializer()).map(Some);
836 }
837 Ok(None)
838 }
839 }
840
841 visitor.visit_seq(SeqVisitor {
842 first: Some(self.0),
843 second: Some(self.1),
844 })
845 }
846
847 serde::forward_to_deserialize_any! {
848 bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
849 bytes byte_buf map struct option unit newtype_struct
850 ignored_any unit_struct tuple_struct tuple enum identifier
851 }
852}