Skip to content

Commit d746a56

Browse files
authored
add serde serialization support (#210)
1 parent 49c5a71 commit d746a56

File tree

6 files changed

+199
-0
lines changed

6 files changed

+199
-0
lines changed

Cargo.toml

+6
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,23 @@ harness = false
3636
# implement its `Allocator` trait.
3737
allocator-api2 = { version = "0.2.8", default-features = false, optional = true }
3838

39+
# This dependency is here to allow integration with Serde, if the `serde` feature is enabled
40+
serde = { version = "1.0.171", optional = true }
41+
3942
[dev-dependencies]
4043
quickcheck = "1.0.3"
4144
criterion = "0.3.6"
4245
rand = "0.8.5"
46+
serde = { version = "1.0.197", features = ["derive"] }
47+
serde_json = "1.0.115"
4348

4449
[features]
4550
default = []
4651
collections = []
4752
boxed = []
4853
allocator_api = []
4954
std = []
55+
serde = ["dep:serde"]
5056

5157
# [profile.bench]
5258
# debug = true

README.md

+31
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,37 @@ in its space itself.
153153
}
154154
```
155155

156+
#### Serde
157+
158+
Adding the `serde` feature flag will enable transparent serialization of Vecs and
159+
boxed values.
160+
161+
```toml
162+
[dependencies]
163+
bumpalo = { version = "3.9", features = ["collections", "boxed", "serde"] }
164+
```
165+
166+
```rust,ignore
167+
use bumpalo::{Bump, boxed::Box, collections::Vec};
168+
169+
// Create a new bump arena.
170+
let bump = Bump::new();
171+
172+
// Create a `Box`
173+
let box = Box::new_in("hello", &bump);
174+
175+
// Serialize with serde_json
176+
assert_eq!(serde_json::to_string(&box).unwrap(), "\"hello\"");
177+
178+
// Create a `Vec`
179+
let vec = Vec::new_in( &bump);
180+
vec.push(1);
181+
vec.push(2);
182+
183+
// Serialize with serde_json
184+
assert_eq!(serde_json::to_string(&vec).unwrap(), "[1, 2]");
185+
```
186+
156187
### `#![no_std]` Support
157188

158189
Bumpalo is a `no_std` crate by default. It depends only on the `alloc` and `core` crates.

src/boxed.rs

+16
Original file line numberDiff line numberDiff line change
@@ -681,3 +681,19 @@ impl<'a, T, const N: usize> TryFrom<Box<'a, [T]>> for Box<'a, [T; N]> {
681681
}
682682
}
683683
}
684+
685+
#[cfg(feature = "serde")]
686+
mod serialize {
687+
use super::*;
688+
689+
use serde::{Serialize, Serializer};
690+
691+
impl<'a, T> Serialize for Box<'a, T>
692+
where
693+
T: Serialize,
694+
{
695+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
696+
T::serialize(self, serializer)
697+
}
698+
}
699+
}

src/collections/vec.rs

+24
Original file line numberDiff line numberDiff line change
@@ -2760,3 +2760,27 @@ impl<'bump> io::Write for Vec<'bump, u8> {
27602760
Ok(())
27612761
}
27622762
}
2763+
2764+
#[cfg(feature = "serde")]
2765+
mod serialize {
2766+
use super::*;
2767+
2768+
use serde::{ser::SerializeSeq, Serialize, Serializer};
2769+
2770+
impl<'a, T> Serialize for Vec<'a, T>
2771+
where
2772+
T: Serialize,
2773+
{
2774+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2775+
where
2776+
S: Serializer,
2777+
{
2778+
let mut seq = serializer.serialize_seq(Some(self.len))?;
2779+
for e in self.iter() {
2780+
seq.serialize_element(e)?;
2781+
}
2782+
seq.end()
2783+
}
2784+
}
2785+
2786+
}

tests/all/main.rs

+3
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,7 @@ mod try_alloc_try_with;
1616
mod try_alloc_with;
1717
mod vec;
1818

19+
#[cfg(feature = "serde")]
20+
mod serde;
21+
1922
fn main() {}

