MCPcopy Index your code
hub / github.com/dtolnay/serde-untagged

github.com/dtolnay/serde-untagged @0.1.9

Chat with this repo
repository ↗ · DeepWiki ↗ · release 0.1.9 ↗ · + Follow
107 symbols 179 edges 9 files 2 documented · 2%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

serde-untagged

github crates.io docs.rs build status

This crate provides a Serde Visitor implementation that is useful for deserializing untagged enums.

[dependencies]
serde-untagged = "0.1"

Untagged enum Deserialize impls look like this:

use serde::de::{Deserialize, Deserializer};
use serde_untagged::UntaggedEnumVisitor;

impl<'de> Deserialize<'de> for $MyType {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        UntaggedEnumVisitor::new()
            /*
             *
             */
            .deserialize(deserializer)
    }
}

Inside the /* ... */, we list each type that the untagged enum needs to support deserializing from, giving a closure that turns the input into $MyType. The following types are supported:

  • bool
  • i8, i16, i32, i64, i128, u8, u16, u32, u64, u128
  • f32
  • f64
  • char
  • string
  • borrowed_str
  • bytes
  • borrowed_bytes
  • byte_buf
  • unit
  • seq
  • map

Example: string or struct

Cargo's http.ssl-version configuration supports deserialization from the following two representations:

[http]
ssl-version = "tlsv1.3"
[http]
ssl-version.min = "tlsv1.2"
ssl-version.max = "tlsv1.3"
use serde::de::{Deserialize, Deserializer};
use serde_derive::Deserialize;
use serde_untagged::UntaggedEnumVisitor;

pub enum SslVersionConfig {
    Single(String),
    Range(SslVersionConfigRange),
}

impl<'de> Deserialize<'de> for SslVersionConfig {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        UntaggedEnumVisitor::new()
            .string(|single| Ok(SslVersionConfig::Single(single.to_owned())))
            .map(|map| map.deserialize().map(SslVersionConfig::Range))
            .deserialize(deserializer)
    }
}

#[derive(Deserialize)]
pub struct SslVersionConfigRange {
    pub min: Option<String>,
    pub max: Option<String>,
}

Example: unit variant or bool

Cargo's LTO setting in profiles supports the 5 values false, true, "fat", "thin", and "off".

[profile.release]
lto = "thin"
use serde::de::{Deserialize, Deserializer, IntoDeserializer};
use serde_derive::Deserialize;
use serde_untagged::UntaggedEnumVisitor;

pub enum LinkTimeOptimization {
    Enabled(bool),
    Enum(LinkTimeOptimizationString),
}

impl<'de> Deserialize<'de> for LinkTimeOptimization {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        UntaggedEnumVisitor::new()
            .bool(|b| Ok(LinkTimeOptimization::Enabled(b)))
            .string(|string| {
                let de = string.into_deserializer();
                LinkTimeOptimizationString::deserialize(de).map(LinkTimeOptimization::Enum)
            })
            .deserialize(deserializer)
    }
}

#[derive(Deserialize)]
#[serde(rename = "lowercase")]
pub enum LinkTimeOptimizationString {
    Fat,
    Thin,
    Off,
}

Since lto = true means the same thing as lto = "fat" to Cargo, there are really only 4 distinct options. This type could be implemented alternatively as:

use serde::de::{Deserialize, Deserializer, Unexpected};
use serde_untagged::UntaggedEnumVisitor;

pub enum LinkTimeOptimization {
    ThinLocal,  // false
    Fat,        // true or "fat"
    Thin,       // "thin"
    Off,        // "off"
}

impl<'de> Deserialize<'de> for LinkTimeOptimization {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        UntaggedEnumVisitor::new()
            .bool(|b| match b {
                false => Ok(LinkTimeOptimization::ThinLocal),
                true => Ok(LinkTimeOptimization::Fat),
            })
            .string(|string| match string {
                "fat" => Ok(LinkTimeOptimization::Fat),
                "thin" => Ok(LinkTimeOptimization::Thin),
                "off" => Ok(LinkTimeOptimization::Off),
                _ => Err(serde::de::Error::invalid_value(
                    Unexpected::Str(string),
                    &r#""fat" or "thin" or "off""#,
                )),
            })
            .deserialize(deserializer)
    }
}

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Extension points exported contracts — how you extend this code

Integer (Interface)
(no doc) [1 implementers]
src/int.rs
ErasedDeserializeSeed (Interface)
(no doc) [1 implementers]
src/seed.rs
ErasedSeqAccess (Interface)
(no doc) [1 implementers]
src/seq.rs
ErasedMapAccess (Interface)
(no doc) [1 implementers]
src/map.rs
IntFrom (Interface)
(no doc) [1 implementers]
src/int.rs

Core symbols most depended-on inside this repo

push
called by 11
src/lib.rs
dispatch_integer
called by 10
src/int.rs
seq
called by 6
src/lib.rs
map
called by 6
src/lib.rs
bool
called by 3
src/lib.rs
take
called by 3
src/any.rs
i8
called by 2
src/lib.rs
visit_str
called by 2
src/lib.rs

Shape

Method 84
Class 7
Function 6
Enum 5
Interface 5

Languages

Rust100%

Modules by API surface

src/lib.rs54 symbols
src/error.rs16 symbols
src/map.rs10 symbols
src/seq.rs8 symbols
tests/test.rs7 symbols
src/int.rs5 symbols
src/any.rs4 symbols
src/seed.rs3 symbols

For agents

$ claude mcp add serde-untagged \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page