├── .gitignore
├── README.md
├── benches
├── flavor
│ └── mod.rs
└── bincode.rs
├── src
├── lib.rs
├── error.rs
├── ser.rs
└── de.rs
├── Cargo.toml
├── tests
└── bincode.rs
└── .github
└── workflows
└── ci.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /Cargo.lock
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # serde-bench
2 |
3 | A minimal serialization format for use in benchmarks of core Serde. The format
4 | closely resembles Bincode.
5 |
6 |
7 |
8 | #### License
9 |
10 |
11 | Licensed under either of Apache License, Version
12 | 2.0 or MIT license at your option.
13 |
14 |
15 |
16 |
17 |
18 | Unless you explicitly state otherwise, any contribution intentionally submitted
19 | for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
20 | be dual licensed as above, without any additional terms or conditions.
21 |
22 |
--------------------------------------------------------------------------------
/benches/flavor/mod.rs:
--------------------------------------------------------------------------------
1 | use postcard::ser_flavors::Flavor;
2 | use postcard::Result;
3 |
4 | pub struct PreallocatedVec<'a> {
5 | vec: &'a mut Vec,
6 | }
7 |
8 | impl<'a> PreallocatedVec<'a> {
9 | pub fn new(vec: &'a mut Vec) -> Self {
10 | PreallocatedVec { vec }
11 | }
12 | }
13 |
14 | impl<'a> Flavor for PreallocatedVec<'a> {
15 | type Output = ();
16 |
17 | #[inline]
18 | fn try_extend(&mut self, data: &[u8]) -> Result<()> {
19 | self.vec.extend_from_slice(data);
20 | Ok(())
21 | }
22 |
23 | #[inline]
24 | fn try_push(&mut self, data: u8) -> Result<()> {
25 | self.vec.push(data);
26 | Ok(())
27 | }
28 |
29 | #[inline]
30 | fn finalize(self) -> Result {
31 | Ok(())
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![allow(
2 | clippy::cast_lossless,
3 | clippy::cast_possible_truncation,
4 | clippy::elidable_lifetime_names,
5 | clippy::missing_errors_doc,
6 | clippy::needless_lifetimes
7 | )]
8 |
9 | extern crate serde_core as serde;
10 |
11 | mod de;
12 | mod error;
13 | mod ser;
14 |
15 | use self::de::Deserializer;
16 | use self::ser::Serializer;
17 | use serde::{Deserialize, Serialize};
18 |
19 | pub use self::error::{Error, Result};
20 |
21 | pub fn serialize(out: &mut Vec, value: &T) -> Result<()>
22 | where
23 | T: Serialize,
24 | {
25 | let mut ser = Serializer::new(out);
26 | Serialize::serialize(value, &mut ser)
27 | }
28 |
29 | pub fn deserialize<'de, T>(bytes: &'de [u8]) -> Result
30 | where
31 | T: Deserialize<'de>,
32 | {
33 | let mut de = Deserializer::new(bytes);
34 | Deserialize::deserialize(&mut de)
35 | }
36 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "serde-bench"
3 | version = "0.0.14"
4 | authors = ["David Tolnay "]
5 | categories = ["encoding", "development-tools::profiling"]
6 | description = "Minimal serialization format for benchmarking Serde"
7 | documentation = "https://docs.rs/serde-bench/"
8 | edition = "2021"
9 | include = ["Cargo.toml", "src/**/*.rs"]
10 | keywords = ["serde", "serialization"]
11 | license = "MIT OR Apache-2.0"
12 | repository = "https://github.com/serde-rs/bench"
13 | rust-version = "1.68"
14 |
15 | [dependencies]
16 | byteorder = "1.4.3"
17 | serde_core = "1.0.220"
18 |
19 | [dev-dependencies]
20 | bincode = { version = "2", features = ["derive", "serde"] }
21 | postcard = { version = "1", features = ["use-std"] }
22 | serde = { version = "1", features = ["derive"] }
23 |
24 | [package.metadata.docs.rs]
25 | targets = ["x86_64-unknown-linux-gnu"]
26 | rustdoc-args = [
27 | "--generate-link-to-definition",
28 | "--generate-macro-expansion",
29 | "--extern-html-root-url=core=https://doc.rust-lang.org",
30 | "--extern-html-root-url=alloc=https://doc.rust-lang.org",
31 | "--extern-html-root-url=std=https://doc.rust-lang.org",
32 | ]
33 |
--------------------------------------------------------------------------------
/src/error.rs:
--------------------------------------------------------------------------------
1 | use serde::{de, ser};
2 | use std::fmt::{self, Display};
3 | use std::{error, io, str, string};
4 |
5 | #[derive(Debug)]
6 | pub struct Error {
7 | msg: String,
8 | }
9 |
10 | pub type Result = std::result::Result;
11 |
12 | impl Error {
13 | pub fn new(msg: T) -> Self {
14 | Error {
15 | msg: msg.to_string(),
16 | }
17 | }
18 | }
19 |
20 | impl error::Error for Error {}
21 |
22 | impl Display for Error {
23 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 | f.write_str(&self.msg)
25 | }
26 | }
27 |
28 | impl ser::Error for Error {
29 | fn custom(msg: T) -> Self {
30 | Error::new(msg)
31 | }
32 | }
33 |
34 | impl de::Error for Error {
35 | fn custom(msg: T) -> Self {
36 | Error::new(msg)
37 | }
38 | }
39 |
40 | impl From for Error {
41 | fn from(err: io::Error) -> Self {
42 | Error::new(err)
43 | }
44 | }
45 |
46 | impl From for Error {
47 | fn from(err: str::Utf8Error) -> Self {
48 | Error::new(err)
49 | }
50 | }
51 |
52 | impl From for Error {
53 | fn from(err: string::FromUtf8Error) -> Self {
54 | Error::new(err)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/bincode.rs:
--------------------------------------------------------------------------------
1 | #![allow(
2 | clippy::derive_partial_eq_without_eq,
3 | clippy::disallowed_names,
4 | clippy::unseparated_literal_suffix
5 | )]
6 |
7 | use serde::{Deserialize, Serialize};
8 |
9 | #[derive(Serialize, Deserialize, PartialEq, Debug)]
10 | struct Foo {
11 | bar: String,
12 | baz: u64,
13 | derp: bool,
14 | }
15 |
16 | impl Default for Foo {
17 | fn default() -> Self {
18 | Foo {
19 | bar: "hello".into(),
20 | baz: 1337u64,
21 | derp: true,
22 | }
23 | }
24 | }
25 |
26 | #[test]
27 | fn test_ser() {
28 | let foo = Foo::default();
29 |
30 | let bincode_bytes = bincode::serde::encode_to_vec(&foo, bincode::config::legacy()).unwrap();
31 |
32 | let mut serde_bytes = Vec::new();
33 | serde_bench::serialize(&mut serde_bytes, &foo).unwrap();
34 |
35 | assert_eq!(bincode_bytes, serde_bytes);
36 | }
37 |
38 | #[test]
39 | fn test_de() {
40 | let foo = Foo::default();
41 | let mut bytes = Vec::new();
42 | serde_bench::serialize(&mut bytes, &foo).unwrap();
43 |
44 | let bincode_foo =
45 | bincode::serde::decode_from_slice::(&bytes, bincode::config::legacy())
46 | .unwrap()
47 | .0;
48 | assert_eq!(bincode_foo, foo);
49 |
50 | let serde_foo = serde_bench::deserialize::(&bytes).unwrap();
51 | assert_eq!(serde_foo, foo);
52 | }
53 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | pull_request:
6 | workflow_dispatch:
7 | schedule: [cron: "40 1 * * *"]
8 |
9 | permissions:
10 | contents: read
11 |
12 | env:
13 | RUSTFLAGS: -Dwarnings
14 |
15 | jobs:
16 | test:
17 | name: Rust ${{matrix.rust}}
18 | runs-on: ubuntu-latest
19 | strategy:
20 | fail-fast: false
21 | matrix:
22 | rust: [nightly, beta, stable, 1.85.0, 1.68.0]
23 | timeout-minutes: 45
24 | steps:
25 | - uses: actions/checkout@v6
26 | - uses: dtolnay/rust-toolchain@master
27 | with:
28 | toolchain: ${{matrix.rust}}
29 | - run: cargo check
30 | - run: cargo test
31 | if: matrix.rust != '1.68.0'
32 | - run: cargo bench --no-run
33 | if: matrix.rust == 'nightly'
34 | - uses: actions/upload-artifact@v6
35 | if: matrix.rust == 'nightly' && always()
36 | with:
37 | name: Cargo.lock
38 | path: Cargo.lock
39 | continue-on-error: true
40 |
41 | minimal:
42 | name: Minimal versions
43 | runs-on: ubuntu-latest
44 | timeout-minutes: 45
45 | steps:
46 | - uses: actions/checkout@v6
47 | - uses: dtolnay/rust-toolchain@nightly
48 | - run: cargo generate-lockfile -Z minimal-versions
49 | - run: cargo check --locked
50 |
51 | doc:
52 | name: Documentation
53 | runs-on: ubuntu-latest
54 | timeout-minutes: 45
55 | env:
56 | RUSTDOCFLAGS: -Dwarnings
57 | steps:
58 | - uses: actions/checkout@v6
59 | - uses: dtolnay/rust-toolchain@nightly
60 | - uses: dtolnay/install@cargo-docs-rs
61 | - run: cargo docs-rs
62 |
63 | clippy:
64 | name: Clippy
65 | runs-on: ubuntu-latest
66 | timeout-minutes: 45
67 | steps:
68 | - uses: actions/checkout@v6
69 | - uses: dtolnay/rust-toolchain@clippy
70 | - run: cargo clippy --tests --benches -- -Dclippy::all -Dclippy::pedantic
71 |
72 | outdated:
73 | name: Outdated
74 | runs-on: ubuntu-latest
75 | if: github.event_name != 'pull_request'
76 | timeout-minutes: 45
77 | steps:
78 | - uses: actions/checkout@v6
79 | - uses: dtolnay/rust-toolchain@stable
80 | - uses: dtolnay/install@cargo-outdated
81 | - run: cargo outdated --workspace --ignore embedded-io --ignore bincode --exit-code 1
82 |
--------------------------------------------------------------------------------
/benches/bincode.rs:
--------------------------------------------------------------------------------
1 | #![feature(test)]
2 | #![allow(clippy::elidable_lifetime_names)]
3 |
4 | extern crate test;
5 |
6 | mod flavor;
7 |
8 | use crate::flavor::PreallocatedVec;
9 | use serde::{Deserialize, Serialize};
10 | use std::hint::black_box;
11 | use test::Bencher;
12 |
13 | #[derive(Serialize, Deserialize, bincode::Encode, bincode::Decode)]
14 | struct Foo {
15 | bar: String,
16 | baz: u64,
17 | derp: bool,
18 | }
19 |
20 | impl Default for Foo {
21 | fn default() -> Self {
22 | Foo {
23 | bar: "hello".into(),
24 | baz: 1337u64,
25 | derp: true,
26 | }
27 | }
28 | }
29 |
30 | #[bench]
31 | fn bincode_serde_deserialize(b: &mut Bencher) {
32 | let foo = Foo::default();
33 | let bytes = bincode::serde::encode_to_vec(&foo, bincode::config::standard()).unwrap();
34 |
35 | b.iter(|| {
36 | let bytes = black_box(&bytes);
37 | bincode::serde::decode_from_slice::(bytes, bincode::config::standard()).unwrap()
38 | });
39 | }
40 |
41 | #[bench]
42 | fn bincode_serde_serialize(b: &mut Bencher) {
43 | let foo = Foo::default();
44 | let mut bytes = Vec::with_capacity(128);
45 |
46 | b.iter(|| {
47 | let foo = black_box(&foo);
48 | bytes.clear();
49 | bincode::serde::encode_into_std_write(foo, &mut bytes, bincode::config::standard())
50 | .unwrap();
51 | });
52 | }
53 |
54 | #[bench]
55 | fn bincode_decode(b: &mut Bencher) {
56 | let foo = Foo::default();
57 | let bytes = bincode::encode_to_vec(&foo, bincode::config::standard()).unwrap();
58 |
59 | b.iter(|| {
60 | let bytes = black_box(&bytes);
61 | bincode::decode_from_slice::(bytes, bincode::config::standard()).unwrap()
62 | });
63 | }
64 |
65 | #[bench]
66 | fn bincode_encode(b: &mut Bencher) {
67 | let foo = Foo::default();
68 | let mut bytes = Vec::with_capacity(128);
69 |
70 | b.iter(|| {
71 | let foo = black_box(&foo);
72 | bytes.clear();
73 | bincode::encode_into_std_write(foo, &mut bytes, bincode::config::standard()).unwrap();
74 | });
75 | }
76 |
77 | #[bench]
78 | fn postcard_deserialize(b: &mut Bencher) {
79 | let foo = Foo::default();
80 | let bytes = postcard::to_stdvec(&foo).unwrap();
81 |
82 | b.iter(|| {
83 | let bytes = black_box(&bytes);
84 | postcard::from_bytes::(bytes).unwrap()
85 | });
86 | }
87 |
88 | #[bench]
89 | fn postcard_serialize(b: &mut Bencher) {
90 | let foo = Foo::default();
91 | let mut bytes = Vec::with_capacity(128);
92 |
93 | b.iter(|| {
94 | let foo = black_box(&foo);
95 | bytes.clear();
96 | postcard::serialize_with_flavor(foo, PreallocatedVec::new(&mut bytes)).unwrap();
97 | });
98 | }
99 |
100 | #[bench]
101 | fn serde_deserialize(b: &mut Bencher) {
102 | let foo = Foo::default();
103 | let mut bytes = Vec::new();
104 | serde_bench::serialize(&mut bytes, &foo).unwrap();
105 |
106 | b.iter(|| {
107 | let bytes = black_box(&bytes);
108 | serde_bench::deserialize::(bytes).unwrap()
109 | });
110 | }
111 |
112 | #[bench]
113 | fn serde_serialize(b: &mut Bencher) {
114 | let foo = Foo::default();
115 | let mut bytes = Vec::with_capacity(128);
116 |
117 | b.iter(|| {
118 | let foo = black_box(&foo);
119 | bytes.clear();
120 | serde_bench::serialize(&mut bytes, foo).unwrap();
121 | });
122 | }
123 |
--------------------------------------------------------------------------------
/src/ser.rs:
--------------------------------------------------------------------------------
1 | use crate::{Error, Result};
2 | use byteorder::{NativeEndian, WriteBytesExt};
3 | use serde::ser::{
4 | SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
5 | SerializeTupleStruct, SerializeTupleVariant,
6 | };
7 | use std::io::Write;
8 |
9 | pub struct Serializer {
10 | writer: W,
11 | }
12 |
13 | impl Serializer
14 | where
15 | W: Write,
16 | {
17 | pub fn new(w: W) -> Self {
18 | Serializer { writer: w }
19 | }
20 | }
21 |
22 | impl serde::Serializer for &mut Serializer
23 | where
24 | W: Write,
25 | {
26 | type Ok = ();
27 | type Error = Error;
28 |
29 | type SerializeSeq = Self;
30 | type SerializeTuple = Self;
31 | type SerializeTupleStruct = Self;
32 | type SerializeTupleVariant = Self;
33 | type SerializeMap = Self;
34 | type SerializeStruct = Self;
35 | type SerializeStructVariant = Self;
36 |
37 | #[inline]
38 | fn serialize_unit(self) -> Result<()> {
39 | Ok(())
40 | }
41 |
42 | #[inline]
43 | fn serialize_unit_struct(self, _: &'static str) -> Result<()> {
44 | Ok(())
45 | }
46 |
47 | #[inline]
48 | fn serialize_bool(self, v: bool) -> Result<()> {
49 | self.writer.write_u8(v as u8).map_err(From::from)
50 | }
51 |
52 | #[inline]
53 | fn serialize_u8(self, v: u8) -> Result<()> {
54 | self.writer.write_u8(v).map_err(From::from)
55 | }
56 |
57 | #[inline]
58 | fn serialize_u16(self, v: u16) -> Result<()> {
59 | self.writer.write_u16::(v).map_err(From::from)
60 | }
61 |
62 | #[inline]
63 | fn serialize_u32(self, v: u32) -> Result<()> {
64 | self.writer.write_u32::(v).map_err(From::from)
65 | }
66 |
67 | #[inline]
68 | fn serialize_u64(self, v: u64) -> Result<()> {
69 | self.writer.write_u64::(v).map_err(From::from)
70 | }
71 |
72 | #[inline]
73 | fn serialize_u128(self, v: u128) -> Result<()> {
74 | self.writer
75 | .write_u128::(v)
76 | .map_err(From::from)
77 | }
78 |
79 | #[inline]
80 | fn serialize_i8(self, v: i8) -> Result<()> {
81 | self.writer.write_i8(v).map_err(From::from)
82 | }
83 |
84 | #[inline]
85 | fn serialize_i16(self, v: i16) -> Result<()> {
86 | self.writer.write_i16::(v).map_err(From::from)
87 | }
88 |
89 | #[inline]
90 | fn serialize_i32(self, v: i32) -> Result<()> {
91 | self.writer.write_i32::(v).map_err(From::from)
92 | }
93 |
94 | #[inline]
95 | fn serialize_i64(self, v: i64) -> Result<()> {
96 | self.writer.write_i64::(v).map_err(From::from)
97 | }
98 |
99 | #[inline]
100 | fn serialize_i128(self, v: i128) -> Result<()> {
101 | self.writer
102 | .write_i128::(v)
103 | .map_err(From::from)
104 | }
105 |
106 | #[inline]
107 | fn serialize_f32(self, v: f32) -> Result<()> {
108 | self.writer.write_f32::(v).map_err(From::from)
109 | }
110 |
111 | #[inline]
112 | fn serialize_f64(self, v: f64) -> Result<()> {
113 | self.writer.write_f64::(v).map_err(From::from)
114 | }
115 |
116 | #[inline]
117 | fn serialize_str(self, v: &str) -> Result<()> {
118 | self.serialize_u64(v.len() as u64)?;
119 | self.writer.write_all(v.as_bytes()).map_err(From::from)
120 | }
121 |
122 | #[inline]
123 | fn serialize_char(self, c: char) -> Result<()> {
124 | self.writer
125 | .write_all(encode_utf8(c).as_slice())
126 | .map_err(From::from)
127 | }
128 |
129 | #[inline]
130 | fn serialize_bytes(self, v: &[u8]) -> Result<()> {
131 | self.serialize_u64(v.len() as u64)?;
132 | self.writer.write_all(v).map_err(From::from)
133 | }
134 |
135 | #[inline]
136 | fn serialize_none(self) -> Result<()> {
137 | self.writer.write_u8(0).map_err(From::from)
138 | }
139 |
140 | #[inline]
141 | fn serialize_some(self, v: &T) -> Result<()>
142 | where
143 | T: ?Sized + serde::Serialize,
144 | {
145 | self.writer.write_u8(1)?;
146 | v.serialize(self)
147 | }
148 |
149 | #[inline]
150 | fn serialize_seq(self, len: Option) -> Result {
151 | let len = len.expect("do not know how to serialize a sequence with no length");
152 | self.serialize_u64(len as u64)?;
153 | Ok(self)
154 | }
155 |
156 | #[inline]
157 | fn serialize_tuple(self, _len: usize) -> Result {
158 | Ok(self)
159 | }
160 |
161 | #[inline]
162 | fn serialize_tuple_struct(
163 | self,
164 | _name: &'static str,
165 | _len: usize,
166 | ) -> Result {
167 | Ok(self)
168 | }
169 |
170 | #[inline]
171 | fn serialize_tuple_variant(
172 | self,
173 | _name: &'static str,
174 | variant_index: u32,
175 | _variant: &'static str,
176 | _len: usize,
177 | ) -> Result {
178 | self.serialize_u32(variant_index)?;
179 | Ok(self)
180 | }
181 |
182 | #[inline]
183 | fn serialize_map(self, len: Option) -> Result {
184 | let len = len.expect("do not know how to serialize a map with no length");
185 | self.serialize_u64(len as u64)?;
186 | Ok(self)
187 | }
188 |
189 | #[inline]
190 | fn serialize_struct(self, _name: &'static str, _len: usize) -> Result {
191 | Ok(self)
192 | }
193 |
194 | #[inline]
195 | fn serialize_struct_variant(
196 | self,
197 | _name: &'static str,
198 | variant_index: u32,
199 | _variant: &'static str,
200 | _len: usize,
201 | ) -> Result {
202 | self.serialize_u32(variant_index)?;
203 | Ok(self)
204 | }
205 |
206 | #[inline]
207 | fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()>
208 | where
209 | T: ?Sized + serde::ser::Serialize,
210 | {
211 | value.serialize(self)
212 | }
213 |
214 | #[inline]
215 | fn serialize_newtype_variant(
216 | self,
217 | _name: &'static str,
218 | variant_index: u32,
219 | _variant: &'static str,
220 | value: &T,
221 | ) -> Result<()>
222 | where
223 | T: ?Sized + serde::ser::Serialize,
224 | {
225 | self.serialize_u32(variant_index)?;
226 | value.serialize(self)
227 | }
228 |
229 | #[inline]
230 | fn serialize_unit_variant(
231 | self,
232 | _name: &'static str,
233 | variant_index: u32,
234 | _variant: &'static str,
235 | ) -> Result<()> {
236 | self.serialize_u32(variant_index)
237 | }
238 |
239 | fn is_human_readable(&self) -> bool {
240 | false
241 | }
242 | }
243 |
244 | impl SerializeSeq for &mut Serializer
245 | where
246 | W: Write,
247 | {
248 | type Ok = ();
249 | type Error = Error;
250 |
251 | #[inline]
252 | fn serialize_element(&mut self, value: &V) -> Result<()>
253 | where
254 | V: ?Sized + serde::Serialize,
255 | {
256 | value.serialize(&mut **self)
257 | }
258 |
259 | #[inline]
260 | fn end(self) -> Result<()> {
261 | Ok(())
262 | }
263 | }
264 |
265 | impl SerializeTuple for &mut Serializer
266 | where
267 | W: Write,
268 | {
269 | type Ok = ();
270 | type Error = Error;
271 |
272 | #[inline]
273 | fn serialize_element(&mut self, value: &V) -> Result<()>
274 | where
275 | V: ?Sized + serde::Serialize,
276 | {
277 | value.serialize(&mut **self)
278 | }
279 |
280 | #[inline]
281 | fn end(self) -> Result<()> {
282 | Ok(())
283 | }
284 | }
285 |
286 | impl SerializeTupleStruct for &mut Serializer
287 | where
288 | W: Write,
289 | {
290 | type Ok = ();
291 | type Error = Error;
292 |
293 | #[inline]
294 | fn serialize_field(&mut self, value: &V) -> Result<()>
295 | where
296 | V: ?Sized + serde::Serialize,
297 | {
298 | value.serialize(&mut **self)
299 | }
300 |
301 | #[inline]
302 | fn end(self) -> Result<()> {
303 | Ok(())
304 | }
305 | }
306 |
307 | impl SerializeTupleVariant for &mut Serializer
308 | where
309 | W: Write,
310 | {
311 | type Ok = ();
312 | type Error = Error;
313 |
314 | #[inline]
315 | fn serialize_field(&mut self, value: &V) -> Result<()>
316 | where
317 | V: ?Sized + serde::Serialize,
318 | {
319 | value.serialize(&mut **self)
320 | }
321 |
322 | #[inline]
323 | fn end(self) -> Result<()> {
324 | Ok(())
325 | }
326 | }
327 |
328 | impl SerializeMap for &mut Serializer
329 | where
330 | W: Write,
331 | {
332 | type Ok = ();
333 | type Error = Error;
334 |
335 | #[inline]
336 | fn serialize_key(&mut self, key: &K) -> Result<()>
337 | where
338 | K: ?Sized + serde::Serialize,
339 | {
340 | key.serialize(&mut **self)
341 | }
342 |
343 | #[inline]
344 | fn serialize_value(&mut self, value: &V) -> Result<()>
345 | where
346 | V: ?Sized + serde::Serialize,
347 | {
348 | value.serialize(&mut **self)
349 | }
350 |
351 | #[inline]
352 | fn end(self) -> Result<()> {
353 | Ok(())
354 | }
355 | }
356 |
357 | impl SerializeStruct for &mut Serializer
358 | where
359 | W: Write,
360 | {
361 | type Ok = ();
362 | type Error = Error;
363 |
364 | #[inline]
365 | fn serialize_field(&mut self, _key: &'static str, value: &V) -> Result<()>
366 | where
367 | V: ?Sized + serde::Serialize,
368 | {
369 | value.serialize(&mut **self)
370 | }
371 |
372 | #[inline]
373 | fn end(self) -> Result<()> {
374 | Ok(())
375 | }
376 | }
377 |
378 | impl SerializeStructVariant for &mut Serializer
379 | where
380 | W: Write,
381 | {
382 | type Ok = ();
383 | type Error = Error;
384 |
385 | #[inline]
386 | fn serialize_field(&mut self, _key: &'static str, value: &V) -> Result<()>
387 | where
388 | V: ?Sized + serde::Serialize,
389 | {
390 | value.serialize(&mut **self)
391 | }
392 |
393 | #[inline]
394 | fn end(self) -> Result<()> {
395 | Ok(())
396 | }
397 | }
398 |
399 | #[inline]
400 | fn encode_utf8(c: char) -> EncodeUtf8 {
401 | const TAG_CONT: u8 = 0b1000_0000;
402 | const TAG_TWO_B: u8 = 0b1100_0000;
403 | const TAG_THREE_B: u8 = 0b1110_0000;
404 | const TAG_FOUR_B: u8 = 0b1111_0000;
405 | const MAX_ONE_B: u32 = 0x80;
406 | const MAX_TWO_B: u32 = 0x800;
407 | const MAX_THREE_B: u32 = 0x10000;
408 |
409 | let code = c as u32;
410 | let mut buf = [0; 4];
411 | let pos = if code < MAX_ONE_B {
412 | buf[3] = code as u8;
413 | 3
414 | } else if code < MAX_TWO_B {
415 | buf[2] = ((code >> 6) & 0x1F) as u8 | TAG_TWO_B;
416 | buf[3] = (code & 0x3F) as u8 | TAG_CONT;
417 | 2
418 | } else if code < MAX_THREE_B {
419 | buf[1] = ((code >> 12) & 0x0F) as u8 | TAG_THREE_B;
420 | buf[2] = ((code >> 6) & 0x3F) as u8 | TAG_CONT;
421 | buf[3] = (code & 0x3F) as u8 | TAG_CONT;
422 | 1
423 | } else {
424 | buf[0] = ((code >> 18) & 0x07) as u8 | TAG_FOUR_B;
425 | buf[1] = ((code >> 12) & 0x3F) as u8 | TAG_CONT;
426 | buf[2] = ((code >> 6) & 0x3F) as u8 | TAG_CONT;
427 | buf[3] = (code & 0x3F) as u8 | TAG_CONT;
428 | 0
429 | };
430 | EncodeUtf8 { buf, pos }
431 | }
432 |
433 | struct EncodeUtf8 {
434 | buf: [u8; 4],
435 | pos: usize,
436 | }
437 |
438 | impl EncodeUtf8 {
439 | #[inline]
440 | fn as_slice(&self) -> &[u8] {
441 | &self.buf[self.pos..]
442 | }
443 | }
444 |
--------------------------------------------------------------------------------
/src/de.rs:
--------------------------------------------------------------------------------
1 | use crate::{Error, Result};
2 | use byteorder::{NativeEndian, ReadBytesExt};
3 | use serde::de::{
4 | self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, SeqAccess, VariantAccess,
5 | Visitor,
6 | };
7 | use std::str;
8 |
9 | pub struct Deserializer<'de> {
10 | bytes: &'de [u8],
11 | }
12 |
13 | impl<'de> Deserializer<'de> {
14 | pub fn new(bytes: &'de [u8]) -> Self {
15 | Deserializer { bytes }
16 | }
17 |
18 | #[inline]
19 | fn read_slice(&mut self) -> Result<&'de [u8]> {
20 | let len = Deserialize::deserialize(&mut *self)?;
21 | let (slice, rest) = self.bytes.split_at(len);
22 | self.bytes = rest;
23 | Ok(slice)
24 | }
25 |
26 | #[inline]
27 | fn read_str(&mut self) -> Result<&'de str> {
28 | str::from_utf8(self.read_slice()?).map_err(Into::into)
29 | }
30 | }
31 |
32 | macro_rules! impl_nums {
33 | ($dser_method:ident, $visitor_method:ident, $reader_method:ident) => {
34 | #[inline]
35 | fn $dser_method(self, visitor: V) -> Result
36 | where
37 | V: Visitor<'de>,
38 | {
39 | let value = self.bytes.$reader_method::()?;
40 | visitor.$visitor_method(value)
41 | }
42 | };
43 | }
44 |
45 | impl<'de> serde::Deserializer<'de> for &mut Deserializer<'de> {
46 | type Error = Error;
47 |
48 | fn deserialize_any(self, _visitor: V) -> Result
49 | where
50 | V: Visitor<'de>,
51 | {
52 | Err(Error::new("`deserialize_any` is not supported"))
53 | }
54 |
55 | #[inline]
56 | fn deserialize_bool(self, visitor: V) -> Result
57 | where
58 | V: Visitor<'de>,
59 | {
60 | match self.bytes.read_u8()? {
61 | 1 => visitor.visit_bool(true),
62 | 0 => visitor.visit_bool(false),
63 | _ => Err(Error::new("invalid boolean")),
64 | }
65 | }
66 |
67 | impl_nums!(deserialize_u16, visit_u16, read_u16);
68 | impl_nums!(deserialize_u32, visit_u32, read_u32);
69 | impl_nums!(deserialize_u64, visit_u64, read_u64);
70 | impl_nums!(deserialize_u128, visit_u128, read_u128);
71 | impl_nums!(deserialize_i16, visit_i16, read_i16);
72 | impl_nums!(deserialize_i32, visit_i32, read_i32);
73 | impl_nums!(deserialize_i64, visit_i64, read_i64);
74 | impl_nums!(deserialize_i128, visit_i128, read_i128);
75 | impl_nums!(deserialize_f32, visit_f32, read_f32);
76 | impl_nums!(deserialize_f64, visit_f64, read_f64);
77 |
78 | #[inline]
79 | fn deserialize_u8(self, visitor: V) -> Result
80 | where
81 | V: Visitor<'de>,
82 | {
83 | visitor.visit_u8(self.bytes.read_u8()?)
84 | }
85 |
86 | #[inline]
87 | fn deserialize_i8(self, visitor: V) -> Result
88 | where
89 | V: Visitor<'de>,
90 | {
91 | visitor.visit_i8(self.bytes.read_i8()?)
92 | }
93 |
94 | #[inline]
95 | fn deserialize_unit(self, visitor: V) -> Result
96 | where
97 | V: Visitor<'de>,
98 | {
99 | visitor.visit_unit()
100 | }
101 |
102 | #[inline]
103 | fn deserialize_char(self, visitor: V) -> Result
104 | where
105 | V: Visitor<'de>,
106 | {
107 | let width = utf8_char_width(self.bytes[0]);
108 | if width == 1 {
109 | return visitor.visit_char(self.bytes[0] as char);
110 | }
111 | if width == 0 {
112 | return Err(Error::new("invalid char"));
113 | }
114 | let res = match str::from_utf8(&self.bytes[..width]) {
115 | Ok(s) => s.chars().next().unwrap(),
116 | Err(err) => {
117 | return Err(err.into());
118 | }
119 | };
120 | self.bytes = &self.bytes[width..];
121 | visitor.visit_char(res)
122 | }
123 |
124 | #[inline]
125 | fn deserialize_str(self, visitor: V) -> Result
126 | where
127 | V: Visitor<'de>,
128 | {
129 | visitor.visit_borrowed_str(self.read_str()?)
130 | }
131 |
132 | #[inline]
133 | fn deserialize_string(self, visitor: V) -> Result
134 | where
135 | V: Visitor<'de>,
136 | {
137 | visitor.visit_borrowed_str(self.read_str()?)
138 | }
139 |
140 | #[inline]
141 | fn deserialize_bytes(self, visitor: V) -> Result
142 | where
143 | V: Visitor<'de>,
144 | {
145 | visitor.visit_borrowed_bytes(self.read_slice()?)
146 | }
147 |
148 | #[inline]
149 | fn deserialize_byte_buf(self, visitor: V) -> Result
150 | where
151 | V: Visitor<'de>,
152 | {
153 | visitor.visit_borrowed_bytes(self.read_slice()?)
154 | }
155 |
156 | #[inline]
157 | fn deserialize_enum(
158 | self,
159 | _enum: &'static str,
160 | _variants: &'static [&'static str],
161 | visitor: V,
162 | ) -> Result
163 | where
164 | V: Visitor<'de>,
165 | {
166 | visitor.visit_enum(self)
167 | }
168 |
169 | #[inline]
170 | fn deserialize_tuple(self, _len: usize, visitor: V) -> Result
171 | where
172 | V: Visitor<'de>,
173 | {
174 | visitor.visit_seq(self)
175 | }
176 |
177 | #[inline]
178 | fn deserialize_option(self, visitor: V) -> Result
179 | where
180 | V: Visitor<'de>,
181 | {
182 | match self.bytes.read_u8()? {
183 | 0 => visitor.visit_none(),
184 | 1 => visitor.visit_some(self),
185 | _ => Err(Error::new("invalid Option")),
186 | }
187 | }
188 |
189 | #[inline]
190 | fn deserialize_seq(self, visitor: V) -> Result
191 | where
192 | V: Visitor<'de>,
193 | {
194 | struct SeqAccess<'a, 'de: 'a> {
195 | deserializer: &'a mut Deserializer<'de>,
196 | remaining: usize,
197 | }
198 |
199 | impl<'de, 'a> de::SeqAccess<'de> for SeqAccess<'a, 'de> {
200 | type Error = Error;
201 |
202 | #[inline]
203 | fn next_element_seed(&mut self, seed: T) -> Result