cargo/util/context/
de.rs

1//! Deserialization for converting [`ConfigValue`] instances to target types.
2//!
3//! The [`Deserializer`] type is the main driver of deserialization.
4//! The workflow is roughly:
5//!
6//! 1. [`GlobalContext::get<T>()`] creates [`Deserializer`] and calls `T::deserialize()`
7//! 2. Then call type-specific deserialize methods as in normal serde deserialization.
8//!     - For primitives, `deserialize_*` methods look up [`ConfigValue`] instances
9//!       in [`GlobalContext`] and convert.
10//!     - Structs and maps are handled by [`ConfigMapAccess`].
11//!     - Sequences are handled by [`ConfigSeqAccess`],
12//!       which later uses [`ArrayItemDeserializer`] for each array item.
13//!     - [`Value<T>`] is delegated to [`ValueDeserializer`] in `deserialize_struct`.
14//!
15//! The purpose of this workflow is to:
16//!
17//! - Retrieve the correct config value based on source location precedence
18//! - Provide richer error context showing where a config is defined
19//! - Provide a richer internal API to map to concrete config types
20//!   without touching underlying [`ConfigValue`] directly
21//!
22//! [`ConfigValue`]: CV
23
24use 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/// Serde deserializer used to convert config values to a target type using
32/// [`GlobalContext::get`].
33#[derive(Clone)]
34pub(super) struct Deserializer<'gctx> {
35    pub(super) gctx: &'gctx GlobalContext,
36    /// The current key being deserialized.
37    pub(super) key: ConfigKey,
38    /// Whether or not this key part is allowed to be an inner table. For
39    /// example, `profile.dev.build-override` needs to check if
40    /// `CARGO_PROFILE_DEV_BUILD_OVERRIDE_` prefixes exist. But
41    /// `CARGO_BUILD_TARGET` should not check for prefixes because it would
42    /// collide with `CARGO_BUILD_TARGET_DIR`. See `ConfigMapAccess` for
43    /// details.
44    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        // The effect here is the same as in `deserialize_option`.
88        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            // Treat missing values as `None`.
114            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        // Match on the magical struct name/field names that are passed in to
128        // detect when we're deserializing `Value<T>`.
129        //
130        // See more comments in `value.rs` for the protocol used here.
131        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    // These aren't really supported, yet.
232    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    /// The fields that this map should deserialize.
242    fields: Vec<KeyKind>,
243    /// Current field being deserialized.
244    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            // `v: Value<HashMap<String, CV>>`
258            for (key, _value) in v.val.drain() {
259                fields.push(KeyKind::CaseSensitive(key));
260            }
261        }
262        if de.gctx.cli_unstable().advanced_env {
263            // `CARGO_PROFILE_DEV_PACKAGE_`
264            let env_prefix = format!("{}_", de.key.as_env_key());
265            for env_key in de.gctx.env_keys() {
266                // `CARGO_PROFILE_DEV_PACKAGE_bar_OPT_LEVEL = 3`
267                if let Some(rest) = env_key.strip_prefix(&env_prefix) {
268                    // `rest = bar_OPT_LEVEL`
269                    let part = rest.splitn(2, '_').next().unwrap();
270                    // `part = "bar"`
271                    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        // Assume that if we're deserializing a struct it exhaustively lists all
289        // possible fields on this key that we're *supposed* to use, so take
290        // this opportunity to warn about any keys that aren't recognized as
291        // fields and warn about them.
292        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        // If the caller is interested in a field which we can provide from
310        // the environment, get it from there.
311        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                // This distinguishes fields that share the same prefix.
319                // For example, when env_key is UNSTABLE_GITOXIDE_FETCH
320                // and field_key is UNSTABLE_GIT, the field shouldn't be
321                // added because `unstable.gitoxide.fetch` doesn't
322                // belong to `unstable.git` struct.
323                if nested_field.is_empty() || nested_field.starts_with('_') {
324                    fields.insert(KeyKind::Normal(field.to_string()));
325                }
326            }
327        }
328
329        // Add everything from the config table we're interested in that we
330        // haven't already provided via an environment variable
331        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        // Set this as the current key in the deserializer.
368        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        // Env vars that are a prefix of another with a dash/underscore cannot
379        // be supported by our serde implementation, so check for them here.
380        // Example:
381        //     CARGO_BUILD_TARGET
382        //     CARGO_BUILD_TARGET_DIR
383        // or
384        //     CARGO_PROFILE_DEV_DEBUG
385        //     CARGO_PROFILE_DEV_DEBUG_ASSERTIONS
386        // The `deserialize_option` method does not know the type of the field.
387        // If the type is an Option<struct> (like
388        // `profile.dev.build-override`), then it needs to check for env vars
389        // starting with CARGO_FOO_BAR_. This is a problem for keys like
390        // CARGO_BUILD_TARGET because checking for a prefix would incorrectly
391        // match CARGO_BUILD_TARGET_DIR. `deserialize_option` would have no
392        // choice but to call `visit_some()` which would then fail if
393        // CARGO_BUILD_TARGET isn't set. So we check for these prefixes and
394        // disallow them here.
395        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    /// The config key to the sequence.
429    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            // TODO: add `def` to error?
465            Some(val @ CV::String(..)) => {
466                // This might be a String or a Value<String>.
467                // ArrayItemDeserializer will handle figuring out which one it is.
468                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
476/// Source of data for [`ValueDeserializer`]
477enum ValueSource<'gctx> {
478    /// The deserializer used to actually deserialize a Value struct.
479    Deserializer {
480        de: Deserializer<'gctx>,
481        definition: Definition,
482    },
483    /// A [`ConfigValue`](CV).
484    ///
485    /// This is used for situations where you can't address a string via a TOML key,
486    /// such as a string inside an array.
487    /// The [`ConfigSeqAccess`] doesn't know if the type it should deserialize to
488    /// is a `String` or `Value<String>`,
489    /// so [`ArrayItemDeserializer`] needs to be able to handle both.
490    ConfigValue(CV),
491}
492
493/// This is a deserializer that deserializes into a `Value<T>` for
494/// configuration.
495///
496/// This is a special deserializer because it deserializes one of its struct
497/// fields into the location that this configuration value was defined in.
498///
499/// See more comments in `value.rs` for the protocol used here.
500struct 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        // Figure out where this key is defined.
508        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                    // Both, pick highest priority.
514                    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                // Assume it is an environment, even if the key is not set.
522                // This can happen for intermediate tables, like
523                // CARGO_FOO_BAR_* where `CARGO_FOO_BAR` is not set.
524                (_, 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 this is the first time around we deserialize the `value` field
573        // which is the actual deserializer
574        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        // ... otherwise we're deserializing the `definition` field, so we need
586        // to figure out where the field we just deserialized was defined at.
587        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/// A deserializer for individual [`ConfigValue`](CV) items in arrays
607///
608/// This deserializer is only implemented to handle deserializing a String
609/// inside a sequence (like `Vec<String>` or `Vec<Value<String>>`).
610/// `Value<String>` is handled by `deserialize_struct` in [`ValueDeserializer`],
611/// and the plain `String` is handled by all the other functions here.
612#[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        // Match on the magical struct name/field names that are passed in to
657        // detect when we're deserializing `Value<T>`.
658        //
659        // See more comments in `value.rs` for the protocol used here.
660        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
691/// A deserializer which takes two values and deserializes into a tuple of those
692/// two values. This is similar to types like `StrDeserializer` in upstream
693/// serde itself.
694struct 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}