indexmap_nostd/
serde_seq.rs

1//! Functions to serialize and deserialize an [`IndexMap`] as an ordered sequence.
2//!
3//! The default `serde` implementation serializes `IndexMap` as a normal map,
4//! but there is no guarantee that serialization formats will preserve the order
5//! of the key-value pairs. This module serializes `IndexMap` as a sequence of
6//! `(key, value)` elements instead, in order.
7//!
8//! This module may be used in a field attribute for derived implementations:
9//!
10//! ```
11//! # use indexmap_nostd::IndexMap;
12//! # use serde_derive::{Deserialize, Serialize};
13//! #[derive(Deserialize, Serialize)]
14//! struct Data {
15//!     #[serde(with = "indexmap_nostd::serde_seq")]
16//!     map: IndexMap<i32, u64>,
17//!     // ...
18//! }
19//! ```
20//!
21//! Requires crate feature `"serde"`.
22
23use crate::IndexMap;
24use core::fmt::{self, Formatter};
25use core::marker::PhantomData;
26use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
27use serde::ser::{Serialize, Serializer};
28
29/// Serializes an [`IndexMap`] as an ordered sequence.
30///
31/// This function may be used in a field attribute for deriving `Serialize`:
32///
33/// ```
34/// # use indexmap_nostd::IndexMap;
35/// # use serde_derive::Serialize;
36/// #[derive(Serialize)]
37/// struct Data {
38///     #[serde(serialize_with = "indexmap_nostd::serde_seq::serialize")]
39///     map: IndexMap<i32, u64>,
40///     // ...
41/// }
42/// ```
43///
44/// Requires crate feature `"serde"`.
45pub fn serialize<K, V, T>(map: &IndexMap<K, V>, serializer: T) -> Result<T::Ok, T::Error>
46where
47    K: Serialize + Ord,
48    V: Serialize,
49    T: Serializer,
50{
51    serializer.collect_seq(map)
52}
53
54/// Visitor to deserialize a *sequenced* [`IndexMap`].
55struct SeqVisitor<K, V>(PhantomData<(K, V)>);
56
57impl<'de, K, V> Visitor<'de> for SeqVisitor<K, V>
58where
59    K: Deserialize<'de> + Ord + Clone,
60    V: Deserialize<'de>,
61{
62    type Value = IndexMap<K, V>;
63
64    fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
65        write!(formatter, "a sequenced map")
66    }
67
68    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
69    where
70        A: SeqAccess<'de>,
71    {
72        let capacity = seq.size_hint().unwrap_or(0);
73        let mut map = IndexMap::with_capacity(capacity);
74        while let Some((key, value)) = seq.next_element()? {
75            map.insert(key, value);
76        }
77        Ok(map)
78    }
79}
80
81/// Deserializes an [`IndexMap`] from an ordered sequence.
82///
83/// This function may be used in a field attribute for deriving `Deserialize`:
84///
85/// ```
86/// # use indexmap_nostd::IndexMap;
87/// # use serde_derive::Deserialize;
88/// #[derive(Deserialize)]
89/// struct Data {
90///     #[serde(deserialize_with = "indexmap_nostd::serde_seq::deserialize")]
91///     map: IndexMap<i32, u64>,
92///     // ...
93/// }
94/// ```
95///
96/// Requires crate feature `"serde"`.
97pub fn deserialize<'de, D, K, V>(deserializer: D) -> Result<IndexMap<K, V>, D::Error>
98where
99    D: Deserializer<'de>,
100    K: Deserialize<'de> + Ord + Clone,
101    V: Deserialize<'de>,
102{
103    deserializer.deserialize_seq(SeqVisitor(PhantomData))
104}