Crates.io | serde-untagged |
lib.rs | serde-untagged |
version | 0.1.6 |
source | src |
created_at | 2023-08-27 22:39:10.140845 |
updated_at | 2024-05-14 17:18:48.18058 |
description | Serde `Visitor` implementation for deserializing untagged enums |
homepage | |
repository | https://github.com/dtolnay/serde-untagged |
max_upload_size | |
id | 956410 |
size | 75,482 |
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:
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>,
}
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)
}
}