#
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}