indexmap/map/
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::IndexMap;
12//! # use serde_derive::{Deserialize, Serialize};
13//! #[derive(Deserialize, Serialize)]
14//! struct Data {
15//!     #[serde(with = "indexmap::map::serde_seq")]
16//!     map: IndexMap<i32, u64>,
17//!     // ...
18//! }
19//! ```
20
21use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
22use serde::ser::{Serialize, Serializer};
23
24use core::fmt::{self, Formatter};
25use core::hash::{BuildHasher, Hash};
26use core::marker::PhantomData;
27
28use crate::map::Slice as MapSlice;
29use crate::serde::cautious_capacity;
30use crate::set::Slice as SetSlice;
31use crate::IndexMap;
32
33/// Serializes a [`map::Slice`][MapSlice] as an ordered sequence.
34///
35/// This behaves like [`crate::map::serde_seq`] for `IndexMap`, serializing a sequence
36/// of `(key, value)` pairs, rather than as a map that might not preserve order.
37impl<K, V> Serialize for MapSlice<K, V>
38where
39    K: Serialize,
40    V: Serialize,
41{
42    fn serialize<T>(&self, serializer: T) -> Result<T::Ok, T::Error>
43    where
44        T: Serializer,
45    {
46        serializer.collect_seq(self)
47    }
48}
49
50/// Serializes a [`set::Slice`][SetSlice] as an ordered sequence.
51impl<T> Serialize for SetSlice<T>
52where
53    T: Serialize,
54{
55    fn serialize<Se>(&self, serializer: Se) -> Result<Se::Ok, Se::Error>
56    where
57        Se: Serializer,
58    {
59        serializer.collect_seq(self)
60    }
61}
62
63/// Serializes an [`IndexMap`] as an ordered sequence.
64///
65/// This function may be used in a field attribute for deriving [`Serialize`]:
66///
67/// ```
68/// # use indexmap::IndexMap;
69/// # use serde_derive::Serialize;
70/// #[derive(Serialize)]
71/// struct Data {
72///     #[serde(serialize_with = "indexmap::map::serde_seq::serialize")]
73///     map: IndexMap<i32, u64>,
74///     // ...
75/// }
76/// ```
77pub fn serialize<K, V, S, T>(map: &IndexMap<K, V, S>, serializer: T) -> Result<T::Ok, T::Error>
78where
79    K: Serialize,
80    V: Serialize,
81    T: Serializer,
82{
83    serializer.collect_seq(map)
84}
85
86/// Visitor to deserialize a *sequenced* `IndexMap`
87struct SeqVisitor<K, V, S>(PhantomData<(K, V, S)>);
88
89impl<'de, K, V, S> Visitor<'de> for SeqVisitor<K, V, S>
90where
91    K: Deserialize<'de> + Eq + Hash,
92    V: Deserialize<'de>,
93    S: Default + BuildHasher,
94{
95    type Value = IndexMap<K, V, S>;
96
97    fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
98        write!(formatter, "a sequenced map")
99    }
100
101    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
102    where
103        A: SeqAccess<'de>,
104    {
105        let capacity = cautious_capacity::<K, V>(seq.size_hint());
106        let mut map = IndexMap::with_capacity_and_hasher(capacity, S::default());
107
108        while let Some((key, value)) = seq.next_element()? {
109            map.insert(key, value);
110        }
111
112        Ok(map)
113    }
114}
115
116/// Deserializes an [`IndexMap`] from an ordered sequence.
117///
118/// This function may be used in a field attribute for deriving [`Deserialize`]:
119///
120/// ```
121/// # use indexmap::IndexMap;
122/// # use serde_derive::Deserialize;
123/// #[derive(Deserialize)]
124/// struct Data {
125///     #[serde(deserialize_with = "indexmap::map::serde_seq::deserialize")]
126///     map: IndexMap<i32, u64>,
127///     // ...
128/// }
129/// ```
130pub fn deserialize<'de, D, K, V, S>(deserializer: D) -> Result<IndexMap<K, V, S>, D::Error>
131where
132    D: Deserializer<'de>,
133    K: Deserialize<'de> + Eq + Hash,
134    V: Deserialize<'de>,
135    S: Default + BuildHasher,
136{
137    deserializer.deserialize_seq(SeqVisitor(PhantomData))
138}