Skip to content

Commit 4644646

Browse files
committed
Serde support
1 parent 36124d2 commit 4644646

File tree

5 files changed

+141
-3
lines changed

5 files changed

+141
-3
lines changed

.travis.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ sudo: false
33
matrix:
44
include:
55
- rust: stable
6+
env: FEATURES="serde_impl"
67
- rust: nightly
7-
env: FEATURES="--features nightly"
8+
env: FEATURES="serde_impl nightly"
89
script:
9-
- cargo build $FEATURES
10-
- cargo test $FEATURES
10+
- cargo build --features "$FEATURES"
11+
- cargo test --features "$FEATURES"
1112
- cargo doc --no-deps
1213
after_success: |
1314
[ "$TRAVIS_RUST_VERSION" = nightly ] &&

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ readme = "README.md"
1414

1515
[features]
1616
nightly = []
17+
serde_impl = ["serde", "serde_json"]
18+
19+
[dependencies]
20+
serde = { version = "^0.7", optional = true }
21+
serde_json = { version = "^0.7", optional = true }
1722

1823
[lib]
1924
test = false

src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
55
#![deny(missing_docs)]
66

7+
// Optional Serde support
8+
#[cfg(feature = "serde_impl")]
9+
pub mod serde;
10+
711
use std::borrow::Borrow;
812
use std::fmt::{self, Debug};
913
use std::iter;

src/serde.rs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//! An optional implementation of serialization/deserialization. Reference
2+
//! implementations used:
3+
//!
4+
//! - [Serialize][1].
5+
//! - [Deserialize][2].
6+
//!
7+
//! [1]: https://github.com/serde-rs/serde/blob/97856462467db2e90cf368e407c7ebcc726a01a9/serde/src/ser/impls.rs#L601-L611
8+
//! [2]: https://github.com/serde-rs/serde/blob/97856462467db2e90cf368e407c7ebcc726a01a9/serde/src/de/impls.rs#L694-L746
9+
10+
extern crate serde;
11+
12+
use super::LinearMap;
13+
14+
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
15+
use self::serde::ser::impls::MapIteratorVisitor;
16+
use self::serde::de::{Visitor, MapVisitor, Error};
17+
18+
use std::marker::PhantomData;
19+
20+
impl<K, V> Serialize for LinearMap<K, V>
21+
where K: Serialize + Ord,
22+
V: Serialize,
23+
{
24+
#[inline]
25+
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
26+
where S: Serializer,
27+
{
28+
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
29+
}
30+
}
31+
32+
#[allow(missing_docs)]
33+
pub struct LinearMapVisitor<K, V> {
34+
marker: PhantomData<LinearMap<K, V>>,
35+
}
36+
37+
impl<K, V> LinearMapVisitor<K, V> {
38+
#[allow(missing_docs)]
39+
pub fn new() -> Self {
40+
LinearMapVisitor {
41+
marker: PhantomData,
42+
}
43+
}
44+
}
45+
46+
impl<K, V> Visitor for LinearMapVisitor<K, V>
47+
where K: Deserialize + Eq,
48+
V: Deserialize,
49+
{
50+
type Value = LinearMap<K, V>;
51+
52+
#[inline]
53+
fn visit_unit<E>(&mut self) -> Result<Self::Value, E>
54+
where E: Error,
55+
{
56+
Ok(LinearMap::new())
57+
}
58+
59+
#[inline]
60+
fn visit_map<Visitor>(&mut self, mut visitor: Visitor) -> Result<Self::Value, Visitor::Error>
61+
where Visitor: MapVisitor,
62+
{
63+
let mut values = LinearMap::with_capacity(visitor.size_hint().0);
64+
65+
while let Some((key, value)) = try!(visitor.visit()) {
66+
values.insert(key, value);
67+
}
68+
69+
try!(visitor.end());
70+
71+
Ok(values)
72+
}
73+
}
74+
75+
impl<K, V> Deserialize for LinearMap<K, V>
76+
where K: Deserialize + Eq,
77+
V: Deserialize,
78+
{
79+
fn deserialize<D>(deserializer: &mut D) -> Result<LinearMap<K, V>, D::Error>
80+
where D: Deserializer,
81+
{
82+
deserializer.deserialize_map(LinearMapVisitor::new())
83+
}
84+
}

tests/serde.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#![cfg(feature = "serde_impl")]
2+
3+
extern crate linear_map;
4+
extern crate serde;
5+
extern crate serde_json;
6+
7+
use linear_map::LinearMap;
8+
9+
#[test]
10+
fn test_ser_empty() {
11+
let map = LinearMap::<String, u32>::new();
12+
let j = serde_json::to_string(&map).unwrap();
13+
let expected = "{}";
14+
assert_eq!(j, expected);
15+
}
16+
17+
#[test]
18+
fn test_ser() {
19+
let mut map = LinearMap::new();
20+
map.insert("b", 20);
21+
map.insert("a", 10);
22+
map.insert("c", 30);
23+
24+
let j = serde_json::to_string(&map).unwrap();
25+
let expected = r#"{"b":20,"a":10,"c":30}"#;
26+
assert_eq!(j, expected);
27+
}
28+
29+
#[test]
30+
fn test_de_empty() {
31+
let j = "{}";
32+
let map: LinearMap<String, u32> = serde_json::from_str(j).unwrap();
33+
assert_eq!(map.len(), 0);
34+
}
35+
36+
#[test]
37+
fn test_de() {
38+
let j = r#"{"b":20,"a":10,"c":30}"#;
39+
let map: LinearMap<String, u32> = serde_json::from_str(j).unwrap();
40+
let items: Vec<_> = map.iter().map(|(k, v)| (k.clone(), *v)).collect();
41+
assert_eq!(items, [("b".to_owned(), 20),
42+
("a".to_owned(), 10),
43+
("c".to_owned(), 30)]);
44+
}

0 commit comments

Comments
 (0)