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