EnumMap

Struct EnumMap 

Source
pub struct EnumMap;
Expand description

Represent a list of enum values as a map.

This only works if the enum uses the default externally tagged representation. Other enum representations are not supported.

serde data formats often represent externally tagged enums as maps with a single key. The key is the enum variant name, and the value is the variant value. Sometimes a map with multiple keys should be treated like a list of enum values.

§Examples

§JSON Map with multiple keys

use serde_with::{serde_as, EnumMap};

#[derive(Serialize, Deserialize)]
enum EnumValue {
    Int(i32),
    String(String),
    Unit,
    Tuple(i32, String, bool),
    Struct {
        a: i32,
        b: String,
        c: bool,
    },
}

#[serde_as]
#[derive(Serialize, Deserialize)]
struct VecEnumValues (
    #[serde_as(as = "EnumMap")]
    Vec<EnumValue>,
);

// ---

// This will serialize this list of values
let values = VecEnumValues(vec![
    EnumValue::Int(123),
    EnumValue::String("FooBar".to_string()),
    EnumValue::Int(456),
    EnumValue::String("XXX".to_string()),
    EnumValue::Unit,
    EnumValue::Tuple(1, "Middle".to_string(), false),
    EnumValue::Struct {
        a: 666,
        b: "BBB".to_string(),
        c: true,
    },
]);

// into this JSON map
// Duplicate keys are emitted for identical enum variants.
let expected =
r#"{
  "Int": 123,
  "String": "FooBar",
  "Int": 456,
  "String": "XXX",
  "Unit": null,
  "Tuple": [
    1,
    "Middle",
    false
  ],
  "Struct": {
    "a": 666,
    "b": "BBB",
    "c": true
  }
}"#;

// Both serialization and deserialization work flawlessly.
let serialized = serde_json::to_string_pretty(&values).unwrap();
assert_eq!(expected, serialized);
let deserialized: VecEnumValues = serde_json::from_str(&serialized).unwrap();
assert_eq!(values, deserialized);

§XML structure with varying keys

With serde_xml_rs tuple and struct variants are not supported since they fail to roundtrip. The enum may have such variants as long as they are not serialized or deserialized.

use serde_with::{serde_as, EnumMap};

#[derive(Serialize, Deserialize)]
enum EnumValue {
    Int(i32),
    String(String),
    Unit,
}

#[serde_as]
#[derive(Serialize, Deserialize)]
struct VecEnumValues {
    #[serde_as(as = "EnumMap")]
    vec: Vec<EnumValue>,
}

// ---

// This will serialize this list of values
let values = VecEnumValues {
    vec: vec![
        EnumValue::Int(123),
        EnumValue::String("FooBar".to_string()),
        EnumValue::Int(456),
        EnumValue::String("XXX".to_string()),
        EnumValue::Unit,
    ],
};

// into this XML document
// Duplicate keys are emitted for identical enum variants.
let expected = r#"
<?xml version="1.0" encoding="utf-8"?>
<VecEnumValues>
    <vec>
        <Int>123</Int>
        <String>FooBar</String>
        <Int>456</Int>
        <String>XXX</String>
        <Unit />
    </vec>
</VecEnumValues>"#
// Remove whitespace
.replace("    ", "")
.replace('\n', "");

// Both serialization and deserialization work flawlessly.
let serialized = serde_xml_rs::to_string(&values).unwrap();
assert_eq!(expected, serialized);
let deserialized: VecEnumValues = serde_xml_rs::from_str(&serialized).unwrap();
assert_eq!(values, deserialized);

Trait Implementations§

Source§

impl<'de, T> DeserializeAs<'de, Vec<T>> for EnumMap
where T: Deserialize<'de>,

Source§

fn deserialize_as<D>(deserializer: D) -> Result<Vec<T>, D::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer.
Source§

impl<T> SerializeAs<Vec<T>> for EnumMap
where T: Serialize,

Source§

fn serialize_as<S>(source: &Vec<T>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,

Serialize this value into the given Serde serializer.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.

Layout§

Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.

Size: 0 bytes