tests/all/serde.rs

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#![cfg(feature = "collections")]
2+
#![cfg(feature = "serde")]
3+
4+
use bumpalo::{boxed::Box, vec, Bump};
5+
use serde::{Deserialize, Serialize};
6+
7+
macro_rules! compare_std_vec {
8+
(in $bump:ident; $($x:expr),+) => {{
9+
let mut vec = vec![in &$bump; $($x),+];
10+
let std_vec = std::vec![$($x),+];
11+
(vec, std_vec)
12+
}}
13+
}
14+
15+
macro_rules! compare_std_box {
16+
(in $bump:ident; $x:expr) => {
17+
(Box::new_in($x, &$bump), std::boxed::Box::new($x))
18+
};
19+
}
20+
21+
macro_rules! assert_eq_json {
22+
($a:ident, $b:ident) => {
23+
assert_eq!(
24+
serde_json::to_string(&$a).unwrap(),
25+
serde_json::to_string(&$b).unwrap(),
26+
)
27+
};
28+
}
29+
30+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
31+
#[serde(tag = "t", content = "c")]
32+
enum Test {
33+
First,
34+
Second,
35+
}
36+
37+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
38+
#[serde()]
39+
struct Mixed {
40+
i: i32,
41+
s: String,
42+
o: Option<String>,
43+
e: Test,
44+
}
45+
46+
#[test]
47+
fn test_vec_serializes_str() {
48+
let bump = Bump::new();
49+
let (vec, std_vec) = compare_std_vec![in bump; "hello", "world"];
50+
assert_eq_json!(vec, std_vec);
51+
let de: std::vec::Vec<String> =
52+
serde_json::from_str(&serde_json::to_string(&vec).unwrap()).unwrap();
53+
assert_eq!(de, std_vec);
54+
}
55+
56+
#[test]
57+
fn test_vec_serializes_f32() {
58+
let bump = Bump::new();
59+
let (vec, std_vec) = compare_std_vec![in bump; 1.5707964, 3.1415927];
60+
assert_eq_json!(vec, std_vec);
61+
let de: std::vec::Vec<f32> =
62+
serde_json::from_str(&serde_json::to_string(&vec).unwrap()).unwrap();
63+
assert_eq!(de, std_vec);
64+
}
65+
66+
#[cfg(feature = "serde")]
67+
#[test]
68+
fn test_vec_serializes_complex() {
69+
let bump = Bump::new();
70+
let (vec, std_vec) = compare_std_vec![
71+
in bump;
72+
Mixed {
73+
i: 8,
74+
s: "a".into(),
75+
o: None,
76+
e: Test::Second,
77+
},
78+
Mixed {
79+
i: 8,
80+
s: "b".into(),
81+
o: Some("some".into()),
82+
e: Test::First,
83+
}
84+
];
85+
assert_eq_json!(vec, std_vec);
86+
let de: std::vec::Vec<Mixed> =
87+
serde_json::from_str(&serde_json::to_string(&vec).unwrap()).unwrap();
88+
assert_eq!(de, std_vec);
89+
}
90+
91+
#[test]
92+
fn test_box_serializes() {
93+
let bump = Bump::new();
94+
let (box_int, std_box_int) = compare_std_box!(in bump; 1);
95+
assert_eq_json!(box_int, std_box_int);
96+
let (box_str, std_box_str) = compare_std_box!(in bump; 1);
97+
assert_eq_json!(box_str, std_box_str);
98+
let (box_vec, std_box_vec) = compare_std_box!(in bump; std::vec!["hello", "world"]);
99+
assert_eq_json!(box_vec, std_box_vec);
100+
}
101+
102+
#[cfg(feature = "serde")]
103+
#[test]
104+
fn test_box_serializes_complex() {
105+
let bump = Bump::new();
106+
let (vec, std_vec) = compare_std_box![
107+
in bump;
108+
Mixed {
109+
i: 8,
110+
s: "a".into(),
111+
o: None,
112+
e: Test::Second,
113+
}
114+
];
115+
assert_eq_json!(vec, std_vec);
116+
let de: std::boxed::Box<Mixed> =
117+
serde_json::from_str(&serde_json::to_string(&vec).unwrap()).unwrap();
118+
assert_eq!(de, std_vec);
119+
}

0 commit comments

Comments
 (0)