<commit_before>//! Support for deserializing configuration via `serde`

use crate::util::config::value;
use crate::util::config::{Config, ConfigError, ConfigKey};
use crate::util::config::{ConfigValue as CV, Definition, Value};
use serde::{de, de::IntoDeserializer};
use std::vec;

/// Serde deserializer used to convert config values to a target type using
/// `Config::get`.
#[derive(Clone)]
pub(super) struct Deserializer<'config> {
    pub(super) config: &'config Config,
    /// The current key being deserialized.
    pub(super) key: ConfigKey,
    /// Whether or not this key part is allowed to be an inner table. For
    /// example, `profile.dev.build-override` needs to check if
    /// CARGO_PROFILE_DEV_BUILD_OVERRIDE_ prefixes exist. But
    /// CARGO_BUILD_TARGET should not check for prefixes because it would
    /// collide with CARGO_BUILD_TARGET_DIR. See `ConfigMapAccess` for
    /// details.
    pub(super) env_prefix_ok: bool,
}

macro_rules! deserialize_method {
    ($method:ident, $visit:ident, $getter:ident) => {
        fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
        where
            V: de::Visitor<'de>,
        {
            let v = self.config.$getter(&self.key)?.ok_or_else(||
                ConfigError::missing(&self.key))?;
            let Value{val, definition} = v;
            let res: Result<V::Value, ConfigError> = visitor.$visit(val);
            res.map_err(|e| e.with_key_context(&self.key, definition))
        }
    }
}

impl<'de, 'config> de::Deserializer<'de> for Deserializer<'config> {
    type Error = ConfigError;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        // Determine if value comes from env, cli, or file, and merge env if
        // possible.
        let cv = self.config.get_cv(&self.key)?;
        let env = self.config.env.get(self.key.as_env_key());
        let env_def = Definition::Environment(self.key.as_env_key().to_string());
        let use_env = match (&cv, env) {
            (Some(cv), Some(_)) => env_def.is_higher_priority(cv.definition()),
            (None, Some(_)) => true,
            _ => false,
        };
        if use_env {
            // Future note: If you ever need to deserialize a non-self describing
            // map type, this should implement a starts_with check (similar to how
            // ConfigMapAccess does).<commit_msg>Update for nightly rustfmt.<commit_after>//! Support for deserializing configuration via `serde`

use crate::util::config::value;
use crate::util::config::{Config, ConfigError, ConfigKey};
use crate::util::config::{ConfigValue as CV, Definition, Value};
use serde::{de, de::IntoDeserializer};
use std::vec;

/// Serde deserializer used to convert config values to a target type using
/// `Config::get`.
#[derive(Clone)]
pub(super) struct Deserializer<'config> {
    pub(super) config: &'config Config,
    /// The current key being deserialized.
    pub(super) key: ConfigKey,
    /// Whether or not this key part is allowed to be an inner table. For
    /// example, `profile.dev.build-override` needs to check if
    /// CARGO_PROFILE_DEV_BUILD_OVERRIDE_ prefixes exist. But
    /// CARGO_BUILD_TARGET should not check for prefixes because it would
    /// collide with CARGO_BUILD_TARGET_DIR. See `ConfigMapAccess` for
    /// details.
    pub(super) env_prefix_ok: bool,
}

macro_rules! deserialize_method {
    ($method:ident, $visit:ident, $getter:ident) => {
        fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
        where
            V: de::Visitor<'de>,
        {
            let v = self
                .config
                .$getter(&self.key)?
                .ok_or_else(|| ConfigError::missing(&self.key))?;
            let Value { val, definition } = v;
            let res: Result<V::Value, ConfigError> = visitor.$visit(val);
            res.map_err(|e| e.with_key_context(&self.key, definition))
        }
    };
}

impl<'de, 'config> de::Deserializer<'de> for Deserializer<'config> {
    type Error = ConfigError;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        // Determine if value comes from env, cli, or file, and merge env if
        // possible.
        let cv = self.config.get_cv(&self.key)?;
        let env = self.config.env.get(self.key.as_env_key());
        let env_def = Definition::Environment(self.key.as_env_key().to_string());
        let use_env = match (&cv, env) {
            (Some(cv), Some(_)) => env_def.is_higher_priority(cv.definition()),
            (None, Some(_)) => true,
            _ => false,
        };
        if use_env {
            // Future note: If you ever need to deserialize a non-self describing
            // map type, this should implement a starts_with check (similar to how
            // ConfigMapAccess does).
{'fraction_non_alphanumeric': 0.13807106598984772, 'fraction_numerical': 0.0, 'mean_word_length': 2.717735849056604, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '787133', 'n_tokens_mistral': 1497, 'n_tokens_neox': 1497, 'n_words': 414}