|
| 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 | +} |
0 commit comments