7 releases
0.1.6 | May 14, 2024 |
---|---|
0.1.5 | Jan 2, 2024 |
0.1.4 | Dec 25, 2023 |
0.1.1 | Aug 28, 2023 |
0.0.0 |
|
#278 in Encoding
327,740 downloads per month
Used in 192 crates
(13 directly)
58KB
1K
SLoC
serde-untagged
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.
Dependencies
~255–480KB
~10K SLoC