]>
Commit | Line | Data |
---|---|---|
5869c6ff XL |
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::serde_seq")] | |
16 | //! map: IndexMap<i32, u64>, | |
17 | //! // ... | |
18 | //! } | |
19 | //! ``` | |
20 | //! | |
21 | //! Requires crate feature `"serde"` or `"serde-1"` | |
22 | ||
23 | use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; | |
24 | use serde::ser::{Serialize, Serializer}; | |
25 | ||
26 | use core::fmt::{self, Formatter}; | |
27 | use core::hash::{BuildHasher, Hash}; | |
28 | use core::marker::PhantomData; | |
29 | ||
30 | use crate::IndexMap; | |
31 | ||
32 | /// Serializes an `IndexMap` as an ordered sequence. | |
33 | /// | |
34 | /// This function may be used in a field attribute for deriving `Serialize`: | |
35 | /// | |
36 | /// ``` | |
37 | /// # use indexmap::IndexMap; | |
38 | /// # use serde_derive::Serialize; | |
39 | /// #[derive(Serialize)] | |
40 | /// struct Data { | |
41 | /// #[serde(serialize_with = "indexmap::serde_seq::serialize")] | |
42 | /// map: IndexMap<i32, u64>, | |
43 | /// // ... | |
44 | /// } | |
45 | /// ``` | |
46 | /// | |
47 | /// Requires crate feature `"serde"` or `"serde-1"` | |
48 | pub fn serialize<K, V, S, T>(map: &IndexMap<K, V, S>, serializer: T) -> Result<T::Ok, T::Error> | |
49 | where | |
50 | K: Serialize + Hash + Eq, | |
51 | V: Serialize, | |
52 | S: BuildHasher, | |
53 | T: Serializer, | |
54 | { | |
55 | serializer.collect_seq(map) | |
56 | } | |
57 | ||
58 | /// Visitor to deserialize a *sequenced* `IndexMap` | |
59 | struct SeqVisitor<K, V, S>(PhantomData<(K, V, S)>); | |
60 | ||
61 | impl<'de, K, V, S> Visitor<'de> for SeqVisitor<K, V, S> | |
62 | where | |
63 | K: Deserialize<'de> + Eq + Hash, | |
64 | V: Deserialize<'de>, | |
65 | S: Default + BuildHasher, | |
66 | { | |
67 | type Value = IndexMap<K, V, S>; | |
68 | ||
69 | fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { | |
70 | write!(formatter, "a sequenced map") | |
71 | } | |
72 | ||
73 | fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> | |
74 | where | |
75 | A: SeqAccess<'de>, | |
76 | { | |
77 | let capacity = seq.size_hint().unwrap_or(0); | |
78 | let mut map = IndexMap::with_capacity_and_hasher(capacity, S::default()); | |
79 | ||
80 | while let Some((key, value)) = seq.next_element()? { | |
81 | map.insert(key, value); | |
82 | } | |
83 | ||
84 | Ok(map) | |
85 | } | |
86 | } | |
87 | ||
88 | /// Deserializes an `IndexMap` from an ordered sequence. | |
89 | /// | |
90 | /// This function may be used in a field attribute for deriving `Deserialize`: | |
91 | /// | |
92 | /// ``` | |
93 | /// # use indexmap::IndexMap; | |
94 | /// # use serde_derive::Deserialize; | |
95 | /// #[derive(Deserialize)] | |
96 | /// struct Data { | |
97 | /// #[serde(deserialize_with = "indexmap::serde_seq::deserialize")] | |
98 | /// map: IndexMap<i32, u64>, | |
99 | /// // ... | |
100 | /// } | |
101 | /// ``` | |
102 | /// | |
103 | /// Requires crate feature `"serde"` or `"serde-1"` | |
104 | pub fn deserialize<'de, D, K, V, S>(deserializer: D) -> Result<IndexMap<K, V, S>, D::Error> | |
105 | where | |
106 | D: Deserializer<'de>, | |
107 | K: Deserialize<'de> + Eq + Hash, | |
108 | V: Deserialize<'de>, | |
109 | S: Default + BuildHasher, | |
110 | { | |
111 | deserializer.deserialize_seq(SeqVisitor(PhantomData)) | |
112 | } |