#
cargo/util/context/
de.rs

    1//! Support for deserializing configuration via `serde`
    2
    3use crate::util::context::value;
    4use crate::util::context::{ConfigError, ConfigKey, GlobalContext};
    5use crate::util::context::{ConfigValue as CV, Definition, Value};
    6use serde::{de, de::IntoDeserializer};
    7use std::collections::HashSet;
    8use std::vec;
    9
    10/// Serde deserializer used to convert config values to a target type using
    11/// [`GlobalContext::get`].
    12#[derive(Clone)]
    13pub(super) struct Deserializer<'gctx> {
    14    pub(super) gctx: &'gctx GlobalContext,
    15    /// The current key being deserialized.
    16    pub(super) key: ConfigKey,
    17    /// Whether or not this key part is allowed to be an inner table. For
    18    /// example, `profile.dev.build-override` needs to check if
    19    /// `CARGO_PROFILE_DEV_BUILD_OVERRIDE_` prefixes exist. But
    20    /// `CARGO_BUILD_TARGET` should not check for prefixes because it would
    21    /// collide with `CARGO_BUILD_TARGET_DIR`. See `ConfigMapAccess` for
    22    /// details.
    23    pub(super) env_prefix_ok: bool,
    24}
    25
    26macro_rules! deserialize_method {
    27    ($method:ident, $visit:ident, $getter:ident) => {
    28        fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    29        where
    30            V: de::Visitor<'de>,
    31        {
    32            let v = self
    33                .gctx
    34                .$getter(&self.key)?
    35                .ok_or_else(|| ConfigError::missing(&self.key))?;
    36            let Value { val, definition } = v;
    37            let res: Result<V::Value, ConfigError> = visitor.$visit(val);
    38            res.map_err(|e| e.with_key_context(&self.key, Some(definition)))
    39        }
    40    };
    41}
    42
    43impl<'de, 'gctx> de::Deserializer<'de> for Deserializer<'gctx> {
    44    type Error = ConfigError;
    45
    46    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    47    where
    48        V: de::Visitor<'de>,
    49    {
    50        let cv = self.gctx.get_cv_with_env(&self.key)?;
    51        if let Some(cv) = cv {
    52            let res: (Result<V::Value, ConfigError>, Definition) = match cv {
    53                CV::Integer(i, def) => (visitor.visit_i64(i), def),
    54                CV::String(s, def) => (visitor.visit_string(s), def),
    55                CV::List(_, def) => (visitor.visit_seq(ConfigSeqAccess::new(self.clone())?), def),
    56                CV::Table(_, def) => (
    57                    visitor.visit_map(ConfigMapAccess::new_map(self.clone())?),
    58                    def,
    59                ),
    60                CV::Boolean(b, def) => (visitor.visit_bool(b), def),
    61            };
    62            let (res, def) = res;
    63            return res.map_err(|e| e.with_key_context(&self.key, Some(def)));
    64        }
    65
    66        // The effect here is the same as in `deserialize_option`.
    67        if self.gctx.has_key(&self.key, self.env_prefix_ok)? {
    68            return visitor.visit_some(self);
    69        }
    70
    71        Err(ConfigError::missing(&self.key))
    72    }
    73
    74    deserialize_method!(deserialize_bool, visit_bool, get_bool);
    75    deserialize_method!(deserialize_i8, visit_i64, get_integer);
    76    deserialize_method!(deserialize_i16, visit_i64, get_integer);
    77    deserialize_method!(deserialize_i32, visit_i64, get_integer);
    78    deserialize_method!(deserialize_i64, visit_i64, get_integer);
    79    deserialize_method!(deserialize_u8, visit_i64, get_integer);
    80    deserialize_method!(deserialize_u16, visit_i64, get_integer);
    81    deserialize_method!(deserialize_u32, visit_i64, get_integer);
    82    deserialize_method!(deserialize_u64, visit_i64, get_integer);
    83    deserialize_method!(deserialize_string, visit_string, get_string_priv);
    84
    85    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    86    where
    87        V: de::Visitor<'de>,
    88    {
    89        if self.gctx.has_key(&self.key, self.env_prefix_ok)? {
    90            visitor.visit_some(self)
    91        } else {
    92            // Treat missing values as `None`.
    93            visitor.visit_none()
    94        }
    95    }
    96
    97    fn deserialize_struct<V>(
    98        self,
    99        name: &'static str,
    100        fields: &'static [&'static str],
    101        visitor: V,
    102    ) -> Result<V::Value, Self::Error>
    103    where
    104        V: de::Visitor<'de>,
    105    {
    106        // Match on the magical struct name/field names that are passed in to
    107        // detect when we're deserializing `Value<T>`.
    108        //
    109        // See more comments in `value.rs` for the protocol used here.
    110        if name == value::NAME && fields == value::FIELDS {
    111            return visitor.visit_map(ValueDeserializer::new(self)?);
    112        }
    113        visitor.visit_map(ConfigMapAccess::new_struct(self, fields)?)
    114    }
    115
    116    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    117    where
    118        V: de::Visitor<'de>,
    119    {
    120        visitor.visit_map(ConfigMapAccess::new_map(self)?)
    121    }
    122
    123    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    124    where
    125        V: de::Visitor<'de>,
    126    {
    127        visitor.visit_seq(ConfigSeqAccess::new(self)?)
    128    }
    129
    130    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
    131    where
    132        V: de::Visitor<'de>,
    133    {
    134        visitor.visit_seq(ConfigSeqAccess::new(self)?)
    135    }
    136
    137    fn deserialize_tuple_struct<V>(
    138        self,
    139        _name: &'static str,
    140        _len: usize,
    141        visitor: V,
    142    ) -> Result<V::Value, Self::Error>
    143    where
    144        V: de::Visitor<'de>,
    145    {
    146        visitor.visit_seq(ConfigSeqAccess::new(self)?)
    147    }
    148
    149    fn deserialize_newtype_struct<V>(
    150        self,
    151        name: &'static str,
    152        visitor: V,
    153    ) -> Result<V::Value, Self::Error>
    154    where
    155        V: de::Visitor<'de>,
    156    {
    157        if name == "StringList" {
    158            let vals = self.gctx.get_list_or_string(&self.key)?;
    159            let vals: Vec<String> = vals.into_iter().map(|vd| vd.0).collect();
    160            visitor.visit_newtype_struct(vals.into_deserializer())
    161        } else {
    162            visitor.visit_newtype_struct(self)
    163        }
    164    }
    165
    166    fn deserialize_enum<V>(
    167        self,
    168        _name: &'static str,
    169        _variants: &'static [&'static str],
    170        visitor: V,
    171    ) -> Result<V::Value, Self::Error>
    172    where
    173        V: de::Visitor<'de>,
    174    {
    175        let value = self
    176            .gctx
    177            .get_string_priv(&self.key)?
    178            .ok_or_else(|| ConfigError::missing(&self.key))?;
    179
    180        let Value { val, definition } = value;
    181        visitor
    182            .visit_enum(val.into_deserializer())
    183            .map_err(|e: ConfigError| e.with_key_context(&self.key, Some(definition)))
    184    }
    185
    186    // These aren't really supported, yet.
    187    serde::forward_to_deserialize_any! {
    188        f32 f64 char str bytes
    189        byte_buf unit unit_struct
    190        identifier ignored_any
    191    }
    192}
    193
    194struct ConfigMapAccess<'gctx> {
    195    de: Deserializer<'gctx>,
    196    /// The fields that this map should deserialize.
    197    fields: Vec<KeyKind>,
    198    /// Current field being deserialized.
    199    field_index: usize,
    200}
    201
    202#[derive(Debug, PartialEq, Eq, Hash)]
    203enum KeyKind {
    204    Normal(String),
    205    CaseSensitive(String),
    206}
    207
    208impl<'gctx> ConfigMapAccess<'gctx> {
    209    fn new_map(de: Deserializer<'gctx>) -> Result<ConfigMapAccess<'gctx>, ConfigError> {
    210        let mut fields = Vec::new();
    211        if let Some(mut v) = de.gctx.get_table(&de.key)? {
    212            // `v: Value<HashMap<String, CV>>`
    213            for (key, _value) in v.val.drain() {
    214                fields.push(KeyKind::CaseSensitive(key));
    215            }
    216        }
    217        if de.gctx.cli_unstable().advanced_env {
    218            // `CARGO_PROFILE_DEV_PACKAGE_`
    219            let env_prefix = format!("{}_", de.key.as_env_key());
    220            for env_key in de.gctx.env_keys() {
    221                // `CARGO_PROFILE_DEV_PACKAGE_bar_OPT_LEVEL = 3`
    222                if let Some(rest) = env_key.strip_prefix(&env_prefix) {
    223                    // `rest = bar_OPT_LEVEL`
    224                    let part = rest.splitn(2, '_').next().unwrap();
    225                    // `part = "bar"`
    226                    fields.push(KeyKind::CaseSensitive(part.to_string()));
    227                }
    228            }
    229        }
    230        Ok(ConfigMapAccess {
    231            de,
    232            fields,
    233            field_index: 0,
    234        })
    235    }
    236
    237    fn new_struct(
    238        de: Deserializer<'gctx>,
    239        given_fields: &'static [&'static str],
    240    ) -> Result<ConfigMapAccess<'gctx>, ConfigError> {
    241        let table = de.gctx.get_table(&de.key)?;
    242
    243        // Assume that if we're deserializing a struct it exhaustively lists all
    244        // possible fields on this key that we're *supposed* to use, so take
    245        // this opportunity to warn about any keys that aren't recognized as
    246        // fields and warn about them.
    247        if let Some(v) = table.as_ref() {
    248            let unused_keys = v
    249                .val
    250                .iter()
    251                .filter(|(k, _v)| !given_fields.iter().any(|gk| gk == k));
    252            for (unused_key, unused_value) in unused_keys {
    253                de.gctx.shell().warn(format!(
    254                    "unused config key `{}.{}` in `{}`",
    255                    de.key,
    256                    unused_key,
    257                    unused_value.definition()
    258                ))?;
    259            }
    260        }
    261
    262        let mut fields = HashSet::new();
    263
    264        // If the caller is interested in a field which we can provide from
    265        // the environment, get it from there.
    266        for field in given_fields {
    267            let mut field_key = de.key.clone();
    268            field_key.push(field);
    269            for env_key in de.gctx.env_keys() {
    270                let Some(nested_field) = env_key.strip_prefix(field_key.as_env_key()) else {
    271                    continue;
    272                };
    273                // This distinguishes fields that share the same prefix.
    274                // For example, when env_key is UNSTABLE_GITOXIDE_FETCH
    275                // and field_key is UNSTABLE_GIT, the field shouldn't be
    276                // added because `unstable.gitoxide.fetch` doesn't
    277                // belong to `unstable.git` struct.
    278                if nested_field.is_empty() || nested_field.starts_with('_') {
    279                    fields.insert(KeyKind::Normal(field.to_string()));
    280                }
    281            }
    282        }
    283
    284        // Add everything from the config table we're interested in that we
    285        // haven't already provided via an environment variable
    286        if let Some(v) = table {
    287            for key in v.val.keys() {
    288                fields.insert(KeyKind::Normal(key.clone()));
    289            }
    290        }
    291
    292        Ok(ConfigMapAccess {
    293            de,
    294            fields: fields.into_iter().collect(),
    295            field_index: 0,
    296        })
    297    }
    298}
    299
    300impl<'de, 'gctx> de::MapAccess<'de> for ConfigMapAccess<'gctx> {
    301    type Error = ConfigError;
    302
    303    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
    304    where
    305        K: de::DeserializeSeed<'de>,
    306    {
    307        if self.field_index >= self.fields.len() {
    308            return Ok(None);
    309        }
    310        let field = match &self.fields[self.field_index] {
    311            KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),
    312        };
    313        seed.deserialize(field.into_deserializer()).map(Some)
    314    }
    315
    316    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
    317    where
    318        V: de::DeserializeSeed<'de>,
    319    {
    320        let field = &self.fields[self.field_index];
    321        self.field_index += 1;
    322        // Set this as the current key in the deserializer.
    323        let field = match field {
    324            KeyKind::Normal(field) => {
    325                self.de.key.push(field);
    326                field
    327            }
    328            KeyKind::CaseSensitive(field) => {
    329                self.de.key.push_sensitive(field);
    330                field
    331            }
    332        };
    333        // Env vars that are a prefix of another with a dash/underscore cannot
    334        // be supported by our serde implementation, so check for them here.
    335        // Example:
    336        //     CARGO_BUILD_TARGET
    337        //     CARGO_BUILD_TARGET_DIR
    338        // or
    339        //     CARGO_PROFILE_DEV_DEBUG
    340        //     CARGO_PROFILE_DEV_DEBUG_ASSERTIONS
    341        // The `deserialize_option` method does not know the type of the field.
    342        // If the type is an Option<struct> (like
    343        // `profile.dev.build-override`), then it needs to check for env vars
    344        // starting with CARGO_FOO_BAR_. This is a problem for keys like
    345        // CARGO_BUILD_TARGET because checking for a prefix would incorrectly
    346        // match CARGO_BUILD_TARGET_DIR. `deserialize_option` would have no
    347        // choice but to call `visit_some()` which would then fail if
    348        // CARGO_BUILD_TARGET isn't set. So we check for these prefixes and
    349        // disallow them here.
    350        let env_prefix = format!("{}_", field).replace('-', "_");
    351        let env_prefix_ok = !self.fields.iter().any(|field| {
    352            let field = match field {
    353                KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),
    354            };
    355            field.replace('-', "_").starts_with(&env_prefix)
    356        });
    357
    358        let result = seed
    359            .deserialize(Deserializer {
    360                gctx: self.de.gctx,
    361                key: self.de.key.clone(),
    362                env_prefix_ok,
    363            })
    364            .map_err(|e| {
    365                if !e.is_missing_field() {
    366                    return e;
    367                }
    368                e.with_key_context(
    369                    &self.de.key,
    370                    self.de
    371                        .gctx
    372                        .get_cv_with_env(&self.de.key)
    373                        .ok()
    374                        .and_then(|cv| cv.map(|cv| cv.get_definition().clone())),
    375                )
    376            });
    377        self.de.key.pop();
    378        result
    379    }
    380}
    381
    382struct ConfigSeqAccess {
    383    list_iter: vec::IntoIter<(String, Definition)>,
    384}
    385
    386impl ConfigSeqAccess {
    387    fn new(de: Deserializer<'_>) -> Result<ConfigSeqAccess, ConfigError> {
    388        let mut res = Vec::new();
    389        if let Some(v) = de.gctx._get_list(&de.key)? {
    390            res.extend(v.val);
    391        }
    392
    393        de.gctx.get_env_list(&de.key, &mut res)?;
    394
    395        Ok(ConfigSeqAccess {
    396            list_iter: res.into_iter(),
    397        })
    398    }
    399}
    400
    401impl<'de> de::SeqAccess<'de> for ConfigSeqAccess {
    402    type Error = ConfigError;
    403
    404    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
    405    where
    406        T: de::DeserializeSeed<'de>,
    407    {
    408        match self.list_iter.next() {
    409            // TODO: add `def` to error?
    410            Some((value, def)) => {
    411                // This might be a String or a Value<String>.
    412                // ValueDeserializer will handle figuring out which one it is.
    413                let maybe_value_de = ValueDeserializer::new_with_string(value, def);
    414                seed.deserialize(maybe_value_de).map(Some)
    415            }
    416            None => Ok(None),
    417        }
    418    }
    419}
    420
    421/// This is a deserializer that deserializes into a `Value<T>` for
    422/// configuration.
    423///
    424/// This is a special deserializer because it deserializes one of its struct
    425/// fields into the location that this configuration value was defined in.
    426///
    427/// See more comments in `value.rs` for the protocol used here.
    428struct ValueDeserializer<'gctx> {
    429    hits: u32,
    430    definition: Definition,
    431    /// The deserializer, used to actually deserialize a Value struct.
    432    /// This is `None` if deserializing a string.
    433    de: Option<Deserializer<'gctx>>,
    434    /// A string value to deserialize.
    435    ///
    436    /// This is used for situations where you can't address a string via a
    437    /// TOML key, such as a string inside an array. The `ConfigSeqAccess`
    438    /// doesn't know if the type it should deserialize to is a `String` or
    439    /// `Value<String>`, so `ValueDeserializer` needs to be able to handle
    440    /// both.
    441    str_value: Option<String>,
    442}
    443
    444impl<'gctx> ValueDeserializer<'gctx> {
    445    fn new(de: Deserializer<'gctx>) -> Result<ValueDeserializer<'gctx>, ConfigError> {
    446        // Figure out where this key is defined.
    447        let definition = {
    448            let env = de.key.as_env_key();
    449            let env_def = Definition::Environment(env.to_string());
    450            match (de.gctx.env.contains_key(env), de.gctx.get_cv(&de.key)?) {
    451                (true, Some(cv)) => {
    452                    // Both, pick highest priority.
    453                    if env_def.is_higher_priority(cv.definition()) {
    454                        env_def
    455                    } else {
    456                        cv.definition().clone()
    457                    }
    458                }
    459                (false, Some(cv)) => cv.definition().clone(),
    460                // Assume it is an environment, even if the key is not set.
    461                // This can happen for intermediate tables, like
    462                // CARGO_FOO_BAR_* where `CARGO_FOO_BAR` is not set.
    463                (_, None) => env_def,
    464            }
    465        };
    466        Ok(ValueDeserializer {
    467            hits: 0,
    468            definition,
    469            de: Some(de),
    470            str_value: None,
    471        })
    472    }
    473
    474    fn new_with_string(s: String, definition: Definition) -> ValueDeserializer<'gctx> {
    475        ValueDeserializer {
    476            hits: 0,
    477            definition,
    478            de: None,
    479            str_value: Some(s),
    480        }
    481    }
    482}
    483
    484impl<'de, 'gctx> de::MapAccess<'de> for ValueDeserializer<'gctx> {
    485    type Error = ConfigError;
    486
    487    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
    488    where
    489        K: de::DeserializeSeed<'de>,
    490    {
    491        self.hits += 1;
    492        match self.hits {
    493            1 => seed
    494                .deserialize(value::VALUE_FIELD.into_deserializer())
    495                .map(Some),
    496            2 => seed
    497                .deserialize(value::DEFINITION_FIELD.into_deserializer())
    498                .map(Some),
    499            _ => Ok(None),
    500        }
    501    }
    502
    503    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
    504    where
    505        V: de::DeserializeSeed<'de>,
    506    {
    507        // If this is the first time around we deserialize the `value` field
    508        // which is the actual deserializer
    509        if self.hits == 1 {
    510            if let Some(de) = &self.de {
    511                return seed
    512                    .deserialize(de.clone())
    513                    .map_err(|e| e.with_key_context(&de.key, Some(self.definition.clone())));
    514            } else {
    515                return seed
    516                    .deserialize(self.str_value.as_ref().unwrap().clone().into_deserializer());
    517            }
    518        }
    519
    520        // ... otherwise we're deserializing the `definition` field, so we need
    521        // to figure out where the field we just deserialized was defined at.
    522        match &self.definition {
    523            Definition::Path(path) => {
    524                seed.deserialize(Tuple2Deserializer(0i32, path.to_string_lossy()))
    525            }
    526            Definition::Environment(env) => {
    527                seed.deserialize(Tuple2Deserializer(1i32, env.as_str()))
    528            }
    529            Definition::Cli(path) => {
    530                let s = path
    531                    .as_ref()
    532                    .map(|p| p.to_string_lossy())
    533                    .unwrap_or_default();
    534                seed.deserialize(Tuple2Deserializer(2i32, s))
    535            }
    536        }
    537    }
    538}
    539
    540// Deserializer is only implemented to handle deserializing a String inside a
    541// sequence (like `Vec<String>` or `Vec<Value<String>>`). `Value<String>` is
    542// handled by deserialize_struct, and the plain `String` is handled by all the
    543// other functions here.
    544impl<'de, 'gctx> de::Deserializer<'de> for ValueDeserializer<'gctx> {
    545    type Error = ConfigError;
    546
    547    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    548    where
    549        V: de::Visitor<'de>,
    550    {
    551        visitor.visit_str(&self.str_value.expect("string expected"))
    552    }
    553
    554    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    555    where
    556        V: de::Visitor<'de>,
    557    {
    558        visitor.visit_string(self.str_value.expect("string expected"))
    559    }
    560
    561    fn deserialize_struct<V>(
    562        self,
    563        name: &'static str,
    564        fields: &'static [&'static str],
    565        visitor: V,
    566    ) -> Result<V::Value, Self::Error>
    567    where
    568        V: de::Visitor<'de>,
    569    {
    570        // Match on the magical struct name/field names that are passed in to
    571        // detect when we're deserializing `Value<T>`.
    572        //
    573        // See more comments in `value.rs` for the protocol used here.
    574        if name == value::NAME && fields == value::FIELDS {
    575            return visitor.visit_map(self);
    576        }
    577        unimplemented!("only strings and Value can be deserialized from a sequence");
    578    }
    579
    580    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    581    where
    582        V: de::Visitor<'de>,
    583    {
    584        visitor.visit_string(self.str_value.expect("string expected"))
    585    }
    586
    587    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    588    where
    589        V: de::Visitor<'de>,
    590    {
    591        visitor.visit_unit()
    592    }
    593
    594    serde::forward_to_deserialize_any! {
    595        i8 i16 i32 i64
    596        u8 u16 u32 u64
    597        option
    598        newtype_struct seq tuple tuple_struct map enum bool
    599        f32 f64 char bytes
    600        byte_buf unit unit_struct
    601        identifier
    602    }
    603}
    604
    605/// A deserializer which takes two values and deserializes into a tuple of those
    606/// two values. This is similar to types like `StrDeserializer` in upstream
    607/// serde itself.
    608struct Tuple2Deserializer<T, U>(T, U);
    609
    610impl<'de, T, U> de::Deserializer<'de> for Tuple2Deserializer<T, U>
    611where
    612    T: IntoDeserializer<'de, ConfigError>,
    613    U: IntoDeserializer<'de, ConfigError>,
    614{
    615    type Error = ConfigError;
    616
    617    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, ConfigError>
    618    where
    619        V: de::Visitor<'de>,
    620    {
    621        struct SeqVisitor<T, U> {
    622            first: Option<T>,
    623            second: Option<U>,
    624        }
    625        impl<'de, T, U> de::SeqAccess<'de> for SeqVisitor<T, U>
    626        where
    627            T: IntoDeserializer<'de, ConfigError>,
    628            U: IntoDeserializer<'de, ConfigError>,
    629        {
    630            type Error = ConfigError;
    631            fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
    632            where
    633                K: de::DeserializeSeed<'de>,
    634            {
    635                if let Some(first) = self.first.take() {
    636                    return seed.deserialize(first.into_deserializer()).map(Some);
    637                }
    638                if let Some(second) = self.second.take() {
    639                    return seed.deserialize(second.into_deserializer()).map(Some);
    640                }
    641                Ok(None)
    642            }
    643        }
    644
    645        visitor.visit_seq(SeqVisitor {
    646            first: Some(self.0),
    647            second: Some(self.1),
    648        })
    649    }
    650
    651    serde::forward_to_deserialize_any! {
    652        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
    653        bytes byte_buf map struct option unit newtype_struct
    654        ignored_any unit_struct tuple_struct tuple enum identifier
    655    }
    656}