ruma_serde/
empty.rs

1use std::fmt;
2
3use serde::{
4    de::{self, Deserialize},
5    Serialize,
6};
7
8#[derive(Clone, Debug, Serialize)]
9pub struct Empty {}
10
11impl<'de> Deserialize<'de> for Empty {
12    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
13    where
14        D: de::Deserializer<'de>,
15    {
16        struct EmptyMapVisitor;
17
18        impl<'de> de::Visitor<'de> for EmptyMapVisitor {
19            type Value = Empty;
20
21            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22                write!(f, "an object/map")
23            }
24
25            fn visit_map<A>(self, _map: A) -> Result<Self::Value, A::Error>
26            where
27                A: de::MapAccess<'de>,
28            {
29                Ok(Empty {})
30            }
31        }
32
33        deserializer.deserialize_map(EmptyMapVisitor)
34    }
35}
36
37/// Serde serialization and deserialization functions that map a `Vec<T>` to a
38/// `BTreeMap<T, Empty>`.
39///
40/// The Matrix spec sometimes specifies lists as hash maps so the list entries
41/// can be expanded with attributes without breaking compatibility. As that
42/// would be a breaking change for ruma's event types anyway, we convert them to
43/// `Vec`s for simplicity, using this module.
44///
45/// To be used as `#[serde(with = "vec_as_map_of_empty")]`.
46pub mod vec_as_map_of_empty {
47    use std::collections::BTreeMap;
48
49    use serde::{Deserialize, Deserializer, Serialize, Serializer};
50
51    use super::Empty;
52
53    /// Serialize the given `Vec<T>` as a map of `T => Empty`.
54    #[allow(clippy::ptr_arg)]
55    pub fn serialize<S, T>(vec: &Vec<T>, serializer: S) -> Result<S::Ok, S::Error>
56    where
57        S: Serializer,
58        T: Serialize + Eq + Ord,
59    {
60        // FIXME: Don't construct a temporary `BTreeMap`.
61        vec.iter().map(|v| (v, Empty {})).collect::<BTreeMap<_, _>>().serialize(serializer)
62    }
63
64    /// Deserialize an object and return the keys as a `Vec<T>`.
65    pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
66    where
67        D: Deserializer<'de>,
68        T: Deserialize<'de> + Eq + Ord,
69    {
70        // FIXME: Don't construct a temporary `BTreeMap`.
71        BTreeMap::<T, Empty>::deserialize(deserializer)
72            .map(|hashmap| hashmap.into_iter().map(|(k, _)| k).collect())
73    }
74}