Skip to content

Commit 25d6550

Browse files
committed
Serde support
1 parent 36124d2 commit 25d6550

File tree

5 files changed

+139
-3
lines changed

5 files changed

+139
-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+
mod serde;
10+
711
use std::borrow::Borrow;
812
use std::fmt::{self, Debug};
913
use std::iter;

src/serde.rs

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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+
struct LinearMapVisitor<K, V> {
33+
marker: PhantomData<LinearMap<K, V>>,
34+
}
35+
36+
impl<K, V> LinearMapVisitor<K, V> {
37+
fn new() -> Self {
38+
LinearMapVisitor {
39+
marker: PhantomData,
40+
}
41+
}
42+
}
43+
44+
impl<K, V> Visitor for LinearMapVisitor<K, V>
45+
where K: Deserialize + Eq,
46+
V: Deserialize,
47+
{
48+
type Value = LinearMap<K, V>;
49+
50+
#[inline]
51+
fn visit_unit<E>(&mut self) -> Result<Self::Value, E>
52+
where E: Error,
53+
{
54+
Ok(LinearMap::new())
55+
}
56+
57+
#[inline]
58+
fn visit_map<Visitor>(&mut self, mut visitor: Visitor) -> Result<Self::Value, Visitor::Error>
59+
where Visitor: MapVisitor,
60+
{
61+
let mut values = LinearMap::with_capacity(visitor.size_hint().0);
62+
63+
while let Some((key, value)) = try!(visitor.visit()) {
64+
values.insert(key, value);
65+
}
66+
67+
try!(visitor.end());
68+
69+
Ok(values)
70+
}
71+
}
72+
73+
impl<K, V> Deserialize for LinearMap<K, V>
74+
where K: Deserialize + Eq,
75+
V: Deserialize,
76+
{
77+
fn deserialize<D>(deserializer: &mut D) -> Result<LinearMap<K, V>, D::Error>
78+
where D: Deserializer,
79+
{
80+
deserializer.deserialize_map(LinearMapVisitor::new())
81+
}
82+
}

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)