1use crate::util::context::value;
25use crate::util::context::{ConfigError, ConfigKey, GlobalContext};
26use crate::util::context::{ConfigValue as CV, Definition, Value};
27use serde::{de, de::IntoDeserializer};
28use std::collections::HashSet;
29use std::vec;
30
31#[derive(Clone)]
34pub(super) struct Deserializer<'gctx> {
35 pub(super) gctx: &'gctx GlobalContext,
36 pub(super) key: ConfigKey,
38 pub(super) env_prefix_ok: bool,
45}
46
47macro_rules! deserialize_method {
48 ($method:ident, $visit:ident, $getter:ident) => {
49 fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
50 where
51 V: de::Visitor<'de>,
52 {
53 let v = self
54 .gctx
55 .$getter(&self.key)?
56 .ok_or_else(|| ConfigError::missing(&self.key))?;
57 let Value { val, definition } = v;
58 let res: Result<V::Value, ConfigError> = visitor.$visit(val);
59 res.map_err(|e| e.with_key_context(&self.key, Some(definition)))
60 }
61 };
62}
63
64impl<'de, 'gctx> de::Deserializer<'de> for Deserializer<'gctx> {
65 type Error = ConfigError;
66
67 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
68 where
69 V: de::Visitor<'de>,
70 {
71 let cv = self.gctx.get_cv_with_env(&self.key)?;
72 if let Some(cv) = cv {
73 let res: (Result<V::Value, ConfigError>, Definition) = match cv {
74 CV::Integer(i, def) => (visitor.visit_i64(i), def),
75 CV::String(s, def) => (visitor.visit_string(s), def),
76 CV::List(_, def) => (visitor.visit_seq(ConfigSeqAccess::new(self.clone())?), def),
77 CV::Table(_, def) => (
78 visitor.visit_map(ConfigMapAccess::new_map(self.clone())?),
79 def,
80 ),
81 CV::Boolean(b, def) => (visitor.visit_bool(b), def),
82 };
83 let (res, def) = res;
84 return res.map_err(|e| e.with_key_context(&self.key, Some(def)));
85 }
86
87 if self.gctx.has_key(&self.key, self.env_prefix_ok)? {
89 return visitor.visit_some(self);
90 }
91
92 Err(ConfigError::missing(&self.key))
93 }
94
95 deserialize_method!(deserialize_bool, visit_bool, get_bool);
96 deserialize_method!(deserialize_i8, visit_i64, get_integer);
97 deserialize_method!(deserialize_i16, visit_i64, get_integer);
98 deserialize_method!(deserialize_i32, visit_i64, get_integer);
99 deserialize_method!(deserialize_i64, visit_i64, get_integer);
100 deserialize_method!(deserialize_u8, visit_i64, get_integer);
101 deserialize_method!(deserialize_u16, visit_i64, get_integer);
102 deserialize_method!(deserialize_u32, visit_i64, get_integer);
103 deserialize_method!(deserialize_u64, visit_i64, get_integer);
104 deserialize_method!(deserialize_string, visit_string, get_string_priv);
105
106 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
107 where
108 V: de::Visitor<'de>,
109 {
110 if self.gctx.has_key(&self.key, self.env_prefix_ok)? {
111 visitor.visit_some(self)
112 } else {
113 visitor.visit_none()
115 }
116 }
117
118 fn deserialize_struct<V>(
119 self,
120 name: &'static str,
121 fields: &'static [&'static str],
122 visitor: V,
123 ) -> Result<V::Value, Self::Error>
124 where
125 V: de::Visitor<'de>,
126 {
127 if name == value::NAME && fields == value::FIELDS {
132 return visitor.visit_map(ValueDeserializer::new(self)?);
133 }
134 visitor.visit_map(ConfigMapAccess::new_struct(self, fields)?)
135 }
136
137 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
138 where
139 V: de::Visitor<'de>,
140 {
141 visitor.visit_map(ConfigMapAccess::new_map(self)?)
142 }
143
144 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
145 where
146 V: de::Visitor<'de>,
147 {
148 visitor.visit_seq(ConfigSeqAccess::new(self)?)
149 }
150
151 fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
152 where
153 V: de::Visitor<'de>,
154 {
155 visitor.visit_seq(ConfigSeqAccess::new(self)?)
156 }
157
158 fn deserialize_tuple_struct<V>(
159 self,
160 _name: &'static str,
161 _len: usize,
162 visitor: V,
163 ) -> Result<V::Value, Self::Error>
164 where
165 V: de::Visitor<'de>,
166 {
167 visitor.visit_seq(ConfigSeqAccess::new(self)?)
168 }
169
170 fn deserialize_newtype_struct<V>(
171 self,
172 name: &'static str,
173 visitor: V,
174 ) -> Result<V::Value, Self::Error>
175 where
176 V: de::Visitor<'de>,
177 {
178 if name == "StringList" {
179 let mut res = Vec::new();
180
181 match self.gctx.get_cv(&self.key)? {
182 Some(CV::List(val, _def)) => res.extend(val),
183 Some(CV::String(val, def)) => {
184 let split_vs = val
185 .split_whitespace()
186 .map(|s| CV::String(s.to_string(), def.clone()));
187 res.extend(split_vs);
188 }
189 Some(val) => {
190 self.gctx
191 .expected("string or array of strings", &self.key, &val)?;
192 }
193 None => {}
194 }
195
196 self.gctx.get_env_list(&self.key, &mut res)?;
197
198 let vals: Vec<String> = res
199 .into_iter()
200 .map(|val| match val {
201 CV::String(s, _defintion) => Ok(s),
202 other => Err(ConfigError::expected(&self.key, "string", &other)),
203 })
204 .collect::<Result<_, _>>()?;
205 visitor.visit_newtype_struct(vals.into_deserializer())
206 } else {
207 visitor.visit_newtype_struct(self)
208 }
209 }
210
211 fn deserialize_enum<V>(
212 self,
213 _name: &'static str,
214 _variants: &'static [&'static str],
215 visitor: V,
216 ) -> Result<V::Value, Self::Error>
217 where
218 V: de::Visitor<'de>,
219 {
220 let value = self
221 .gctx
222 .get_string_priv(&self.key)?
223 .ok_or_else(|| ConfigError::missing(&self.key))?;
224
225 let Value { val, definition } = value;
226 visitor
227 .visit_enum(val.into_deserializer())
228 .map_err(|e: ConfigError| e.with_key_context(&self.key, Some(definition)))
229 }
230
231 serde::forward_to_deserialize_any! {
233 f32 f64 char str bytes
234 byte_buf unit unit_struct
235 identifier ignored_any
236 }
237}
238
239struct ConfigMapAccess<'gctx> {
240 de: Deserializer<'gctx>,
241 fields: Vec<KeyKind>,
243 field_index: usize,
245}
246
247#[derive(Debug, PartialEq, Eq, Hash)]
248enum KeyKind {
249 Normal(String),
250 CaseSensitive(String),
251}
252
253impl<'gctx> ConfigMapAccess<'gctx> {
254 fn new_map(de: Deserializer<'gctx>) -> Result<ConfigMapAccess<'gctx>, ConfigError> {
255 let mut fields = Vec::new();
256 if let Some(mut v) = de.gctx.get_table(&de.key)? {
257 for (key, _value) in v.val.drain() {
259 fields.push(KeyKind::CaseSensitive(key));
260 }
261 }
262 if de.gctx.cli_unstable().advanced_env {
263 let env_prefix = format!("{}_", de.key.as_env_key());
265 for env_key in de.gctx.env_keys() {
266 if let Some(rest) = env_key.strip_prefix(&env_prefix) {
268 let part = rest.splitn(2, '_').next().unwrap();
270 fields.push(KeyKind::CaseSensitive(part.to_string()));
272 }
273 }
274 }
275 Ok(ConfigMapAccess {
276 de,
277 fields,
278 field_index: 0,
279 })
280 }
281
282 fn new_struct(
283 de: Deserializer<'gctx>,
284 given_fields: &'static [&'static str],
285 ) -> Result<ConfigMapAccess<'gctx>, ConfigError> {
286 let table = de.gctx.get_table(&de.key)?;
287
288 if let Some(v) = table.as_ref() {
293 let unused_keys = v
294 .val
295 .iter()
296 .filter(|(k, _v)| !given_fields.iter().any(|gk| gk == k));
297 for (unused_key, unused_value) in unused_keys {
298 de.gctx.shell().warn(format!(
299 "unused config key `{}.{}` in `{}`",
300 de.key,
301 unused_key,
302 unused_value.definition()
303 ))?;
304 }
305 }
306
307 let mut fields = HashSet::new();
308
309 for field in given_fields {
312 let mut field_key = de.key.clone();
313 field_key.push(field);
314 for env_key in de.gctx.env_keys() {
315 let Some(nested_field) = env_key.strip_prefix(field_key.as_env_key()) else {
316 continue;
317 };
318 if nested_field.is_empty() || nested_field.starts_with('_') {
324 fields.insert(KeyKind::Normal(field.to_string()));
325 }
326 }
327 }
328
329 if let Some(v) = table {
332 for key in v.val.keys() {
333 fields.insert(KeyKind::Normal(key.clone()));
334 }
335 }
336
337 Ok(ConfigMapAccess {
338 de,
339 fields: fields.into_iter().collect(),
340 field_index: 0,
341 })
342 }
343}
344
345impl<'de, 'gctx> de::MapAccess<'de> for ConfigMapAccess<'gctx> {
346 type Error = ConfigError;
347
348 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
349 where
350 K: de::DeserializeSeed<'de>,
351 {
352 if self.field_index >= self.fields.len() {
353 return Ok(None);
354 }
355 let field = match &self.fields[self.field_index] {
356 KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),
357 };
358 seed.deserialize(field.into_deserializer()).map(Some)
359 }
360
361 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
362 where
363 V: de::DeserializeSeed<'de>,
364 {
365 let field = &self.fields[self.field_index];
366 self.field_index += 1;
367 let field = match field {
369 KeyKind::Normal(field) => {
370 self.de.key.push(field);
371 field
372 }
373 KeyKind::CaseSensitive(field) => {
374 self.de.key.push_sensitive(field);
375 field
376 }
377 };
378 let env_prefix = format!("{}_", field).replace('-', "_");
396 let env_prefix_ok = !self.fields.iter().any(|field| {
397 let field = match field {
398 KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),
399 };
400 field.replace('-', "_").starts_with(&env_prefix)
401 });
402
403 let result = seed
404 .deserialize(Deserializer {
405 gctx: self.de.gctx,
406 key: self.de.key.clone(),
407 env_prefix_ok,
408 })
409 .map_err(|e| {
410 if !e.is_missing_field() {
411 return e;
412 }
413 e.with_key_context(
414 &self.de.key,
415 self.de
416 .gctx
417 .get_cv_with_env(&self.de.key)
418 .ok()
419 .and_then(|cv| cv.map(|cv| cv.definition().clone())),
420 )
421 });
422 self.de.key.pop();
423 result
424 }
425}
426
427struct ConfigSeqAccess {
428 key: ConfigKey,
430 list_iter: vec::IntoIter<CV>,
431}
432
433impl ConfigSeqAccess {
434 fn new(de: Deserializer<'_>) -> Result<ConfigSeqAccess, ConfigError> {
435 let mut res = Vec::new();
436
437 match de.gctx.get_cv(&de.key)? {
438 Some(CV::List(val, _definition)) => {
439 res.extend(val);
440 }
441 Some(val) => {
442 de.gctx.expected("list", &de.key, &val)?;
443 }
444 None => {}
445 }
446
447 de.gctx.get_env_list(&de.key, &mut res)?;
448
449 Ok(ConfigSeqAccess {
450 key: de.key,
451 list_iter: res.into_iter(),
452 })
453 }
454}
455
456impl<'de> de::SeqAccess<'de> for ConfigSeqAccess {
457 type Error = ConfigError;
458
459 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
460 where
461 T: de::DeserializeSeed<'de>,
462 {
463 match self.list_iter.next() {
464 Some(val @ CV::String(..)) => {
466 seed.deserialize(ArrayItemDeserializer::new(val)).map(Some)
469 }
470 Some(val) => Err(ConfigError::expected(&self.key, "list of string", &val)),
471 None => Ok(None),
472 }
473 }
474}
475
476enum ValueSource<'gctx> {
478 Deserializer {
480 de: Deserializer<'gctx>,
481 definition: Definition,
482 },
483 ConfigValue(CV),
491}
492
493struct ValueDeserializer<'gctx> {
501 hits: u32,
502 source: ValueSource<'gctx>,
503}
504
505impl<'gctx> ValueDeserializer<'gctx> {
506 fn new(de: Deserializer<'gctx>) -> Result<ValueDeserializer<'gctx>, 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(ValueDeserializer {
529 hits: 0,
530 source: ValueSource::Deserializer { de, definition },
531 })
532 }
533
534 fn with_cv(cv: CV) -> ValueDeserializer<'gctx> {
535 ValueDeserializer {
536 hits: 0,
537 source: ValueSource::ConfigValue(cv),
538 }
539 }
540
541 fn definition(&self) -> &Definition {
542 match &self.source {
543 ValueSource::Deserializer { definition, .. } => definition,
544 ValueSource::ConfigValue(cv) => cv.definition(),
545 }
546 }
547}
548
549impl<'de, 'gctx> de::MapAccess<'de> for ValueDeserializer<'gctx> {
550 type Error = ConfigError;
551
552 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
553 where
554 K: de::DeserializeSeed<'de>,
555 {
556 self.hits += 1;
557 match self.hits {
558 1 => seed
559 .deserialize(value::VALUE_FIELD.into_deserializer())
560 .map(Some),
561 2 => seed
562 .deserialize(value::DEFINITION_FIELD.into_deserializer())
563 .map(Some),
564 _ => Ok(None),
565 }
566 }
567
568 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
569 where
570 V: de::DeserializeSeed<'de>,
571 {
572 if self.hits == 1 {
575 return match &self.source {
576 ValueSource::Deserializer { de, definition } => seed
577 .deserialize(de.clone())
578 .map_err(|e| e.with_key_context(&de.key, Some(definition.clone()))),
579 ValueSource::ConfigValue(cv) => {
580 seed.deserialize(ArrayItemDeserializer::new(cv.clone()))
581 }
582 };
583 }
584
585 match self.definition() {
588 Definition::BuiltIn => seed.deserialize(0.into_deserializer()),
589 Definition::Path(path) => {
590 seed.deserialize(Tuple2Deserializer(1i32, path.to_string_lossy()))
591 }
592 Definition::Environment(env) => {
593 seed.deserialize(Tuple2Deserializer(2i32, env.as_str()))
594 }
595 Definition::Cli(path) => {
596 let s = path
597 .as_ref()
598 .map(|p| p.to_string_lossy())
599 .unwrap_or_default();
600 seed.deserialize(Tuple2Deserializer(3i32, s))
601 }
602 }
603 }
604}
605
606#[derive(Clone)]
613struct ArrayItemDeserializer {
614 cv: CV,
615}
616
617impl ArrayItemDeserializer {
618 fn new(cv: CV) -> Self {
619 Self { cv }
620 }
621
622 fn into_inner(self) -> String {
623 match self.cv {
624 CV::String(s, _def) => s,
625 _ => unreachable!("string expected"),
626 }
627 }
628}
629
630impl<'de> de::Deserializer<'de> for ArrayItemDeserializer {
631 type Error = ConfigError;
632
633 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
634 where
635 V: de::Visitor<'de>,
636 {
637 visitor.visit_str(&self.into_inner())
638 }
639
640 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
641 where
642 V: de::Visitor<'de>,
643 {
644 visitor.visit_string(self.into_inner())
645 }
646
647 fn deserialize_struct<V>(
648 self,
649 name: &'static str,
650 fields: &'static [&'static str],
651 visitor: V,
652 ) -> Result<V::Value, Self::Error>
653 where
654 V: de::Visitor<'de>,
655 {
656 if name == value::NAME && fields == value::FIELDS {
661 return visitor.visit_map(ValueDeserializer::with_cv(self.cv));
662 }
663 unimplemented!("only strings and Value can be deserialized from a sequence");
664 }
665
666 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
667 where
668 V: de::Visitor<'de>,
669 {
670 visitor.visit_string(self.into_inner())
671 }
672
673 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
674 where
675 V: de::Visitor<'de>,
676 {
677 visitor.visit_unit()
678 }
679
680 serde::forward_to_deserialize_any! {
681 i8 i16 i32 i64
682 u8 u16 u32 u64
683 option
684 newtype_struct seq tuple tuple_struct map enum bool
685 f32 f64 char bytes
686 byte_buf unit unit_struct
687 identifier
688 }
689}
690
691struct Tuple2Deserializer<T, U>(T, U);
695
696impl<'de, T, U> de::Deserializer<'de> for Tuple2Deserializer<T, U>
697where
698 T: IntoDeserializer<'de, ConfigError>,
699 U: IntoDeserializer<'de, ConfigError>,
700{
701 type Error = ConfigError;
702
703 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, ConfigError>
704 where
705 V: de::Visitor<'de>,
706 {
707 struct SeqVisitor<T, U> {
708 first: Option<T>,
709 second: Option<U>,
710 }
711 impl<'de, T, U> de::SeqAccess<'de> for SeqVisitor<T, U>
712 where
713 T: IntoDeserializer<'de, ConfigError>,
714 U: IntoDeserializer<'de, ConfigError>,
715 {
716 type Error = ConfigError;
717 fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
718 where
719 K: de::DeserializeSeed<'de>,
720 {
721 if let Some(first) = self.first.take() {
722 return seed.deserialize(first.into_deserializer()).map(Some);
723 }
724 if let Some(second) = self.second.take() {
725 return seed.deserialize(second.into_deserializer()).map(Some);
726 }
727 Ok(None)
728 }
729 }
730
731 visitor.visit_seq(SeqVisitor {
732 first: Some(self.0),
733 second: Some(self.1),
734 })
735 }
736
737 serde::forward_to_deserialize_any! {
738 bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
739 bytes byte_buf map struct option unit newtype_struct
740 ignored_any unit_struct tuple_struct tuple enum identifier
741 }
742}