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
//! Deserializing maps to tuple-vecs.
//!
//! Don't waste space and time making a HashMap when you will never use it!
//!
//! 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 whole HashMap for the data, the key/value pairs are simply collected into a Vec.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(collections))]
#![deny(missing_docs)]

extern crate serde;

#[cfg(not(feature = "std"))]
extern crate collections;

#[cfg(feature = "std")]
mod core {
    // this mirrors serde's setup for std/non-std.
    pub use std::marker;
    pub use std::cmp;
    pub use std::fmt;
}

use core::marker::PhantomData;
use core::{cmp, fmt};

use serde::{Serializer, Deserializer, Serialize, Deserialize};
use serde::de::{MapVisitor, Visitor};

#[cfg(not(feature = "std"))]
use collections::Vec;

struct TupleVecMapVisitor<K: Deserialize, V: Deserialize> {
    marker: PhantomData<Vec<(K, V)>>,
}

impl<K, V> TupleVecMapVisitor<K, V>
    where K: Deserialize,
          V: Deserialize
{
    pub fn new() -> Self {
        TupleVecMapVisitor { marker: PhantomData }
    }
}

impl<K, V> Visitor for TupleVecMapVisitor<K, V>
    where K: Deserialize,
          V: Deserialize
{
    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 visitor: T) -> Result<Vec<(K, V)>, T::Error>
        where T: MapVisitor
    {
        let mut values = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4069));

        while let Some((key, value)) = visitor.visit()? {
            values.push((key, value));
        }

        Ok(values)
    }
}

/// Serialize a Vec<(K, V)> as if it were a HashMap<K, V>.
pub fn serialize<K, V, S>(data: &Vec<(K, V)>, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          K: Serialize,
          V: Serialize
{
    serializer.collect_map(data.into_iter().map(|x| (&x.0, &x.1)))
}

/// Deserialize to a Vec<(K, V)> as if it were a HashMap<K, V>.
///
/// Note: does not allocate a hashmap, deserializes directly to the Vec.
pub fn deserialize<K, V, D>(deserializer: D) -> Result<Vec<(K, V)>, D::Error>
    where D: Deserializer,
          K: Deserialize,
          V: Deserialize
{
    deserializer.deserialize_map(TupleVecMapVisitor::new())
}