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}