tuple_vec_map/
lib.rs

1//! Deserializing maps to tuple-vecs.
2//!
3//! To use, just include a `Vec<(String, ...)>` in your struct instead of a `HashMap<String, ...>`
4//! and tag it with `#[serde(with = "tuple_vec_map")`:
5//!
6//! ```
7//! # extern crate serde;
8//! # #[macro_use] extern crate serde_derive;
9//! extern crate tuple_vec_map;
10//!
11//! #[derive(Serialize, Deserialize)]
12//! struct SomeData {
13//!     other_stuff: u32,
14//!     #[serde(with = "tuple_vec_map")]
15//!     inner_data: Vec<(String, String)>,
16//! }
17//! # fn main() {}
18//! ```
19//!
20//! That's it! Now your structure accepts an inner_data Map or JSON Object, and instead of making
21//! a HashMap for the data, the key/value pairs are simply collected into a Vec.
22//!
23//! ## Features
24//!
25//! To use without `std`, depend on `serde-tuple-vec-map` with `default-features = false`. This will still
26//! depend on the `alloc` crate, and requires Rust 1.36.0 or newer.
27#![cfg_attr(not(feature = "std"), no_std)]
28#![deny(missing_docs)]
29#![doc(html_root_url = "https://docs.rs/serde-tuple-vec-map/1.0.1")]
30
31extern crate serde;
32
33#[cfg(not(feature = "std"))]
34extern crate alloc;
35
36#[cfg(feature = "std")]
37mod core {
38    // this mirrors serde's setup for std/non-std.
39    pub use std::cmp;
40    pub use std::fmt;
41    pub use std::marker;
42}
43
44use core::marker::PhantomData;
45use core::{cmp, fmt};
46
47use serde::de::{MapAccess, Visitor};
48use serde::{Deserialize, Deserializer, Serialize, Serializer};
49
50#[cfg(not(feature = "std"))]
51use alloc::vec::Vec;
52
53struct TupleVecMapVisitor<K, V> {
54    marker: PhantomData<Vec<(K, V)>>,
55}
56
57impl<K, V> TupleVecMapVisitor<K, V> {
58    pub fn new() -> Self {
59        TupleVecMapVisitor {
60            marker: PhantomData,
61        }
62    }
63}
64
65impl<'de, K, V> Visitor<'de> for TupleVecMapVisitor<K, V>
66where
67    K: Deserialize<'de>,
68    V: Deserialize<'de>,
69{
70    type Value = Vec<(K, V)>;
71
72    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
73        formatter.write_str("a map")
74    }
75
76    #[inline]
77    fn visit_unit<E>(self) -> Result<Vec<(K, V)>, E> {
78        Ok(Vec::new())
79    }
80
81    #[inline]
82    fn visit_map<T>(self, mut access: T) -> Result<Vec<(K, V)>, T::Error>
83    where
84        T: MapAccess<'de>,
85    {
86        let mut values = Vec::with_capacity(cmp::min(access.size_hint().unwrap_or(0), 4096));
87
88        while let Some((key, value)) = access.next_entry()? {
89            values.push((key, value));
90        }
91
92        Ok(values)
93    }
94}
95
96/// Serialize an array of `(K, V)` pairs as if it were a `HashMap<K, V>`.
97///
98/// In formats where dictionaries are ordered, this maintains the input data's order. Each pair is treated as a single
99/// entry into the dictionary.
100///
101/// Behavior when duplicate keys are present in the data is unspecified and serializer-dependent. This function does
102/// not check for duplicate keys and will not warn the serializer.
103pub fn serialize<K, V, S>(data: &[(K, V)], serializer: S) -> Result<S::Ok, S::Error>
104where
105    S: Serializer,
106    K: Serialize,
107    V: Serialize,
108{
109    serializer.collect_map(data.iter().map(|x| (&x.0, &x.1)))
110}
111
112/// Deserialize to a `Vec<(K, V)>` as if it were a `HashMap<K, V>`.
113///
114/// This directly deserializes into the returned vec with no intermediate allocation.
115///
116/// In formats where dictionaries are ordered, this maintains the input data's order.
117pub fn deserialize<'de, K, V, D>(deserializer: D) -> Result<Vec<(K, V)>, D::Error>
118where
119    D: Deserializer<'de>,
120    K: Deserialize<'de>,
121    V: Deserialize<'de>,
122{
123    deserializer.deserialize_map(TupleVecMapVisitor::new())
124}