Bug 1716518 - Upgrade bincode to v1.3.3. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D117752
This commit is contained in:
Mike Hommey 2021-06-15 20:39:44 +00:00
parent b19f6f43a2
commit 81d392cdc1
19 changed files with 4808 additions and 2380 deletions

5
Cargo.lock generated
View File

@ -270,11 +270,10 @@ checksum = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
[[package]]
name = "bincode"
version = "1.2.1"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"byteorder",
"serde",
]

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"16c6c5374dd14773571dfab3254557ca0e3f7810e1fb27df6e27c2112e16c605","LICENSE.md":"90d7e062634054e6866d3c81e6a2b3058a840e6af733e98e80bdfe1a7dec6912","readme.md":"8d9ee7f575a20798e09471169ff3b5e3dea6ab74c50d2128cfc77f4074e97149","src/config.rs":"e3e6e264cdc736c442b9299d7ad39475457f0c69d2ea8fa0de14f8120c5f3023","src/de/mod.rs":"c431445d27366eaa05553fe1eb5dee320e87b7145b26fe50a56568fc83ccfe95","src/de/read.rs":"e188e291aef8c4ce41552390a28caacb26188c796e25c912d9730ad411a4abeb","src/error.rs":"ce6617bf8523392e6fc8b853b7768899a229b6b78dabc2918c0e2dd3f846aa01","src/internal.rs":"55a69c335cf15038eb76f7ba71b0828b20ee1d16adbc5e10e2087efbb74c55ea","src/lib.rs":"41258f970098e3b0421daf9fbaff34efa716039632f5d1b6409e22fe473c5775","src/ser/mod.rs":"323ca31c66188ba952faf6de111c91fe551a27ebc522c10a3cfe2e5348a74390"},"package":"5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf"}
{"files":{"Cargo.toml":"bec3b1248d39cbaa31f04baba57650b70540ce6458d81e0f83c7bd178d7636f2","LICENSE.md":"237710d4c9dd8eb7fead2c9c433be493a878f547d1093812feff43d18abe5896","readme.md":"46bed3c85db9aafba5999d5632753d93dda40e3af3b8b3e2bbab12a75f42f05e","src/byteorder.rs":"2c9de3d574339be9cafd47333e57dc92bd9014b2e0fd1a400683d06ceceb6fa7","src/config/endian.rs":"4cc21f604425f3bd7b169019a2560356dad62c8e0199c8cb46bb5e209ae70432","src/config/int.rs":"66065835fc56a515df57f2c19df6bfc8295a87266d05cf6dac17f0380cae2af6","src/config/legacy.rs":"db8dca430bb718058289b99528cd8e62502fdaf93d652ca6772026de8a784e40","src/config/limit.rs":"e5883d901a4b216e622f092503767ace121c396b645a24e28dcc528eab54d8e3","src/config/mod.rs":"d79766ac15a213293e8d684ba639e0968bf883214007ffcab6c9f7128a12bdb6","src/config/trailing.rs":"dec18dbbd847e87456bcaa93413c377d922efb4239f0600879c7440540a07a3e","src/de/mod.rs":"b91fe450aedbc9332f59f189dd438fdabfb4d7482f951aa40db18b49fa91b942","src/de/read.rs":"bb32d12d8dee1b0df426e3cc48288664152468c48b1df2448edd18bf1df921be","src/error.rs":"f1154e228fd0d2dfc73bed9efb410875a8b84a77b40c2dfbe37d3dd244ed0741","src/internal.rs":"ac343424a43899f4f9d44855484bc84cd86a07fafc9ae721d92a2095afeb8b05","src/lib.rs":"c68480ac64127e196b49b75a676b7c3a3bd723020b168b4f6093a64feb548b2e","src/ser/mod.rs":"a9cbf0b6c24c73d6f51994ebdb4c3b8ecd410011b083b7a882d823a7271d2221","tests/test.rs":"63974ad679ec47fe0497f6a21caf17f5b8040b68ef70df7af508bfa8c0e01d59"},"package":"b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"}

View File

@ -12,9 +12,9 @@
[package]
name = "bincode"
version = "1.2.1"
authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>", "David Tolnay <dtolnay@gmail.com>", "Daniel Griffen"]
exclude = ["logo.png", "tests/*", "examples/*", ".gitignore", ".travis.yml"]
version = "1.3.3"
authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>", "David Tolnay <dtolnay@gmail.com>", "Zoey Riordan <zoey@dos.cafe>"]
exclude = ["logo.png", "examples/*", ".gitignore", ".travis.yml"]
publish = true
description = "A binary serialization / deserialization strategy that uses Serde for transforming structs into bytes and vice versa!"
documentation = "https://docs.rs/bincode"
@ -23,9 +23,6 @@ keywords = ["binary", "encode", "decode", "serialize", "deserialize"]
categories = ["encoding", "network-programming"]
license = "MIT"
repository = "https://github.com/servo/bincode"
[dependencies.byteorder]
version = "1.3.0"
[dependencies.serde]
version = "1.0.63"
[dev-dependencies.serde_bytes]

View File

@ -1,21 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Ty Overby
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The MIT License (MIT)
Copyright (c) 2014 Ty Overby
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,70 +1,112 @@
# Bincode
<img align="right" src="./logo.png" />
[![Build Status](https://travis-ci.com/servo/bincode.svg)](https://travis-ci.com/servo/bincode)
[![](https://meritbadge.herokuapp.com/bincode)](https://crates.io/crates/bincode)
[![](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
A compact encoder / decoder pair that uses a binary zero-fluff encoding scheme.
The size of the encoded object will be the same or smaller than the size that
the object takes up in memory in a running Rust program.
In addition to exposing two simple functions
(one that encodes to `Vec<u8>`, and one that decodes from `&[u8]`),
binary-encode exposes a Reader/Writer API that makes it work
perfectly with other stream-based APIs such as Rust files, network streams,
and the [flate2-rs](https://github.com/alexcrichton/flate2-rs) compression
library.
## [API Documentation](https://docs.rs/bincode/)
## Bincode in the wild
* [google/tarpc](https://github.com/google/tarpc): Bincode is used to serialize and deserialize networked RPC messages.
* [servo/webrender](https://github.com/servo/webrender): Bincode records webrender API calls for record/replay-style graphics debugging.
* [servo/ipc-channel](https://github.com/servo/ipc-channel): IPC-Channel uses Bincode to send structs between processes using a channel-like API.
## Example
```rust
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Entity {
x: f32,
y: f32,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct World(Vec<Entity>);
fn main() {
let world = World(vec![Entity { x: 0.0, y: 4.0 }, Entity { x: 10.0, y: 20.5 }]);
let encoded: Vec<u8> = bincode::serialize(&world).unwrap();
// 8 bytes for the length of the vector, 4 bytes per float.
assert_eq!(encoded.len(), 8 + 4 * 4);
let decoded: World = bincode::deserialize(&encoded[..]).unwrap();
assert_eq!(world, decoded);
}
```
## Details
The encoding (and thus decoding) proceeds unsurprisingly -- primitive
types are encoded according to the underlying `Writer`, tuples and
structs are encoded by encoding their fields one-by-one, and enums are
encoded by first writing out the tag representing the variant and
then the contents.
However, there are some implementation details to be aware of:
* `isize`/`usize` are encoded as `i64`/`u64`, for portability.
* enums variants are encoded as a `u32` instead of a `usize`.
`u32` is enough for all practical uses.
* `str` is encoded as `(u64, &[u8])`, where the `u64` is the number of
bytes contained in the encoded string.
# Bincode
<img align="right" src="./logo.png" />
![CI](https://github.com/servo/bincode/workflows/CI/badge.svg)
[![](https://meritbadge.herokuapp.com/bincode)](https://crates.io/crates/bincode)
[![](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![](https://img.shields.io/badge/bincode-rustc_1.18+-lightgray.svg)](https://blog.rust-lang.org/2017/06/08/Rust-1.18.html)
A compact encoder / decoder pair that uses a binary zero-fluff encoding scheme.
The size of the encoded object will be the same or smaller than the size that
the object takes up in memory in a running Rust program.
In addition to exposing two simple functions
(one that encodes to `Vec<u8>`, and one that decodes from `&[u8]`),
binary-encode exposes a Reader/Writer API that makes it work
perfectly with other stream-based APIs such as Rust files, network streams,
and the [flate2-rs](https://github.com/alexcrichton/flate2-rs) compression
library.
## [API Documentation](https://docs.rs/bincode/)
## Bincode in the wild
* [google/tarpc](https://github.com/google/tarpc): Bincode is used to serialize and deserialize networked RPC messages.
* [servo/webrender](https://github.com/servo/webrender): Bincode records webrender API calls for record/replay-style graphics debugging.
* [servo/ipc-channel](https://github.com/servo/ipc-channel): IPC-Channel uses Bincode to send structs between processes using a channel-like API.
## Example
```rust
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Entity {
x: f32,
y: f32,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct World(Vec<Entity>);
fn main() {
let world = World(vec![Entity { x: 0.0, y: 4.0 }, Entity { x: 10.0, y: 20.5 }]);
let encoded: Vec<u8> = bincode::serialize(&world).unwrap();
// 8 bytes for the length of the vector, 4 bytes per float.
assert_eq!(encoded.len(), 8 + 4 * 4);
let decoded: World = bincode::deserialize(&encoded[..]).unwrap();
assert_eq!(world, decoded);
}
```
## Details
The encoding (and thus decoding) proceeds unsurprisingly -- primitive
types are encoded according to the underlying `Writer`, tuples and
structs are encoded by encoding their fields one-by-one, and enums are
encoded by first writing out the tag representing the variant and
then the contents.
However, there are some implementation details to be aware of:
* `isize`/`usize` are encoded as `i64`/`u64`, for portability.
* enums variants are encoded as a `u32` instead of a `usize`.
`u32` is enough for all practical uses.
* `str` is encoded as `(u64, &[u8])`, where the `u64` is the number of
bytes contained in the encoded string.
## Specification
Bincode's format will eventually be codified into a specification, along with
its configuration options and default configuration. In the meantime, here are
some frequently asked questions regarding use of the crate:
### Is Bincode suitable for storage?
The encoding format is stable across minor revisions, provided the same
configuration is used. This should ensure that later versions can still read
data produced by a previous versions of the library if no major version change
has occured.
Bincode is invariant over byte-order in the default configuration
(`bincode::options::DefaultOptions`), making an exchange between different
architectures possible. It is also rather space efficient, as it stores no
metadata like struct field names in the output format and writes long streams of
binary data without needing any potentially size-increasing encoding.
As a result, Bincode is suitable for storing data. Be aware that it does not
implement any sort of data versioning scheme or file headers, as these
features are outside the scope of this crate.
### Is Bincode suitable for untrusted inputs?
Bincode attempts to protect against hostile data. There is a maximum size
configuration available (`bincode::config::Bounded`), but not enabled in the
default configuration. Enabling it causes pre-allocation size to be limited to
prevent against memory exhaustion attacks.
Deserializing any incoming data will not cause undefined behavior or memory
issues, assuming that the deserialization code for the struct is safe itself.
Bincode can be used for untrusted inputs in the sense that it will not create a
security issues in your application, provided the configuration is changed to enable a
maximum size limit. Malicious inputs will fail upon deserialization.
### What is Bincode's MSRV (minimum supported Rust version)?
Bincode 1.0 maintains support for rust 1.18.0. Any changes to this are considered a breaking change for semver purposes.

View File

@ -0,0 +1,385 @@
// Copyright (c) 2015 Andrew Gallant
use std::io;
use std::io::Result;
use std::ptr::copy_nonoverlapping;
#[derive(Copy, Clone)]
pub struct LittleEndian;
#[derive(Copy, Clone)]
pub struct BigEndian;
#[cfg(target_endian = "little")]
pub type NativeEndian = LittleEndian;
#[cfg(target_endian = "big")]
pub type NativeEndian = BigEndian;
macro_rules! read_num_bytes {
($ty:ty, $size:expr, $src:expr, $which:ident) => {{
assert!($size == ::std::mem::size_of::<$ty>());
assert!($size <= $src.len());
let mut data: $ty = 0;
unsafe {
copy_nonoverlapping($src.as_ptr(), &mut data as *mut $ty as *mut u8, $size);
}
data.$which()
}};
}
macro_rules! write_num_bytes {
($ty:ty, $size:expr, $n:expr, $dst:expr, $which:ident) => {{
assert!($size <= $dst.len());
unsafe {
// N.B. https://github.com/rust-lang/rust/issues/22776
let bytes = *(&$n.$which() as *const _ as *const [u8; $size]);
copy_nonoverlapping((&bytes).as_ptr(), $dst.as_mut_ptr(), $size);
}
}};
}
impl ByteOrder for LittleEndian {
#[inline]
fn read_u16(buf: &[u8]) -> u16 {
read_num_bytes!(u16, 2, buf, to_le)
}
#[inline]
fn read_u32(buf: &[u8]) -> u32 {
read_num_bytes!(u32, 4, buf, to_le)
}
#[inline]
fn read_u64(buf: &[u8]) -> u64 {
read_num_bytes!(u64, 8, buf, to_le)
}
#[inline]
fn write_u16(buf: &mut [u8], n: u16) {
write_num_bytes!(u16, 2, n, buf, to_le);
}
#[inline]
fn write_u32(buf: &mut [u8], n: u32) {
write_num_bytes!(u32, 4, n, buf, to_le);
}
#[inline]
fn write_u64(buf: &mut [u8], n: u64) {
write_num_bytes!(u64, 8, n, buf, to_le);
}
serde_if_integer128! {
#[inline]
fn write_u128(buf: &mut [u8], n: u128) {
write_num_bytes!(u128, 16, n, buf, to_le);
}
#[inline]
fn read_u128(buf: &[u8]) -> u128 {
read_num_bytes!(u128, 16, buf, to_le)
}
}
}
impl ByteOrder for BigEndian {
#[inline]
fn read_u16(buf: &[u8]) -> u16 {
read_num_bytes!(u16, 2, buf, to_be)
}
#[inline]
fn read_u32(buf: &[u8]) -> u32 {
read_num_bytes!(u32, 4, buf, to_be)
}
#[inline]
fn read_u64(buf: &[u8]) -> u64 {
read_num_bytes!(u64, 8, buf, to_be)
}
#[inline]
fn write_u16(buf: &mut [u8], n: u16) {
write_num_bytes!(u16, 2, n, buf, to_be);
}
#[inline]
fn write_u32(buf: &mut [u8], n: u32) {
write_num_bytes!(u32, 4, n, buf, to_be);
}
#[inline]
fn write_u64(buf: &mut [u8], n: u64) {
write_num_bytes!(u64, 8, n, buf, to_be);
}
serde_if_integer128! {
#[inline]
fn write_u128(buf: &mut [u8], n: u128) {
write_num_bytes!(u128, 16, n, buf, to_be);
}
#[inline]
fn read_u128(buf: &[u8]) -> u128 {
read_num_bytes!(u128, 16, buf, to_be)
}
}
}
pub trait ByteOrder: Clone + Copy {
fn read_u16(buf: &[u8]) -> u16;
fn read_u32(buf: &[u8]) -> u32;
fn read_u64(buf: &[u8]) -> u64;
fn write_u16(buf: &mut [u8], n: u16);
fn write_u32(buf: &mut [u8], n: u32);
fn write_u64(buf: &mut [u8], n: u64);
#[inline]
fn read_i16(buf: &[u8]) -> i16 {
Self::read_u16(buf) as i16
}
#[inline]
fn read_i32(buf: &[u8]) -> i32 {
Self::read_u32(buf) as i32
}
#[inline]
fn read_i64(buf: &[u8]) -> i64 {
Self::read_u64(buf) as i64
}
#[inline]
fn read_f32(buf: &[u8]) -> f32 {
unsafe { *(&Self::read_u32(buf) as *const u32 as *const f32) }
}
#[inline]
fn read_f64(buf: &[u8]) -> f64 {
unsafe { *(&Self::read_u64(buf) as *const u64 as *const f64) }
}
#[inline]
fn write_i16(buf: &mut [u8], n: i16) {
Self::write_u16(buf, n as u16)
}
#[inline]
fn write_i32(buf: &mut [u8], n: i32) {
Self::write_u32(buf, n as u32)
}
#[inline]
fn write_i64(buf: &mut [u8], n: i64) {
Self::write_u64(buf, n as u64)
}
#[inline]
fn write_f32(buf: &mut [u8], n: f32) {
let n = unsafe { *(&n as *const f32 as *const u32) };
Self::write_u32(buf, n)
}
#[inline]
fn write_f64(buf: &mut [u8], n: f64) {
let n = unsafe { *(&n as *const f64 as *const u64) };
Self::write_u64(buf, n)
}
serde_if_integer128! {
fn read_u128(buf: &[u8]) -> u128;
fn write_u128(buf: &mut [u8], n: u128);
#[inline]
fn read_i128(buf: &[u8]) -> i128 {
Self::read_u128(buf) as i128
}
#[inline]
fn write_i128(buf: &mut [u8], n: i128) {
Self::write_u128(buf, n as u128)
}
}
}
pub trait ReadBytesExt: io::Read {
#[inline]
fn read_u8(&mut self) -> Result<u8> {
let mut buf = [0; 1];
try!(self.read_exact(&mut buf));
Ok(buf[0])
}
#[inline]
fn read_i8(&mut self) -> Result<i8> {
let mut buf = [0; 1];
try!(self.read_exact(&mut buf));
Ok(buf[0] as i8)
}
#[inline]
fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> {
let mut buf = [0; 2];
try!(self.read_exact(&mut buf));
Ok(T::read_u16(&buf))
}
#[inline]
fn read_i16<T: ByteOrder>(&mut self) -> Result<i16> {
let mut buf = [0; 2];
try!(self.read_exact(&mut buf));
Ok(T::read_i16(&buf))
}
#[inline]
fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> {
let mut buf = [0; 4];
try!(self.read_exact(&mut buf));
Ok(T::read_u32(&buf))
}
#[inline]
fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> {
let mut buf = [0; 4];
try!(self.read_exact(&mut buf));
Ok(T::read_i32(&buf))
}
#[inline]
fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> {
let mut buf = [0; 8];
try!(self.read_exact(&mut buf));
Ok(T::read_u64(&buf))
}
#[inline]
fn read_i64<T: ByteOrder>(&mut self) -> Result<i64> {
let mut buf = [0; 8];
try!(self.read_exact(&mut buf));
Ok(T::read_i64(&buf))
}
#[inline]
fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> {
let mut buf = [0; 4];
try!(self.read_exact(&mut buf));
Ok(T::read_f32(&buf))
}
#[inline]
fn read_f64<T: ByteOrder>(&mut self) -> Result<f64> {
let mut buf = [0; 8];
try!(self.read_exact(&mut buf));
Ok(T::read_f64(&buf))
}
serde_if_integer128! {
#[inline]
fn read_u128<T: ByteOrder>(&mut self) -> Result<u128> {
let mut buf = [0; 16];
try!(self.read_exact(&mut buf));
Ok(T::read_u128(&buf))
}
#[inline]
fn read_i128<T: ByteOrder>(&mut self) -> Result<i128> {
let mut buf = [0; 16];
try!(self.read_exact(&mut buf));
Ok(T::read_i128(&buf))
}
}
}
impl<R: io::Read + ?Sized> ReadBytesExt for R {}
pub trait WriteBytesExt: io::Write {
#[inline]
fn write_u8(&mut self, n: u8) -> Result<()> {
self.write_all(&[n])
}
#[inline]
fn write_i8(&mut self, n: i8) -> Result<()> {
self.write_all(&[n as u8])
}
#[inline]
fn write_u16<T: ByteOrder>(&mut self, n: u16) -> Result<()> {
let mut buf = [0; 2];
T::write_u16(&mut buf, n);
self.write_all(&buf)
}
#[inline]
fn write_i16<T: ByteOrder>(&mut self, n: i16) -> Result<()> {
let mut buf = [0; 2];
T::write_i16(&mut buf, n);
self.write_all(&buf)
}
#[inline]
fn write_u32<T: ByteOrder>(&mut self, n: u32) -> Result<()> {
let mut buf = [0; 4];
T::write_u32(&mut buf, n);
self.write_all(&buf)
}
#[inline]
fn write_i32<T: ByteOrder>(&mut self, n: i32) -> Result<()> {
let mut buf = [0; 4];
T::write_i32(&mut buf, n);
self.write_all(&buf)
}
#[inline]
fn write_u64<T: ByteOrder>(&mut self, n: u64) -> Result<()> {
let mut buf = [0; 8];
T::write_u64(&mut buf, n);
self.write_all(&buf)
}
#[inline]
fn write_i64<T: ByteOrder>(&mut self, n: i64) -> Result<()> {
let mut buf = [0; 8];
T::write_i64(&mut buf, n);
self.write_all(&buf)
}
#[inline]
fn write_f32<T: ByteOrder>(&mut self, n: f32) -> Result<()> {
let mut buf = [0; 4];
T::write_f32(&mut buf, n);
self.write_all(&buf)
}
#[inline]
fn write_f64<T: ByteOrder>(&mut self, n: f64) -> Result<()> {
let mut buf = [0; 8];
T::write_f64(&mut buf, n);
self.write_all(&buf)
}
serde_if_integer128! {
#[inline]
fn write_u128<T: ByteOrder>(&mut self, n: u128) -> Result<()> {
let mut buf = [0; 16];
T::write_u128(&mut buf, n);
self.write_all(&buf)
}
#[inline]
fn write_i128<T: ByteOrder>(&mut self, n: i128) -> Result<()> {
let mut buf = [0; 16];
T::write_i128(&mut buf, n);
self.write_all(&buf)
}
}
}
impl<W: io::Write + ?Sized> WriteBytesExt for W {}

View File

@ -0,0 +1,27 @@
pub trait BincodeByteOrder {
type Endian: ::byteorder::ByteOrder + 'static;
}
/// Little-endian byte ordering.
#[derive(Copy, Clone)]
pub struct LittleEndian;
/// Big-endian byte ordering.
#[derive(Copy, Clone)]
pub struct BigEndian;
/// The native byte ordering of the current system.
#[derive(Copy, Clone)]
pub struct NativeEndian;
impl BincodeByteOrder for LittleEndian {
type Endian = ::byteorder::LittleEndian;
}
impl BincodeByteOrder for BigEndian {
type Endian = ::byteorder::BigEndian;
}
impl BincodeByteOrder for NativeEndian {
type Endian = ::byteorder::NativeEndian;
}

View File

@ -0,0 +1,682 @@
use std::io::Write;
use std::mem::size_of;
use super::Options;
use de::read::BincodeRead;
use error::{ErrorKind, Result};
pub trait IntEncoding {
/// Gets the size (in bytes) that a value would be serialized to.
fn u16_size(n: u16) -> u64;
/// Gets the size (in bytes) that a value would be serialized to.
fn u32_size(n: u32) -> u64;
/// Gets the size (in bytes) that a value would be serialized to.
fn u64_size(n: u64) -> u64;
/// Gets the size (in bytes) that a value would be serialized to.
fn i16_size(n: i16) -> u64;
/// Gets the size (in bytes) that a value would be serialized to.
fn i32_size(n: i32) -> u64;
/// Gets the size (in bytes) that a value would be serialized to.
fn i64_size(n: i64) -> u64;
#[inline(always)]
fn len_size(len: usize) -> u64 {
Self::u64_size(len as u64)
}
/// Serializes a sequence length.
#[inline(always)]
fn serialize_len<W: Write, O: Options>(
ser: &mut ::ser::Serializer<W, O>,
len: usize,
) -> Result<()> {
Self::serialize_u64(ser, len as u64)
}
fn serialize_u16<W: Write, O: Options>(
ser: &mut ::ser::Serializer<W, O>,
val: u16,
) -> Result<()>;
fn serialize_u32<W: Write, O: Options>(
ser: &mut ::ser::Serializer<W, O>,
val: u32,
) -> Result<()>;
fn serialize_u64<W: Write, O: Options>(
ser: &mut ::ser::Serializer<W, O>,
val: u64,
) -> Result<()>;
fn serialize_i16<W: Write, O: Options>(
ser: &mut ::ser::Serializer<W, O>,
val: i16,
) -> Result<()>;
fn serialize_i32<W: Write, O: Options>(
ser: &mut ::ser::Serializer<W, O>,
val: i32,
) -> Result<()>;
fn serialize_i64<W: Write, O: Options>(
ser: &mut ::ser::Serializer<W, O>,
val: i64,
) -> Result<()>;
/// Deserializes a sequence length.
#[inline(always)]
fn deserialize_len<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::de::Deserializer<R, O>,
) -> Result<usize> {
Self::deserialize_u64(de).and_then(cast_u64_to_usize)
}
fn deserialize_u16<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::de::Deserializer<R, O>,
) -> Result<u16>;
fn deserialize_u32<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::de::Deserializer<R, O>,
) -> Result<u32>;
fn deserialize_u64<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::de::Deserializer<R, O>,
) -> Result<u64>;
fn deserialize_i16<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::de::Deserializer<R, O>,
) -> Result<i16>;
fn deserialize_i32<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::de::Deserializer<R, O>,
) -> Result<i32>;
fn deserialize_i64<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::de::Deserializer<R, O>,
) -> Result<i64>;
serde_if_integer128! {
fn u128_size(v: u128) -> u64;
fn i128_size(v: i128) -> u64;
fn serialize_u128<W: Write, O: Options>(
ser: &mut ::Serializer<W, O>,
val: u128,
) -> Result<()>;
fn deserialize_u128<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<u128>;
fn serialize_i128<W: Write, O: Options>(
ser: &mut ::Serializer<W, O>,
val: i128,
) -> Result<()>;
fn deserialize_i128<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<i128>;
}
}
/// Fixed-size integer encoding.
///
/// * Fixed size integers are encoded directly
/// * Enum discriminants are encoded as u32
/// * Lengths and usize are encoded as u64
#[derive(Copy, Clone)]
pub struct FixintEncoding;
/// Variable-size integer encoding (excepting [ui]8).
///
/// Encoding an unsigned integer v (of any type excepting u8) works as follows:
///
/// 1. If `u < 251`, encode it as a single byte with that value.
/// 2. If `251 <= u < 2**16`, encode it as a literal byte 251, followed by a u16 with value `u`.
/// 3. If `2**16 <= u < 2**32`, encode it as a literal byte 252, followed by a u32 with value `u`.
/// 4. If `2**32 <= u < 2**64`, encode it as a literal byte 253, followed by a u64 with value `u`.
/// 5. If `2**64 <= u < 2**128`, encode it as a literal byte 254, followed by a
/// u128 with value `u`.
///
/// Then, for signed integers, we first convert to unsigned using the zigzag algorithm,
/// and then encode them as we do for unsigned integers generally. The reason we use this
/// algorithm is that it encodes those values which are close to zero in less bytes; the
/// obvious algorithm, where we encode the cast values, gives a very large encoding for all
/// negative values.
///
/// The zigzag algorithm is defined as follows:
///
/// ```ignore
/// fn zigzag(v: Signed) -> Unsigned {
/// match v {
/// 0 => 0,
/// v if v < 0 => |v| * 2 - 1
/// v if v > 0 => v * 2
/// }
/// }
/// ```
///
/// And works such that:
///
/// ```ignore
/// assert_eq!(zigzag(0), 0);
/// assert_eq!(zigzag(-1), 1);
/// assert_eq!(zigzag(1), 2);
/// assert_eq!(zigzag(-2), 3);
/// assert_eq!(zigzag(2), 4);
/// assert_eq!(zigzag(i64::min_value()), u64::max_value());
/// ```
///
/// Note that u256 and the like are unsupported by this format; if and when they are added to the
/// language, they may be supported via the extension point given by the 255 byte.
#[derive(Copy, Clone)]
pub struct VarintEncoding;
const SINGLE_BYTE_MAX: u8 = 250;
const U16_BYTE: u8 = 251;
const U32_BYTE: u8 = 252;
const U64_BYTE: u8 = 253;
const U128_BYTE: u8 = 254;
const DESERIALIZE_EXTENSION_POINT_ERR: &str = r#"
Byte 255 is treated as an extension point; it should not be encoding anything.
Do you have a mismatched bincode version or configuration?
"#;
impl VarintEncoding {
fn varint_size(n: u64) -> u64 {
if n <= SINGLE_BYTE_MAX as u64 {
1
} else if n <= u16::max_value() as u64 {
(1 + size_of::<u16>()) as u64
} else if n <= u32::max_value() as u64 {
(1 + size_of::<u32>()) as u64
} else {
(1 + size_of::<u64>()) as u64
}
}
#[inline(always)]
fn zigzag_encode(n: i64) -> u64 {
if n < 0 {
// let's avoid the edge case of i64::min_value()
// !n is equal to `-n - 1`, so this is:
// !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
!(n as u64) * 2 + 1
} else {
(n as u64) * 2
}
}
#[inline(always)]
fn zigzag_decode(n: u64) -> i64 {
if n % 2 == 0 {
// positive number
(n / 2) as i64
} else {
// negative number
// !m * 2 + 1 = n
// !m * 2 = n - 1
// !m = (n - 1) / 2
// m = !((n - 1) / 2)
// since we have n is odd, we have floor(n / 2) = floor((n - 1) / 2)
!(n / 2) as i64
}
}
fn serialize_varint<W: Write, O: Options>(
ser: &mut ::ser::Serializer<W, O>,
n: u64,
) -> Result<()> {
if n <= SINGLE_BYTE_MAX as u64 {
ser.serialize_byte(n as u8)
} else if n <= u16::max_value() as u64 {
ser.serialize_byte(U16_BYTE)?;
ser.serialize_literal_u16(n as u16)
} else if n <= u32::max_value() as u64 {
ser.serialize_byte(U32_BYTE)?;
ser.serialize_literal_u32(n as u32)
} else {
ser.serialize_byte(U64_BYTE)?;
ser.serialize_literal_u64(n as u64)
}
}
fn deserialize_varint<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::de::Deserializer<R, O>,
) -> Result<u64> {
#[allow(ellipsis_inclusive_range_patterns)]
match de.deserialize_byte()? {
byte @ 0...SINGLE_BYTE_MAX => Ok(byte as u64),
U16_BYTE => Ok(de.deserialize_literal_u16()? as u64),
U32_BYTE => Ok(de.deserialize_literal_u32()? as u64),
U64_BYTE => de.deserialize_literal_u64(),
U128_BYTE => Err(Box::new(ErrorKind::Custom(
"Invalid value (u128 range): you may have a version or configuration disagreement?"
.to_string(),
))),
_ => Err(Box::new(ErrorKind::Custom(
DESERIALIZE_EXTENSION_POINT_ERR.to_string(),
))),
}
}
serde_if_integer128! {
// see zigzag_encode and zigzag_decode for implementation comments
#[inline(always)]
fn zigzag128_encode(n: i128) -> u128 {
if n < 0 {
!(n as u128) * 2 + 1
} else {
(n as u128) * 2
}
}
#[inline(always)]
fn zigzag128_decode(n: u128) -> i128 {
if n % 2 == 0 {
(n / 2) as i128
} else {
!(n / 2) as i128
}
}
fn varint128_size(n: u128) -> u64 {
if n <= SINGLE_BYTE_MAX as u128 {
1
} else if n <= u16::max_value() as u128 {
(1 + size_of::<u16>()) as u64
} else if n <= u32::max_value() as u128 {
(1 + size_of::<u32>()) as u64
} else if n <= u64::max_value() as u128 {
(1 + size_of::<u64>()) as u64
} else {
(1 + size_of::<u128>()) as u64
}
}
fn serialize_varint128<W: Write, O: Options>(
ser: &mut ::ser::Serializer<W, O>,
n: u128,
) -> Result<()> {
if n <= SINGLE_BYTE_MAX as u128 {
ser.serialize_byte(n as u8)
} else if n <= u16::max_value() as u128 {
ser.serialize_byte(U16_BYTE)?;
ser.serialize_literal_u16(n as u16)
} else if n <= u32::max_value() as u128 {
ser.serialize_byte(U32_BYTE)?;
ser.serialize_literal_u32(n as u32)
} else if n <= u64::max_value() as u128 {
ser.serialize_byte(U64_BYTE)?;
ser.serialize_literal_u64(n as u64)
} else {
ser.serialize_byte(U128_BYTE)?;
ser.serialize_literal_u128(n)
}
}
fn deserialize_varint128<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::de::Deserializer<R, O>,
) -> Result<u128> {
#[allow(ellipsis_inclusive_range_patterns)]
match de.deserialize_byte()? {
byte @ 0...SINGLE_BYTE_MAX => Ok(byte as u128),
U16_BYTE => Ok(de.deserialize_literal_u16()? as u128),
U32_BYTE => Ok(de.deserialize_literal_u32()? as u128),
U64_BYTE => Ok(de.deserialize_literal_u64()? as u128),
U128_BYTE => de.deserialize_literal_u128(),
_ => Err(Box::new(ErrorKind::Custom(DESERIALIZE_EXTENSION_POINT_ERR.to_string()))),
}
}
}
}
impl IntEncoding for FixintEncoding {
#[inline(always)]
fn u16_size(_: u16) -> u64 {
size_of::<u16>() as u64
}
#[inline(always)]
fn u32_size(_: u32) -> u64 {
size_of::<u32>() as u64
}
#[inline(always)]
fn u64_size(_: u64) -> u64 {
size_of::<u64>() as u64
}
#[inline(always)]
fn i16_size(_: i16) -> u64 {
size_of::<i16>() as u64
}
#[inline(always)]
fn i32_size(_: i32) -> u64 {
size_of::<i32>() as u64
}
#[inline(always)]
fn i64_size(_: i64) -> u64 {
size_of::<i64>() as u64
}
#[inline(always)]
fn serialize_u16<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: u16) -> Result<()> {
ser.serialize_literal_u16(val)
}
#[inline(always)]
fn serialize_u32<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: u32) -> Result<()> {
ser.serialize_literal_u32(val)
}
#[inline(always)]
fn serialize_u64<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: u64) -> Result<()> {
ser.serialize_literal_u64(val)
}
#[inline(always)]
fn serialize_i16<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: i16) -> Result<()> {
ser.serialize_literal_u16(val as u16)
}
#[inline(always)]
fn serialize_i32<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: i32) -> Result<()> {
ser.serialize_literal_u32(val as u32)
}
#[inline(always)]
fn serialize_i64<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: i64) -> Result<()> {
ser.serialize_literal_u64(val as u64)
}
#[inline(always)]
fn deserialize_u16<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<u16> {
de.deserialize_literal_u16()
}
#[inline(always)]
fn deserialize_u32<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<u32> {
de.deserialize_literal_u32()
}
#[inline(always)]
fn deserialize_u64<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<u64> {
de.deserialize_literal_u64()
}
#[inline(always)]
fn deserialize_i16<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<i16> {
Ok(de.deserialize_literal_u16()? as i16)
}
#[inline(always)]
fn deserialize_i32<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<i32> {
Ok(de.deserialize_literal_u32()? as i32)
}
#[inline(always)]
fn deserialize_i64<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<i64> {
Ok(de.deserialize_literal_u64()? as i64)
}
serde_if_integer128! {
#[inline(always)]
fn u128_size(_: u128) -> u64{
size_of::<u128>() as u64
}
#[inline(always)]
fn i128_size(_: i128) -> u64{
size_of::<i128>() as u64
}
#[inline(always)]
fn serialize_u128<W: Write, O: Options>(
ser: &mut ::Serializer<W, O>,
val: u128,
) -> Result<()> {
ser.serialize_literal_u128(val)
}
#[inline(always)]
fn serialize_i128<W: Write, O: Options>(
ser: &mut ::Serializer<W, O>,
val: i128,
) -> Result<()> {
ser.serialize_literal_u128(val as u128)
}
#[inline(always)]
fn deserialize_u128<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<u128> {
de.deserialize_literal_u128()
}
#[inline(always)]
fn deserialize_i128<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<i128> {
Ok(de.deserialize_literal_u128()? as i128)
}
}
}
impl IntEncoding for VarintEncoding {
#[inline(always)]
fn u16_size(n: u16) -> u64 {
Self::varint_size(n as u64)
}
#[inline(always)]
fn u32_size(n: u32) -> u64 {
Self::varint_size(n as u64)
}
#[inline(always)]
fn u64_size(n: u64) -> u64 {
Self::varint_size(n)
}
#[inline(always)]
fn i16_size(n: i16) -> u64 {
Self::varint_size(Self::zigzag_encode(n as i64))
}
#[inline(always)]
fn i32_size(n: i32) -> u64 {
Self::varint_size(Self::zigzag_encode(n as i64))
}
#[inline(always)]
fn i64_size(n: i64) -> u64 {
Self::varint_size(Self::zigzag_encode(n))
}
#[inline(always)]
fn serialize_u16<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: u16) -> Result<()> {
Self::serialize_varint(ser, val as u64)
}
#[inline(always)]
fn serialize_u32<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: u32) -> Result<()> {
Self::serialize_varint(ser, val as u64)
}
#[inline(always)]
fn serialize_u64<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: u64) -> Result<()> {
Self::serialize_varint(ser, val)
}
#[inline(always)]
fn serialize_i16<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: i16) -> Result<()> {
Self::serialize_varint(ser, Self::zigzag_encode(val as i64))
}
#[inline(always)]
fn serialize_i32<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: i32) -> Result<()> {
Self::serialize_varint(ser, Self::zigzag_encode(val as i64))
}
#[inline(always)]
fn serialize_i64<W: Write, O: Options>(ser: &mut ::Serializer<W, O>, val: i64) -> Result<()> {
Self::serialize_varint(ser, Self::zigzag_encode(val))
}
#[inline(always)]
fn deserialize_u16<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<u16> {
Self::deserialize_varint(de).and_then(cast_u64_to_u16)
}
#[inline(always)]
fn deserialize_u32<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<u32> {
Self::deserialize_varint(de).and_then(cast_u64_to_u32)
}
#[inline(always)]
fn deserialize_u64<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<u64> {
Self::deserialize_varint(de)
}
#[inline(always)]
fn deserialize_i16<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<i16> {
Self::deserialize_varint(de)
.map(Self::zigzag_decode)
.and_then(cast_i64_to_i16)
}
#[inline(always)]
fn deserialize_i32<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<i32> {
Self::deserialize_varint(de)
.map(Self::zigzag_decode)
.and_then(cast_i64_to_i32)
}
#[inline(always)]
fn deserialize_i64<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<i64> {
Self::deserialize_varint(de).map(Self::zigzag_decode)
}
serde_if_integer128! {
#[inline(always)]
fn u128_size(n: u128) -> u64 {
Self::varint128_size(n)
}
#[inline(always)]
fn i128_size(n: i128) -> u64 {
Self::varint128_size(Self::zigzag128_encode(n))
}
#[inline(always)]
fn serialize_u128<W: Write, O: Options>(
ser: &mut ::Serializer<W, O>,
val: u128,
) -> Result<()> {
Self::serialize_varint128(ser, val)
}
#[inline(always)]
fn serialize_i128<W: Write, O: Options>(
ser: &mut ::Serializer<W, O>,
val: i128,
) -> Result<()> {
Self::serialize_varint128(ser, Self::zigzag128_encode(val))
}
#[inline(always)]
fn deserialize_u128<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<u128> {
Self::deserialize_varint128(de)
}
#[inline(always)]
fn deserialize_i128<'de, R: BincodeRead<'de>, O: Options>(
de: &mut ::Deserializer<R, O>,
) -> Result<i128> {
Self::deserialize_varint128(de).map(Self::zigzag128_decode)
}
}
}
fn cast_u64_to_usize(n: u64) -> Result<usize> {
if n <= usize::max_value() as u64 {
Ok(n as usize)
} else {
Err(Box::new(ErrorKind::Custom(format!(
"Invalid size {}: sizes must fit in a usize (0 to {})",
n,
usize::max_value()
))))
}
}
fn cast_u64_to_u32(n: u64) -> Result<u32> {
if n <= u32::max_value() as u64 {
Ok(n as u32)
} else {
Err(Box::new(ErrorKind::Custom(format!(
"Invalid u32 {}: you may have a version disagreement?",
n,
))))
}
}
fn cast_u64_to_u16(n: u64) -> Result<u16> {
if n <= u16::max_value() as u64 {
Ok(n as u16)
} else {
Err(Box::new(ErrorKind::Custom(format!(
"Invalid u16 {}: you may have a version disagreement?",
n,
))))
}
}
fn cast_i64_to_i32(n: i64) -> Result<i32> {
if n <= i32::max_value() as i64 && n >= i32::min_value() as i64 {
Ok(n as i32)
} else {
Err(Box::new(ErrorKind::Custom(format!(
"Invalid i32 {}: you may have a version disagreement?",
n,
))))
}
}
fn cast_i64_to_i16(n: i64) -> Result<i16> {
if n <= i16::max_value() as i64 && n >= i16::min_value() as i64 {
Ok(n as i16)
} else {
Err(Box::new(ErrorKind::Custom(format!(
"Invalid i16 {}: you may have a version disagreement?",
n,
))))
}
}
#[cfg(test)]
mod test {
use super::VarintEncoding;
#[test]
fn test_zigzag_encode() {
let zigzag = VarintEncoding::zigzag_encode;
assert_eq!(zigzag(0), 0);
for x in 1..512 {
assert_eq!(zigzag(x), (x as u64) * 2);
assert_eq!(zigzag(-x), (x as u64) * 2 - 1);
}
}
#[test]
fn test_zigzag_decode() {
// zigzag'
let zigzagp = VarintEncoding::zigzag_decode;
for x in (0..512).map(|x| x * 2) {
assert_eq!(zigzagp(x), x as i64 / 2);
assert_eq!(zigzagp(x + 1), -(x as i64) / 2 - 1);
}
}
#[test]
fn test_zigzag_edge_cases() {
let (zigzag, zigzagp) = (VarintEncoding::zigzag_encode, VarintEncoding::zigzag_decode);
assert_eq!(zigzag(i64::max_value()), u64::max_value() - 1);
assert_eq!(zigzag(i64::min_value()), u64::max_value());
assert_eq!(zigzagp(u64::max_value() - 1), i64::max_value());
assert_eq!(zigzagp(u64::max_value()), i64::min_value());
}
}

View File

@ -1,364 +1,253 @@
use super::internal::{Bounded, Infinite, SizeLimit};
use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian};
use de::read::BincodeRead;
use error::Result;
use serde;
use std::io::{Read, Write};
use std::marker::PhantomData;
use {DeserializerAcceptor, SerializerAcceptor};
use self::EndianOption::*;
use self::LimitOption::*;
struct DefaultOptions(Infinite);
pub(crate) trait Options {
type Limit: SizeLimit + 'static;
type Endian: ByteOrder + 'static;
fn limit(&mut self) -> &mut Self::Limit;
}
pub(crate) trait OptionsExt: Options + Sized {
fn with_no_limit(self) -> WithOtherLimit<Self, Infinite> {
WithOtherLimit::new(self, Infinite)
}
fn with_limit(self, limit: u64) -> WithOtherLimit<Self, Bounded> {
WithOtherLimit::new(self, Bounded(limit))
}
fn with_little_endian(self) -> WithOtherEndian<Self, LittleEndian> {
WithOtherEndian::new(self)
}
fn with_big_endian(self) -> WithOtherEndian<Self, BigEndian> {
WithOtherEndian::new(self)
}
fn with_native_endian(self) -> WithOtherEndian<Self, NativeEndian> {
WithOtherEndian::new(self)
}
}
impl<'a, O: Options> Options for &'a mut O {
type Limit = O::Limit;
type Endian = O::Endian;
#[inline(always)]
fn limit(&mut self) -> &mut Self::Limit {
(*self).limit()
}
}
impl<T: Options> OptionsExt for T {}
impl DefaultOptions {
fn new() -> DefaultOptions {
DefaultOptions(Infinite)
}
}
impl Options for DefaultOptions {
type Limit = Infinite;
type Endian = LittleEndian;
#[inline(always)]
fn limit(&mut self) -> &mut Infinite {
&mut self.0
}
}
#[derive(Clone, Copy)]
enum LimitOption {
Unlimited,
Limited(u64),
}
#[derive(Clone, Copy)]
enum EndianOption {
Big,
Little,
Native,
}
/// A configuration builder whose options Bincode will use
/// while serializing and deserializing.
///
/// ### Options
/// Endianness: The endianness with which multi-byte integers will be read/written. *default: little endian*
/// Limit: The maximum number of bytes that will be read/written in a bincode serialize/deserialize. *default: unlimited*
///
/// ### Byte Limit Details
/// The purpose of byte-limiting is to prevent Denial-Of-Service attacks whereby malicious attackers get bincode
/// deserialization to crash your process by allocating too much memory or keeping a connection open for too long.
///
/// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
/// serialization that goes over the limit.
#[derive(Clone)]
pub struct Config {
limit: LimitOption,
endian: EndianOption,
}
pub(crate) struct WithOtherLimit<O: Options, L: SizeLimit> {
_options: O,
pub(crate) new_limit: L,
}
pub(crate) struct WithOtherEndian<O: Options, E: ByteOrder> {
options: O,
_endian: PhantomData<E>,
}
impl<O: Options, L: SizeLimit> WithOtherLimit<O, L> {
#[inline(always)]
pub(crate) fn new(options: O, limit: L) -> WithOtherLimit<O, L> {
WithOtherLimit {
_options: options,
new_limit: limit,
}
}
}
impl<O: Options, E: ByteOrder> WithOtherEndian<O, E> {
#[inline(always)]
pub(crate) fn new(options: O) -> WithOtherEndian<O, E> {
WithOtherEndian {
options: options,
_endian: PhantomData,
}
}
}
impl<O: Options, E: ByteOrder + 'static> Options for WithOtherEndian<O, E> {
type Limit = O::Limit;
type Endian = E;
#[inline(always)]
fn limit(&mut self) -> &mut O::Limit {
self.options.limit()
}
}
impl<O: Options, L: SizeLimit + 'static> Options for WithOtherLimit<O, L> {
type Limit = L;
type Endian = O::Endian;
fn limit(&mut self) -> &mut L {
&mut self.new_limit
}
}
macro_rules! config_map {
($self:expr, $opts:ident => $call:expr) => {
match ($self.limit, $self.endian) {
(Unlimited, Little) => {
let $opts = DefaultOptions::new().with_no_limit().with_little_endian();
$call
}
(Unlimited, Big) => {
let $opts = DefaultOptions::new().with_no_limit().with_big_endian();
$call
}
(Unlimited, Native) => {
let $opts = DefaultOptions::new().with_no_limit().with_native_endian();
$call
}
(Limited(l), Little) => {
let $opts = DefaultOptions::new().with_limit(l).with_little_endian();
$call
}
(Limited(l), Big) => {
let $opts = DefaultOptions::new().with_limit(l).with_big_endian();
$call
}
(Limited(l), Native) => {
let $opts = DefaultOptions::new().with_limit(l).with_native_endian();
$call
}
}
};
}
impl Config {
#[inline(always)]
pub(crate) fn new() -> Config {
Config {
limit: LimitOption::Unlimited,
endian: EndianOption::Little,
}
}
/// Sets the byte limit to be unlimited.
/// This is the default.
#[inline(always)]
pub fn no_limit(&mut self) -> &mut Self {
self.limit = LimitOption::Unlimited;
self
}
/// Sets the byte limit to `limit`.
#[inline(always)]
pub fn limit(&mut self, limit: u64) -> &mut Self {
self.limit = LimitOption::Limited(limit);
self
}
/// Sets the endianness to little-endian
/// This is the default.
#[inline(always)]
pub fn little_endian(&mut self) -> &mut Self {
self.endian = EndianOption::Little;
self
}
/// Sets the endianness to big-endian
#[inline(always)]
pub fn big_endian(&mut self) -> &mut Self {
self.endian = EndianOption::Big;
self
}
/// Sets the endianness to the the machine-native endianness
#[inline(always)]
pub fn native_endian(&mut self) -> &mut Self {
self.endian = EndianOption::Native;
self
}
/// Serializes a serializable object into a `Vec` of bytes using this configuration
#[inline(always)]
pub fn serialize<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<Vec<u8>> {
config_map!(self, opts => ::internal::serialize(t, opts))
}
/// Returns the size that an object would be if serialized using Bincode with this configuration
#[inline(always)]
pub fn serialized_size<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<u64> {
config_map!(self, opts => ::internal::serialized_size(t, opts))
}
/// Serializes an object directly into a `Writer` using this configuration
///
/// If the serialization would take more bytes than allowed by the size limit, an error
/// is returned and *no bytes* will be written into the `Writer`
#[inline(always)]
pub fn serialize_into<W: Write, T: ?Sized + serde::Serialize>(
&self,
w: W,
t: &T,
) -> Result<()> {
config_map!(self, opts => ::internal::serialize_into(w, t, opts))
}
/// Deserializes a slice of bytes into an instance of `T` using this configuration
#[inline(always)]
pub fn deserialize<'a, T: serde::Deserialize<'a>>(&self, bytes: &'a [u8]) -> Result<T> {
config_map!(self, opts => ::internal::deserialize(bytes, opts))
}
/// TODO: document
#[doc(hidden)]
#[inline(always)]
pub fn deserialize_in_place<'a, R, T>(&self, reader: R, place: &mut T) -> Result<()>
where
R: BincodeRead<'a>,
T: serde::de::Deserialize<'a>,
{
config_map!(self, opts => ::internal::deserialize_in_place(reader, opts, place))
}
/// Deserializes a slice of bytes with state `seed` using this configuration.
#[inline(always)]
pub fn deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>(
&self,
seed: T,
bytes: &'a [u8],
) -> Result<T::Value> {
config_map!(self, opts => ::internal::deserialize_seed(seed, bytes, opts))
}
/// Deserializes an object directly from a `Read`er using this configuration
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
pub fn deserialize_from<R: Read, T: serde::de::DeserializeOwned>(
&self,
reader: R,
) -> Result<T> {
config_map!(self, opts => ::internal::deserialize_from(reader, opts))
}
/// Deserializes an object directly from a `Read`er with state `seed` using this configuration
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
pub fn deserialize_from_seed<'a, R: Read, T: serde::de::DeserializeSeed<'a>>(
&self,
seed: T,
reader: R,
) -> Result<T::Value> {
config_map!(self, opts => ::internal::deserialize_from_seed(seed, reader, opts))
}
/// Deserializes an object from a custom `BincodeRead`er using the default configuration.
/// It is highly recommended to use `deserialize_from` unless you need to implement
/// `BincodeRead` for performance reasons.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
pub fn deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>(
&self,
reader: R,
) -> Result<T> {
config_map!(self, opts => ::internal::deserialize_from_custom(reader, opts))
}
/// Deserializes an object from a custom `BincodeRead`er with state `seed` using the default
/// configuration. It is highly recommended to use `deserialize_from` unless you need to
/// implement `BincodeRead` for performance reasons.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
pub fn deserialize_from_custom_seed<
'a,
R: BincodeRead<'a>,
T: serde::de::DeserializeSeed<'a>,
>(
&self,
seed: T,
reader: R,
) -> Result<T::Value> {
config_map!(self, opts => ::internal::deserialize_from_custom_seed(seed, reader, opts))
}
/// Executes the acceptor with a serde::Deserializer instance.
/// NOT A PART OF THE STABLE PUBLIC API
#[doc(hidden)]
pub fn with_deserializer<'a, A, R>(&self, reader: R, acceptor: A) -> A::Output
where
A: DeserializerAcceptor<'a>,
R: BincodeRead<'a>,
{
config_map!(self, opts => {
let mut deserializer = ::de::Deserializer::new(reader, opts);
acceptor.accept(&mut deserializer)
})
}
/// Executes the acceptor with a serde::Serializer instance.
/// NOT A PART OF THE STABLE PUBLIC API
#[doc(hidden)]
pub fn with_serializer<A, W>(&self, writer: W, acceptor: A) -> A::Output
where
A: SerializerAcceptor,
W: Write,
{
config_map!(self, opts => {
let mut serializer = ::ser::Serializer::new(writer, opts);
acceptor.accept(&mut serializer)
})
}
}
use std::io::{Read, Write};
use self::EndianOption::*;
use self::LimitOption::*;
use super::{DefaultOptions, Options};
use de::read::BincodeRead;
use error::Result;
use serde;
/// A configuration builder whose options Bincode will use
/// while serializing and deserializing.
///
/// ### Options
/// Endianness: The endianness with which multi-byte integers will be read/written. *default: little endian*
/// Limit: The maximum number of bytes that will be read/written in a bincode serialize/deserialize. *default: unlimited*
///
/// ### Byte Limit Details
/// The purpose of byte-limiting is to prevent Denial-Of-Service attacks whereby malicious attackers get bincode
/// deserialization to crash your process by allocating too much memory or keeping a connection open for too long.
///
/// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
/// serialization that goes over the limit.
#[derive(Clone, Debug)]
#[deprecated(
since = "1.3.0",
note = "please use the `DefaultOptions`/`Options` system instead"
)]
pub struct Config {
limit: LimitOption,
endian: EndianOption,
}
#[derive(Clone, Copy, Debug)]
enum LimitOption {
Unlimited,
Limited(u64),
}
#[derive(Clone, Copy, Debug)]
enum EndianOption {
Big,
Little,
Native,
}
macro_rules! config_map {
($self:expr, $opts:ident => $call:expr) => {
match ($self.limit, $self.endian) {
(Unlimited, Little) => {
let $opts = DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.with_no_limit()
.with_little_endian();
$call
}
(Unlimited, Big) => {
let $opts = DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.with_no_limit()
.with_big_endian();
$call
}
(Unlimited, Native) => {
let $opts = DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.with_no_limit()
.with_native_endian();
$call
}
(Limited(l), Little) => {
let $opts = DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.with_limit(l)
.with_little_endian();
$call
}
(Limited(l), Big) => {
let $opts = DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.with_limit(l)
.with_big_endian();
$call
}
(Limited(l), Native) => {
let $opts = DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.with_limit(l)
.with_native_endian();
$call
}
}
};
}
impl Config {
#[inline(always)]
pub(crate) fn new() -> Config {
Config {
limit: LimitOption::Unlimited,
endian: EndianOption::Little,
}
}
/// Sets the byte limit to be unlimited.
/// This is the default.
#[inline(always)]
pub fn no_limit(&mut self) -> &mut Self {
self.limit = LimitOption::Unlimited;
self
}
/// Sets the byte limit to `limit`.
#[inline(always)]
pub fn limit(&mut self, limit: u64) -> &mut Self {
self.limit = LimitOption::Limited(limit);
self
}
/// Sets the endianness to little-endian
/// This is the default.
#[inline(always)]
pub fn little_endian(&mut self) -> &mut Self {
self.endian = EndianOption::Little;
self
}
/// Sets the endianness to big-endian
#[inline(always)]
pub fn big_endian(&mut self) -> &mut Self {
self.endian = EndianOption::Big;
self
}
/// Sets the endianness to the the machine-native endianness
#[inline(always)]
pub fn native_endian(&mut self) -> &mut Self {
self.endian = EndianOption::Native;
self
}
/// Serializes a serializable object into a `Vec` of bytes using this configuration
#[inline(always)]
pub fn serialize<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<Vec<u8>> {
config_map!(self, opts => ::internal::serialize(t, opts))
}
/// Returns the size that an object would be if serialized using Bincode with this configuration
#[inline(always)]
pub fn serialized_size<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<u64> {
config_map!(self, opts => ::internal::serialized_size(t, opts))
}
/// Serializes an object directly into a `Writer` using this configuration
///
/// If the serialization would take more bytes than allowed by the size limit, an error
/// is returned and *no bytes* will be written into the `Writer`
#[inline(always)]
pub fn serialize_into<W: Write, T: ?Sized + serde::Serialize>(
&self,
w: W,
t: &T,
) -> Result<()> {
config_map!(self, opts => ::internal::serialize_into(w, t, opts))
}
/// Deserializes a slice of bytes into an instance of `T` using this configuration
#[inline(always)]
pub fn deserialize<'a, T: serde::Deserialize<'a>>(&self, bytes: &'a [u8]) -> Result<T> {
config_map!(self, opts => ::internal::deserialize(bytes, opts))
}
/// TODO: document
#[doc(hidden)]
#[inline(always)]
pub fn deserialize_in_place<'a, R, T>(&self, reader: R, place: &mut T) -> Result<()>
where
R: BincodeRead<'a>,
T: serde::de::Deserialize<'a>,
{
config_map!(self, opts => ::internal::deserialize_in_place(reader, opts, place))
}
/// Deserializes a slice of bytes with state `seed` using this configuration.
#[inline(always)]
pub fn deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>(
&self,
seed: T,
bytes: &'a [u8],
) -> Result<T::Value> {
config_map!(self, opts => ::internal::deserialize_seed(seed, bytes, opts))
}
/// Deserializes an object directly from a `Read`er using this configuration
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
pub fn deserialize_from<R: Read, T: serde::de::DeserializeOwned>(
&self,
reader: R,
) -> Result<T> {
config_map!(self, opts => ::internal::deserialize_from(reader, opts))
}
/// Deserializes an object directly from a `Read`er with state `seed` using this configuration
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
pub fn deserialize_from_seed<'a, R: Read, T: serde::de::DeserializeSeed<'a>>(
&self,
seed: T,
reader: R,
) -> Result<T::Value> {
config_map!(self, opts => ::internal::deserialize_from_seed(seed, reader, opts))
}
/// Deserializes an object from a custom `BincodeRead`er using the default configuration.
/// It is highly recommended to use `deserialize_from` unless you need to implement
/// `BincodeRead` for performance reasons.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
pub fn deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>(
&self,
reader: R,
) -> Result<T> {
config_map!(self, opts => ::internal::deserialize_from_custom(reader, opts))
}
/// Deserializes an object from a custom `BincodeRead`er with state `seed` using the default
/// configuration. It is highly recommended to use `deserialize_from` unless you need to
/// implement `BincodeRead` for performance reasons.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
pub fn deserialize_from_custom_seed<
'a,
R: BincodeRead<'a>,
T: serde::de::DeserializeSeed<'a>,
>(
&self,
seed: T,
reader: R,
) -> Result<T::Value> {
config_map!(self, opts => ::internal::deserialize_from_custom_seed(seed, reader, opts))
}
}

View File

@ -0,0 +1,49 @@
use error::{ErrorKind, Result};
/// A trait for stopping serialization and deserialization when a certain limit has been reached.
pub trait SizeLimit {
/// Tells the SizeLimit that a certain number of bytes has been
/// read or written. Returns Err if the limit has been exceeded.
fn add(&mut self, n: u64) -> Result<()>;
/// Returns the hard limit (if one exists)
fn limit(&self) -> Option<u64>;
}
/// A SizeLimit that restricts serialized or deserialized messages from
/// exceeding a certain byte length.
#[derive(Copy, Clone)]
pub struct Bounded(pub u64);
/// A SizeLimit without a limit!
/// Use this if you don't care about the size of encoded or decoded messages.
#[derive(Copy, Clone)]
pub struct Infinite;
impl SizeLimit for Bounded {
#[inline(always)]
fn add(&mut self, n: u64) -> Result<()> {
if self.0 >= n {
self.0 -= n;
Ok(())
} else {
Err(Box::new(ErrorKind::SizeLimit))
}
}
#[inline(always)]
fn limit(&self) -> Option<u64> {
Some(self.0)
}
}
impl SizeLimit for Infinite {
#[inline(always)]
fn add(&mut self, _: u64) -> Result<()> {
Ok(())
}
#[inline(always)]
fn limit(&self) -> Option<u64> {
None
}
}

View File

@ -0,0 +1,408 @@
//! `bincode` uses a Builder-pattern to configure the Serializers and Deserializers in this
//! crate. This means that if you need to customize the behavior of `bincode`, you should create an
//! instance of the `DefaultOptions` struct:
//!
//! ```rust
//! use bincode::Options;
//! let my_options = bincode::DefaultOptions::new();
//! ```
//!
//! # Options Struct vs bincode functions
//!
//! Due to historical reasons, the default options used by the `serialize()` and `deserialize()`
//! family of functions are different than the default options created by the `DefaultOptions` struct:
//!
//! | | Byte limit | Endianness | Int Encoding | Trailing Behavior |
//! |----------|------------|------------|--------------|-------------------|
//! | struct | Unlimited | Little | Varint | Reject |
//! | function | Unlimited | Little | Fixint | Allow |
//!
//! This means that if you want to use the `Serialize` / `Deserialize` structs with the same
//! settings as the functions, you should adjust the `DefaultOptions` struct like so:
//!
//! ```rust
//! use bincode::Options;
//! let my_options = bincode::DefaultOptions::new()
//! .with_fixint_encoding()
//! .allow_trailing_bytes();
//! ```
use de::read::BincodeRead;
use error::Result;
use serde;
use std::io::{Read, Write};
use std::marker::PhantomData;
pub(crate) use self::endian::BincodeByteOrder;
pub(crate) use self::int::IntEncoding;
pub(crate) use self::internal::*;
pub(crate) use self::limit::SizeLimit;
pub(crate) use self::trailing::TrailingBytes;
pub use self::endian::{BigEndian, LittleEndian, NativeEndian};
pub use self::int::{FixintEncoding, VarintEncoding};
pub use self::legacy::*;
pub use self::limit::{Bounded, Infinite};
pub use self::trailing::{AllowTrailing, RejectTrailing};
mod endian;
mod int;
mod legacy;
mod limit;
mod trailing;
/// The default options for bincode serialization/deserialization.
///
/// ### Defaults
/// By default bincode will use little-endian encoding for multi-byte integers, and will not
/// limit the number of serialized/deserialized bytes.
///
/// ### Configuring `DefaultOptions`
///
/// `DefaultOptions` implements the [Options] trait, which means it exposes functions to change the behavior of bincode.
///
/// For example, if you wanted to limit the bincode deserializer to 1 kilobyte of user input:
///
/// ```rust
/// use bincode::Options;
/// let my_options = bincode::DefaultOptions::new().with_limit(1024);
/// ```
///
/// ### DefaultOptions struct vs. functions
///
/// The default configuration used by this struct is not the same as that used by the bincode
/// helper functions in the root of this crate. See the
/// [config](index.html#options-struct-vs-bincode-functions) module for more details
#[derive(Copy, Clone)]
pub struct DefaultOptions(Infinite);
impl DefaultOptions {
/// Get a default configuration object.
///
/// ### Default Configuration:
///
/// | Byte limit | Endianness | Int Encoding | Trailing Behavior |
/// |------------|------------|--------------|-------------------|
/// | Unlimited | Little | Varint | Reject |
pub fn new() -> DefaultOptions {
DefaultOptions(Infinite)
}
}
impl Default for DefaultOptions {
fn default() -> Self {
Self::new()
}
}
impl InternalOptions for DefaultOptions {
type Limit = Infinite;
type Endian = LittleEndian;
type IntEncoding = VarintEncoding;
type Trailing = RejectTrailing;
#[inline(always)]
fn limit(&mut self) -> &mut Infinite {
&mut self.0
}
}
/// A configuration builder trait whose options Bincode will use
/// while serializing and deserializing.
///
/// ### Options
/// Endianness: The endianness with which multi-byte integers will be read/written. *default: little endian*
///
/// Limit: The maximum number of bytes that will be read/written in a bincode serialize/deserialize. *default: unlimited*
///
/// Int Encoding: The encoding used for numbers, enum discriminants, and lengths. *default: varint*
///
/// Trailing Behavior: The behavior when there are trailing bytes left over in a slice after deserialization. *default: reject*
///
/// ### Byte Limit Details
/// The purpose of byte-limiting is to prevent Denial-Of-Service attacks whereby malicious attackers get bincode
/// deserialization to crash your process by allocating too much memory or keeping a connection open for too long.
///
/// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
/// serialization that goes over the limit.
pub trait Options: InternalOptions + Sized {
/// Sets the byte limit to be unlimited.
/// This is the default.
fn with_no_limit(self) -> WithOtherLimit<Self, Infinite> {
WithOtherLimit::new(self, Infinite)
}
/// Sets the byte limit to `limit`.
fn with_limit(self, limit: u64) -> WithOtherLimit<Self, Bounded> {
WithOtherLimit::new(self, Bounded(limit))
}
/// Sets the endianness to little-endian
/// This is the default.
fn with_little_endian(self) -> WithOtherEndian<Self, LittleEndian> {
WithOtherEndian::new(self)
}
/// Sets the endianness to big-endian
fn with_big_endian(self) -> WithOtherEndian<Self, BigEndian> {
WithOtherEndian::new(self)
}
/// Sets the endianness to the the machine-native endianness
fn with_native_endian(self) -> WithOtherEndian<Self, NativeEndian> {
WithOtherEndian::new(self)
}
/// Sets the length encoding to varint
fn with_varint_encoding(self) -> WithOtherIntEncoding<Self, VarintEncoding> {
WithOtherIntEncoding::new(self)
}
/// Sets the length encoding to be fixed
fn with_fixint_encoding(self) -> WithOtherIntEncoding<Self, FixintEncoding> {
WithOtherIntEncoding::new(self)
}
/// Sets the deserializer to reject trailing bytes
fn reject_trailing_bytes(self) -> WithOtherTrailing<Self, RejectTrailing> {
WithOtherTrailing::new(self)
}
/// Sets the deserializer to allow trailing bytes
fn allow_trailing_bytes(self) -> WithOtherTrailing<Self, AllowTrailing> {
WithOtherTrailing::new(self)
}
/// Serializes a serializable object into a `Vec` of bytes using this configuration
#[inline(always)]
fn serialize<S: ?Sized + serde::Serialize>(self, t: &S) -> Result<Vec<u8>> {
::internal::serialize(t, self)
}
/// Returns the size that an object would be if serialized using Bincode with this configuration
#[inline(always)]
fn serialized_size<T: ?Sized + serde::Serialize>(self, t: &T) -> Result<u64> {
::internal::serialized_size(t, self)
}
/// Serializes an object directly into a `Writer` using this configuration
///
/// If the serialization would take more bytes than allowed by the size limit, an error
/// is returned and *no bytes* will be written into the `Writer`
#[inline(always)]
fn serialize_into<W: Write, T: ?Sized + serde::Serialize>(self, w: W, t: &T) -> Result<()> {
::internal::serialize_into(w, t, self)
}
/// Deserializes a slice of bytes into an instance of `T` using this configuration
#[inline(always)]
fn deserialize<'a, T: serde::Deserialize<'a>>(self, bytes: &'a [u8]) -> Result<T> {
::internal::deserialize(bytes, self)
}
/// TODO: document
#[doc(hidden)]
#[inline(always)]
fn deserialize_in_place<'a, R, T>(self, reader: R, place: &mut T) -> Result<()>
where
R: BincodeRead<'a>,
T: serde::de::Deserialize<'a>,
{
::internal::deserialize_in_place(reader, self, place)
}
/// Deserializes a slice of bytes with state `seed` using this configuration.
#[inline(always)]
fn deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>(
self,
seed: T,
bytes: &'a [u8],
) -> Result<T::Value> {
::internal::deserialize_seed(seed, bytes, self)
}
/// Deserializes an object directly from a `Read`er using this configuration
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
fn deserialize_from<R: Read, T: serde::de::DeserializeOwned>(self, reader: R) -> Result<T> {
::internal::deserialize_from(reader, self)
}
/// Deserializes an object directly from a `Read`er with state `seed` using this configuration
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
fn deserialize_from_seed<'a, R: Read, T: serde::de::DeserializeSeed<'a>>(
self,
seed: T,
reader: R,
) -> Result<T::Value> {
::internal::deserialize_from_seed(seed, reader, self)
}
/// Deserializes an object from a custom `BincodeRead`er using the default configuration.
/// It is highly recommended to use `deserialize_from` unless you need to implement
/// `BincodeRead` for performance reasons.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
fn deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>(
self,
reader: R,
) -> Result<T> {
::internal::deserialize_from_custom(reader, self)
}
/// Deserializes an object from a custom `BincodeRead`er with state `seed` using the default
/// configuration. It is highly recommended to use `deserialize_from` unless you need to
/// implement `BincodeRead` for performance reasons.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
#[inline(always)]
fn deserialize_from_custom_seed<'a, R: BincodeRead<'a>, T: serde::de::DeserializeSeed<'a>>(
self,
seed: T,
reader: R,
) -> Result<T::Value> {
::internal::deserialize_from_custom_seed(seed, reader, self)
}
}
impl<T: InternalOptions> Options for T {}
/// A configuration struct with a user-specified byte limit
#[derive(Clone, Copy)]
pub struct WithOtherLimit<O: Options, L: SizeLimit> {
_options: O,
pub(crate) new_limit: L,
}
/// A configuration struct with a user-specified endian order
#[derive(Clone, Copy)]
pub struct WithOtherEndian<O: Options, E: BincodeByteOrder> {
options: O,
_endian: PhantomData<E>,
}
/// A configuration struct with a user-specified length encoding
#[derive(Clone, Copy)]
pub struct WithOtherIntEncoding<O: Options, I: IntEncoding> {
options: O,
_length: PhantomData<I>,
}
/// A configuration struct with a user-specified trailing bytes behavior.
#[derive(Clone, Copy)]
pub struct WithOtherTrailing<O: Options, T: TrailingBytes> {
options: O,
_trailing: PhantomData<T>,
}
impl<O: Options, L: SizeLimit> WithOtherLimit<O, L> {
#[inline(always)]
pub(crate) fn new(options: O, limit: L) -> WithOtherLimit<O, L> {
WithOtherLimit {
_options: options,
new_limit: limit,
}
}
}
impl<O: Options, E: BincodeByteOrder> WithOtherEndian<O, E> {
#[inline(always)]
pub(crate) fn new(options: O) -> WithOtherEndian<O, E> {
WithOtherEndian {
options,
_endian: PhantomData,
}
}
}
impl<O: Options, I: IntEncoding> WithOtherIntEncoding<O, I> {
#[inline(always)]
pub(crate) fn new(options: O) -> WithOtherIntEncoding<O, I> {
WithOtherIntEncoding {
options,
_length: PhantomData,
}
}
}
impl<O: Options, T: TrailingBytes> WithOtherTrailing<O, T> {
#[inline(always)]
pub(crate) fn new(options: O) -> WithOtherTrailing<O, T> {
WithOtherTrailing {
options,
_trailing: PhantomData,
}
}
}
impl<O: Options, E: BincodeByteOrder + 'static> InternalOptions for WithOtherEndian<O, E> {
type Limit = O::Limit;
type Endian = E;
type IntEncoding = O::IntEncoding;
type Trailing = O::Trailing;
#[inline(always)]
fn limit(&mut self) -> &mut O::Limit {
self.options.limit()
}
}
impl<O: Options, L: SizeLimit + 'static> InternalOptions for WithOtherLimit<O, L> {
type Limit = L;
type Endian = O::Endian;
type IntEncoding = O::IntEncoding;
type Trailing = O::Trailing;
fn limit(&mut self) -> &mut L {
&mut self.new_limit
}
}
impl<O: Options, I: IntEncoding + 'static> InternalOptions for WithOtherIntEncoding<O, I> {
type Limit = O::Limit;
type Endian = O::Endian;
type IntEncoding = I;
type Trailing = O::Trailing;
fn limit(&mut self) -> &mut O::Limit {
self.options.limit()
}
}
impl<O: Options, T: TrailingBytes + 'static> InternalOptions for WithOtherTrailing<O, T> {
type Limit = O::Limit;
type Endian = O::Endian;
type IntEncoding = O::IntEncoding;
type Trailing = T;
fn limit(&mut self) -> &mut O::Limit {
self.options.limit()
}
}
mod internal {
use super::*;
pub trait InternalOptions {
type Limit: SizeLimit + 'static;
type Endian: BincodeByteOrder + 'static;
type IntEncoding: IntEncoding + 'static;
type Trailing: TrailingBytes + 'static;
fn limit(&mut self) -> &mut Self::Limit;
}
impl<'a, O: InternalOptions> InternalOptions for &'a mut O {
type Limit = O::Limit;
type Endian = O::Endian;
type IntEncoding = O::IntEncoding;
type Trailing = O::Trailing;
#[inline(always)]
fn limit(&mut self) -> &mut Self::Limit {
(*self).limit()
}
}
}

View File

@ -0,0 +1,37 @@
use de::read::SliceReader;
use {ErrorKind, Result};
/// A trait for erroring deserialization if not all bytes were read.
pub trait TrailingBytes {
/// Checks a given slice reader to determine if deserialization used all bytes in the slice.
fn check_end(reader: &SliceReader) -> Result<()>;
}
/// A TrailingBytes config that will allow trailing bytes in slices after deserialization.
#[derive(Copy, Clone)]
pub struct AllowTrailing;
/// A TrailingBytes config that will cause bincode to produce an error if bytes are left over in the slice when deserialization is complete.
#[derive(Copy, Clone)]
pub struct RejectTrailing;
impl TrailingBytes for AllowTrailing {
#[inline(always)]
fn check_end(_reader: &SliceReader) -> Result<()> {
Ok(())
}
}
impl TrailingBytes for RejectTrailing {
#[inline(always)]
fn check_end(reader: &SliceReader) -> Result<()> {
if reader.is_finished() {
Ok(())
} else {
Err(Box::new(ErrorKind::Custom(
"Slice had bytes remaining after deserialization".to_string(),
)))
}
}
}

View File

@ -1,465 +1,515 @@
use config::Options;
use std::io::Read;
use self::read::BincodeRead;
use byteorder::ReadBytesExt;
use internal::SizeLimit;
use serde;
use serde::de::Error as DeError;
use serde::de::IntoDeserializer;
use {Error, ErrorKind, Result};
pub mod read;
/// A Deserializer that reads bytes from a buffer.
///
/// This struct should rarely be used.
/// In most cases, prefer the `deserialize_from` function.
///
/// The ByteOrder that is chosen will impact the endianness that
/// is used to read integers out of the reader.
///
/// ```ignore
/// let d = Deserializer::new(&mut some_reader, SizeLimit::new());
/// serde::Deserialize::deserialize(&mut deserializer);
/// let bytes_read = d.bytes_read();
/// ```
pub(crate) struct Deserializer<R, O: Options> {
reader: R,
options: O,
}
impl<'de, R: BincodeRead<'de>, O: Options> Deserializer<R, O> {
/// Creates a new Deserializer with a given `Read`er and a size_limit.
pub(crate) fn new(r: R, options: O) -> Deserializer<R, O> {
Deserializer {
reader: r,
options: options,
}
}
fn read_bytes(&mut self, count: u64) -> Result<()> {
self.options.limit().add(count)
}
fn read_type<T>(&mut self) -> Result<()> {
use std::mem::size_of;
self.read_bytes(size_of::<T>() as u64)
}
fn read_vec(&mut self) -> Result<Vec<u8>> {
let len: usize = try!(serde::Deserialize::deserialize(&mut *self));
self.read_bytes(len as u64)?;
self.reader.get_byte_buffer(len)
}
fn read_string(&mut self) -> Result<String> {
let vec = self.read_vec()?;
String::from_utf8(vec).map_err(|e| ErrorKind::InvalidUtf8Encoding(e.utf8_error()).into())
}
}
macro_rules! impl_nums {
($ty:ty, $dser_method:ident, $visitor_method:ident, $reader_method:ident) => {
#[inline]
fn $dser_method<V>(self, visitor: V) -> Result<V::Value>
where V: serde::de::Visitor<'de>,
{
try!(self.read_type::<$ty>());
let value = try!(self.reader.$reader_method::<O::Endian>());
visitor.$visitor_method(value)
}
}
}
impl<'de, 'a, R, O> serde::Deserializer<'de> for &'a mut Deserializer<R, O>
where
R: BincodeRead<'de>,
O: Options,
{
type Error = Error;
#[inline]
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
Err(Box::new(ErrorKind::DeserializeAnyNotSupported))
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let value: u8 = try!(serde::Deserialize::deserialize(self));
match value {
1 => visitor.visit_bool(true),
0 => visitor.visit_bool(false),
value => Err(ErrorKind::InvalidBoolEncoding(value).into()),
}
}
impl_nums!(u16, deserialize_u16, visit_u16, read_u16);
impl_nums!(u32, deserialize_u32, visit_u32, read_u32);
impl_nums!(u64, deserialize_u64, visit_u64, read_u64);
impl_nums!(i16, deserialize_i16, visit_i16, read_i16);
impl_nums!(i32, deserialize_i32, visit_i32, read_i32);
impl_nums!(i64, deserialize_i64, visit_i64, read_i64);
impl_nums!(f32, deserialize_f32, visit_f32, read_f32);
impl_nums!(f64, deserialize_f64, visit_f64, read_f64);
serde_if_integer128! {
impl_nums!(u128, deserialize_u128, visit_u128, read_u128);
impl_nums!(i128, deserialize_i128, visit_i128, read_i128);
}
#[inline]
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
try!(self.read_type::<u8>());
visitor.visit_u8(try!(self.reader.read_u8()))
}
#[inline]
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
try!(self.read_type::<i8>());
visitor.visit_i8(try!(self.reader.read_i8()))
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
use std::str;
let error = || ErrorKind::InvalidCharEncoding.into();
let mut buf = [0u8; 4];
// Look at the first byte to see how many bytes must be read
let _ = try!(self.reader.read_exact(&mut buf[..1]));
let width = utf8_char_width(buf[0]);
if width == 1 {
return visitor.visit_char(buf[0] as char);
}
if width == 0 {
return Err(error());
}
if self.reader.read_exact(&mut buf[1..width]).is_err() {
return Err(error());
}
let res = try!(
str::from_utf8(&buf[..width])
.ok()
.and_then(|s| s.chars().next())
.ok_or(error())
);
visitor.visit_char(res)
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let len: usize = try!(serde::Deserialize::deserialize(&mut *self));
try!(self.read_bytes(len as u64));
self.reader.forward_read_str(len, visitor)
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_string(try!(self.read_string()))
}
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let len: usize = try!(serde::Deserialize::deserialize(&mut *self));
try!(self.read_bytes(len as u64));
self.reader.forward_read_bytes(len, visitor)
}
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_byte_buf(try!(self.read_vec()))
}
fn deserialize_enum<V>(
self,
_enum: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
impl<'de, 'a, R: 'a, O> serde::de::EnumAccess<'de> for &'a mut Deserializer<R, O>
where
R: BincodeRead<'de>,
O: Options,
{
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
where
V: serde::de::DeserializeSeed<'de>,
{
let idx: u32 = try!(serde::de::Deserialize::deserialize(&mut *self));
let val: Result<_> = seed.deserialize(idx.into_deserializer());
Ok((try!(val), self))
}
}
visitor.visit_enum(self)
}
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
struct Access<'a, R: Read + 'a, O: Options + 'a> {
deserializer: &'a mut Deserializer<R, O>,
len: usize,
}
impl<'de, 'a, 'b: 'a, R: BincodeRead<'de> + 'b, O: Options> serde::de::SeqAccess<'de>
for Access<'a, R, O>
{
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
where
T: serde::de::DeserializeSeed<'de>,
{
if self.len > 0 {
self.len -= 1;
let value = try!(serde::de::DeserializeSeed::deserialize(
seed,
&mut *self.deserializer,
));
Ok(Some(value))
} else {
Ok(None)
}
}
fn size_hint(&self) -> Option<usize> {
Some(self.len)
}
}
visitor.visit_seq(Access {
deserializer: self,
len: len,
})
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let value: u8 = try!(serde::de::Deserialize::deserialize(&mut *self));
match value {
0 => visitor.visit_none(),
1 => visitor.visit_some(&mut *self),
v => Err(ErrorKind::InvalidTagEncoding(v as usize).into()),
}
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let len = try!(serde::Deserialize::deserialize(&mut *self));
self.deserialize_tuple(len, visitor)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
struct Access<'a, R: Read + 'a, O: Options + 'a> {
deserializer: &'a mut Deserializer<R, O>,
len: usize,
}
impl<'de, 'a, 'b: 'a, R: BincodeRead<'de> + 'b, O: Options> serde::de::MapAccess<'de>
for Access<'a, R, O>
{
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: serde::de::DeserializeSeed<'de>,
{
if self.len > 0 {
self.len -= 1;
let key = try!(serde::de::DeserializeSeed::deserialize(
seed,
&mut *self.deserializer,
));
Ok(Some(key))
} else {
Ok(None)
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: serde::de::DeserializeSeed<'de>,
{
let value = try!(serde::de::DeserializeSeed::deserialize(
seed,
&mut *self.deserializer,
));
Ok(value)
}
fn size_hint(&self) -> Option<usize> {
Some(self.len)
}
}
let len = try!(serde::Deserialize::deserialize(&mut *self));
visitor.visit_map(Access {
deserializer: self,
len: len,
})
}
fn deserialize_struct<V>(
self,
_name: &str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_tuple(fields.len(), visitor)
}
fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let message = "Bincode does not support Deserializer::deserialize_identifier";
Err(Error::custom(message))
}
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}
fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_tuple(len, visitor)
}
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let message = "Bincode does not support Deserializer::deserialize_ignored_any";
Err(Error::custom(message))
}
fn is_human_readable(&self) -> bool {
false
}
}
impl<'de, 'a, R, O> serde::de::VariantAccess<'de> for &'a mut Deserializer<R, O>
where
R: BincodeRead<'de>,
O: Options,
{
type Error = Error;
fn unit_variant(self) -> Result<()> {
Ok(())
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
where
T: serde::de::DeserializeSeed<'de>,
{
serde::de::DeserializeSeed::deserialize(seed, self)
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
serde::de::Deserializer::deserialize_tuple(self, len, visitor)
}
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
serde::de::Deserializer::deserialize_tuple(self, fields.len(), visitor)
}
}
static UTF8_CHAR_WIDTH: [u8; 256] = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, // 0x1F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, // 0x3F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, // 0x5F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, // 0x7F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // 0x9F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // 0xBF
0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, // 0xDF
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF
4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF
];
// This function is a copy of core::str::utf8_char_width
fn utf8_char_width(b: u8) -> usize {
UTF8_CHAR_WIDTH[b as usize] as usize
}
use config::{BincodeByteOrder, Options};
use std::io::Read;
use self::read::{BincodeRead, IoReader, SliceReader};
use byteorder::ReadBytesExt;
use config::{IntEncoding, SizeLimit};
use serde;
use serde::de::Error as DeError;
use serde::de::IntoDeserializer;
use {Error, ErrorKind, Result};
/// Specialized ways to read data into bincode.
pub mod read;
/// A Deserializer that reads bytes from a buffer.
///
/// This struct should rarely be used.
/// In most cases, prefer the `deserialize_from` function.
///
/// The ByteOrder that is chosen will impact the endianness that
/// is used to read integers out of the reader.
///
/// ```ignore
/// let d = Deserializer::new(&mut some_reader, SizeLimit::new());
/// serde::Deserialize::deserialize(&mut deserializer);
/// let bytes_read = d.bytes_read();
/// ```
pub struct Deserializer<R, O: Options> {
pub(crate) reader: R,
options: O,
}
macro_rules! impl_deserialize_literal {
($name:ident : $ty:ty = $read:ident()) => {
#[inline]
pub(crate) fn $name(&mut self) -> Result<$ty> {
self.read_literal_type::<$ty>()?;
self.reader
.$read::<<O::Endian as BincodeByteOrder>::Endian>()
.map_err(Into::into)
}
};
}
impl<'de, IR: Read, O: Options> Deserializer<IoReader<IR>, O> {
/// Creates a new Deserializer with a given `Read`er and options.
pub fn with_reader(r: IR, options: O) -> Self {
Deserializer {
reader: IoReader::new(r),
options,
}
}
}
impl<'de, O: Options> Deserializer<SliceReader<'de>, O> {
/// Creates a new Deserializer that will read from the given slice.
pub fn from_slice(slice: &'de [u8], options: O) -> Self {
Deserializer {
reader: SliceReader::new(slice),
options,
}
}
}
impl<'de, R: BincodeRead<'de>, O: Options> Deserializer<R, O> {
/// Creates a new Deserializer with the given `BincodeRead`er
pub fn with_bincode_read(r: R, options: O) -> Deserializer<R, O> {
Deserializer { reader: r, options }
}
pub(crate) fn deserialize_byte(&mut self) -> Result<u8> {
self.read_literal_type::<u8>()?;
self.reader.read_u8().map_err(Into::into)
}
impl_deserialize_literal! { deserialize_literal_u16 : u16 = read_u16() }
impl_deserialize_literal! { deserialize_literal_u32 : u32 = read_u32() }
impl_deserialize_literal! { deserialize_literal_u64 : u64 = read_u64() }
serde_if_integer128! {
impl_deserialize_literal! { deserialize_literal_u128 : u128 = read_u128() }
}
fn read_bytes(&mut self, count: u64) -> Result<()> {
self.options.limit().add(count)
}
fn read_literal_type<T>(&mut self) -> Result<()> {
use std::mem::size_of;
self.read_bytes(size_of::<T>() as u64)
}
fn read_vec(&mut self) -> Result<Vec<u8>> {
let len = O::IntEncoding::deserialize_len(self)?;
self.read_bytes(len as u64)?;
self.reader.get_byte_buffer(len)
}
fn read_string(&mut self) -> Result<String> {
let vec = self.read_vec()?;
String::from_utf8(vec).map_err(|e| ErrorKind::InvalidUtf8Encoding(e.utf8_error()).into())
}
}
macro_rules! impl_deserialize_int {
($name:ident = $visitor_method:ident ($dser_method:ident)) => {
#[inline]
fn $name<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.$visitor_method(O::IntEncoding::$dser_method(self)?)
}
};
}
impl<'de, 'a, R, O> serde::Deserializer<'de> for &'a mut Deserializer<R, O>
where
R: BincodeRead<'de>,
O: Options,
{
type Error = Error;
#[inline]
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
Err(Box::new(ErrorKind::DeserializeAnyNotSupported))
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
match self.deserialize_byte()? {
1 => visitor.visit_bool(true),
0 => visitor.visit_bool(false),
value => Err(ErrorKind::InvalidBoolEncoding(value).into()),
}
}
impl_deserialize_int!(deserialize_u16 = visit_u16(deserialize_u16));
impl_deserialize_int!(deserialize_u32 = visit_u32(deserialize_u32));
impl_deserialize_int!(deserialize_u64 = visit_u64(deserialize_u64));
impl_deserialize_int!(deserialize_i16 = visit_i16(deserialize_i16));
impl_deserialize_int!(deserialize_i32 = visit_i32(deserialize_i32));
impl_deserialize_int!(deserialize_i64 = visit_i64(deserialize_i64));
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
self.read_literal_type::<f32>()?;
let value = self
.reader
.read_f32::<<O::Endian as BincodeByteOrder>::Endian>()?;
visitor.visit_f32(value)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
self.read_literal_type::<f64>()?;
let value = self
.reader
.read_f64::<<O::Endian as BincodeByteOrder>::Endian>()?;
visitor.visit_f64(value)
}
serde_if_integer128! {
impl_deserialize_int!(deserialize_u128 = visit_u128(deserialize_u128));
impl_deserialize_int!(deserialize_i128 = visit_i128(deserialize_i128));
}
#[inline]
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_u8(self.deserialize_byte()? as u8)
}
#[inline]
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_i8(self.deserialize_byte()? as i8)
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
use std::str;
let error = || ErrorKind::InvalidCharEncoding.into();
let mut buf = [0u8; 4];
// Look at the first byte to see how many bytes must be read
self.reader.read_exact(&mut buf[..1])?;
let width = utf8_char_width(buf[0]);
if width == 1 {
return visitor.visit_char(buf[0] as char);
}
if width == 0 {
return Err(error());
}
if self.reader.read_exact(&mut buf[1..width]).is_err() {
return Err(error());
}
let res = str::from_utf8(&buf[..width])
.ok()
.and_then(|s| s.chars().next())
.ok_or_else(error)?;
visitor.visit_char(res)
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let len = O::IntEncoding::deserialize_len(self)?;
self.read_bytes(len as u64)?;
self.reader.forward_read_str(len, visitor)
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_string(self.read_string()?)
}
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let len = O::IntEncoding::deserialize_len(self)?;
self.read_bytes(len as u64)?;
self.reader.forward_read_bytes(len, visitor)
}
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_byte_buf(self.read_vec()?)
}
fn deserialize_enum<V>(
self,
_enum: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
impl<'de, 'a, R: 'a, O> serde::de::EnumAccess<'de> for &'a mut Deserializer<R, O>
where
R: BincodeRead<'de>,
O: Options,
{
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
where
V: serde::de::DeserializeSeed<'de>,
{
let idx: u32 = O::IntEncoding::deserialize_u32(self)?;
let val: Result<_> = seed.deserialize(idx.into_deserializer());
Ok((val?, self))
}
}
visitor.visit_enum(self)
}
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
struct Access<'a, R: Read + 'a, O: Options + 'a> {
deserializer: &'a mut Deserializer<R, O>,
len: usize,
}
impl<'de, 'a, 'b: 'a, R: BincodeRead<'de> + 'b, O: Options> serde::de::SeqAccess<'de>
for Access<'a, R, O>
{
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
where
T: serde::de::DeserializeSeed<'de>,
{
if self.len > 0 {
self.len -= 1;
let value =
serde::de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
Ok(Some(value))
} else {
Ok(None)
}
}
fn size_hint(&self) -> Option<usize> {
Some(self.len)
}
}
visitor.visit_seq(Access {
deserializer: self,
len,
})
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let value: u8 = serde::de::Deserialize::deserialize(&mut *self)?;
match value {
0 => visitor.visit_none(),
1 => visitor.visit_some(&mut *self),
v => Err(ErrorKind::InvalidTagEncoding(v as usize).into()),
}
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let len = O::IntEncoding::deserialize_len(self)?;
self.deserialize_tuple(len, visitor)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
struct Access<'a, R: Read + 'a, O: Options + 'a> {
deserializer: &'a mut Deserializer<R, O>,
len: usize,
}
impl<'de, 'a, 'b: 'a, R: BincodeRead<'de> + 'b, O: Options> serde::de::MapAccess<'de>
for Access<'a, R, O>
{
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: serde::de::DeserializeSeed<'de>,
{
if self.len > 0 {
self.len -= 1;
let key =
serde::de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
Ok(Some(key))
} else {
Ok(None)
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: serde::de::DeserializeSeed<'de>,
{
let value = serde::de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
Ok(value)
}
fn size_hint(&self) -> Option<usize> {
Some(self.len)
}
}
let len = O::IntEncoding::deserialize_len(self)?;
visitor.visit_map(Access {
deserializer: self,
len,
})
}
fn deserialize_struct<V>(
self,
_name: &str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_tuple(fields.len(), visitor)
}
fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let message = "Bincode does not support Deserializer::deserialize_identifier";
Err(Error::custom(message))
}
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}
fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_tuple(len, visitor)
}
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
let message = "Bincode does not support Deserializer::deserialize_ignored_any";
Err(Error::custom(message))
}
fn is_human_readable(&self) -> bool {
false
}
}
impl<'de, 'a, R, O> serde::de::VariantAccess<'de> for &'a mut Deserializer<R, O>
where
R: BincodeRead<'de>,
O: Options,
{
type Error = Error;
fn unit_variant(self) -> Result<()> {
Ok(())
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
where
T: serde::de::DeserializeSeed<'de>,
{
serde::de::DeserializeSeed::deserialize(seed, self)
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
serde::de::Deserializer::deserialize_tuple(self, len, visitor)
}
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'de>,
{
serde::de::Deserializer::deserialize_tuple(self, fields.len(), visitor)
}
}
static UTF8_CHAR_WIDTH: [u8; 256] = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, // 0x1F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, // 0x3F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, // 0x5F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, // 0x7F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // 0x9F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // 0xBF
0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, // 0xDF
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF
4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF
];
// This function is a copy of core::str::utf8_char_width
fn utf8_char_width(b: u8) -> usize {
UTF8_CHAR_WIDTH[b as usize] as usize
}

View File

@ -1,201 +1,202 @@
use error::Result;
use serde;
use std::{io, slice};
/// An optional Read trait for advanced Bincode usage.
///
/// It is highly recommended to use bincode with `io::Read` or `&[u8]` before
/// implementing a custom `BincodeRead`.
pub trait BincodeRead<'storage>: io::Read {
/// Forwards reading `length` bytes of a string on to the serde reader.
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>;
/// Return the first `length` bytes of the internal byte buffer.
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>>;
/// Forwards reading `length` bytes on to the serde reader.
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>;
}
/// A BincodeRead implementation for byte slices
/// NOT A PART OF THE STABLE PUBLIC API
#[doc(hidden)]
pub struct SliceReader<'storage> {
slice: &'storage [u8],
}
/// A BincodeRead implementation for io::Readers
/// NOT A PART OF THE STABLE PUBLIC API
#[doc(hidden)]
pub struct IoReader<R> {
reader: R,
temp_buffer: Vec<u8>,
}
impl<'storage> SliceReader<'storage> {
/// Constructs a slice reader
pub fn new(bytes: &'storage [u8]) -> SliceReader<'storage> {
SliceReader { slice: bytes }
}
}
impl<R> IoReader<R> {
/// Constructs an IoReadReader
pub fn new(r: R) -> IoReader<R> {
IoReader {
reader: r,
temp_buffer: vec![],
}
}
}
impl<'storage> io::Read for SliceReader<'storage> {
#[inline(always)]
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
(&mut self.slice).read(out)
}
#[inline(always)]
fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {
(&mut self.slice).read_exact(out)
}
}
impl<R: io::Read> io::Read for IoReader<R> {
#[inline(always)]
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
self.reader.read(out)
}
#[inline(always)]
fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {
self.reader.read_exact(out)
}
}
impl<'storage> SliceReader<'storage> {
#[inline(always)]
fn unexpected_eof() -> Box<::ErrorKind> {
return Box::new(::ErrorKind::Io(io::Error::new(
io::ErrorKind::UnexpectedEof,
"",
)));
}
}
impl<'storage> BincodeRead<'storage> for SliceReader<'storage> {
#[inline(always)]
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>,
{
use ErrorKind;
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let string = match ::std::str::from_utf8(&self.slice[..length]) {
Ok(s) => s,
Err(e) => return Err(ErrorKind::InvalidUtf8Encoding(e).into()),
};
let r = visitor.visit_borrowed_str(string);
self.slice = &self.slice[length..];
r
}
#[inline(always)]
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let r = &self.slice[..length];
self.slice = &self.slice[length..];
Ok(r.to_vec())
}
#[inline(always)]
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>,
{
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let r = visitor.visit_borrowed_bytes(&self.slice[..length]);
self.slice = &self.slice[length..];
r
}
}
impl<R> IoReader<R>
where
R: io::Read,
{
fn fill_buffer(&mut self, length: usize) -> Result<()> {
// We first reserve the space needed in our buffer.
let current_length = self.temp_buffer.len();
if length > current_length {
self.temp_buffer.reserve_exact(length - current_length);
}
// Then create a slice with the length as our desired length. This is
// safe as long as we only write (no reads) to this buffer, because
// `reserve_exact` above has allocated this space.
let buf = unsafe {
slice::from_raw_parts_mut(self.temp_buffer.as_mut_ptr(), length)
};
// This method is assumed to properly handle slices which include
// uninitialized bytes (as ours does). See discussion at the link below.
// https://github.com/servo/bincode/issues/260
self.reader.read_exact(buf)?;
// Only after `read_exact` successfully returns do we set the buffer
// length. By doing this after the call to `read_exact`, we can avoid
// exposing uninitialized memory in the case of `read_exact` returning
// an error.
unsafe {
self.temp_buffer.set_len(length);
}
Ok(())
}
}
impl<'a, R> BincodeRead<'a> for IoReader<R>
where
R: io::Read,
{
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'a>,
{
self.fill_buffer(length)?;
let string = match ::std::str::from_utf8(&self.temp_buffer[..]) {
Ok(s) => s,
Err(e) => return Err(::ErrorKind::InvalidUtf8Encoding(e).into()),
};
let r = visitor.visit_str(string);
r
}
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {
self.fill_buffer(length)?;
Ok(::std::mem::replace(&mut self.temp_buffer, Vec::new()))
}
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'a>,
{
self.fill_buffer(length)?;
let r = visitor.visit_bytes(&self.temp_buffer[..]);
r
}
}
use error::Result;
use serde;
use std::io;
/// An optional Read trait for advanced Bincode usage.
///
/// It is highly recommended to use bincode with `io::Read` or `&[u8]` before
/// implementing a custom `BincodeRead`.
///
/// The forward_read_* methods are necessary because some byte sources want
/// to pass a long-lived borrow to the visitor and others want to pass a
/// transient slice.
pub trait BincodeRead<'storage>: io::Read {
/// Check that the next `length` bytes are a valid string and pass
/// it on to the serde reader.
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>;
/// Transfer ownership of the next `length` bytes to the caller.
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>>;
/// Pass a slice of the next `length` bytes on to the serde reader.
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>;
}
/// A BincodeRead implementation for byte slices
pub struct SliceReader<'storage> {
slice: &'storage [u8],
}
/// A BincodeRead implementation for `io::Read`ers
pub struct IoReader<R> {
reader: R,
temp_buffer: Vec<u8>,
}
impl<'storage> SliceReader<'storage> {
/// Constructs a slice reader
pub(crate) fn new(bytes: &'storage [u8]) -> SliceReader<'storage> {
SliceReader { slice: bytes }
}
#[inline(always)]
fn get_byte_slice(&mut self, length: usize) -> Result<&'storage [u8]> {
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let (read_slice, remaining) = self.slice.split_at(length);
self.slice = remaining;
Ok(read_slice)
}
pub(crate) fn is_finished(&self) -> bool {
self.slice.is_empty()
}
}
impl<R> IoReader<R> {
/// Constructs an IoReadReader
pub(crate) fn new(r: R) -> IoReader<R> {
IoReader {
reader: r,
temp_buffer: vec![],
}
}
}
impl<'storage> io::Read for SliceReader<'storage> {
#[inline(always)]
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
if out.len() > self.slice.len() {
return Err(io::ErrorKind::UnexpectedEof.into());
}
let (read_slice, remaining) = self.slice.split_at(out.len());
out.copy_from_slice(read_slice);
self.slice = remaining;
Ok(out.len())
}
#[inline(always)]
fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {
self.read(out).map(|_| ())
}
}
impl<R: io::Read> io::Read for IoReader<R> {
#[inline(always)]
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
self.reader.read(out)
}
#[inline(always)]
fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {
self.reader.read_exact(out)
}
}
impl<'storage> SliceReader<'storage> {
#[inline(always)]
fn unexpected_eof() -> Box<::ErrorKind> {
Box::new(::ErrorKind::Io(io::Error::new(
io::ErrorKind::UnexpectedEof,
"",
)))
}
}
impl<'storage> BincodeRead<'storage> for SliceReader<'storage> {
#[inline(always)]
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>,
{
use ErrorKind;
let string = match ::std::str::from_utf8(self.get_byte_slice(length)?) {
Ok(s) => s,
Err(e) => return Err(ErrorKind::InvalidUtf8Encoding(e).into()),
};
visitor.visit_borrowed_str(string)
}
#[inline(always)]
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {
self.get_byte_slice(length).map(|x| x.to_vec())
}
#[inline(always)]
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>,
{
visitor.visit_borrowed_bytes(self.get_byte_slice(length)?)
}
}
impl<R> IoReader<R>
where
R: io::Read,
{
fn fill_buffer(&mut self, length: usize) -> Result<()> {
self.temp_buffer.resize(length, 0);
self.reader.read_exact(&mut self.temp_buffer)?;
Ok(())
}
}
impl<'a, R> BincodeRead<'a> for IoReader<R>
where
R: io::Read,
{
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'a>,
{
self.fill_buffer(length)?;
let string = match ::std::str::from_utf8(&self.temp_buffer[..]) {
Ok(s) => s,
Err(e) => return Err(::ErrorKind::InvalidUtf8Encoding(e).into()),
};
visitor.visit_str(string)
}
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {
self.fill_buffer(length)?;
Ok(::std::mem::replace(&mut self.temp_buffer, Vec::new()))
}
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'a>,
{
self.fill_buffer(length)?;
visitor.visit_bytes(&self.temp_buffer[..])
}
}
#[cfg(test)]
mod test {
use super::IoReader;
#[test]
fn test_fill_buffer() {
let buffer = vec![0u8; 64];
let mut reader = IoReader::new(buffer.as_slice());
reader.fill_buffer(20).unwrap();
assert_eq!(20, reader.temp_buffer.len());
reader.fill_buffer(30).unwrap();
assert_eq!(30, reader.temp_buffer.len());
reader.fill_buffer(5).unwrap();
assert_eq!(5, reader.temp_buffer.len());
}
}

View File

@ -1,115 +1,115 @@
use std::error::Error as StdError;
use std::io;
use std::str::Utf8Error;
use std::{error, fmt};
use serde;
/// The result of a serialization or deserialization operation.
pub type Result<T> = ::std::result::Result<T, Error>;
/// An error that can be produced during (de)serializing.
pub type Error = Box<ErrorKind>;
/// The kind of error that can be produced during a serialization or deserialization.
#[derive(Debug)]
pub enum ErrorKind {
/// If the error stems from the reader/writer that is being used
/// during (de)serialization, that error will be stored and returned here.
Io(io::Error),
/// Returned if the deserializer attempts to deserialize a string that is not valid utf8
InvalidUtf8Encoding(Utf8Error),
/// Returned if the deserializer attempts to deserialize a bool that was
/// not encoded as either a 1 or a 0
InvalidBoolEncoding(u8),
/// Returned if the deserializer attempts to deserialize a char that is not in the correct format.
InvalidCharEncoding,
/// Returned if the deserializer attempts to deserialize the tag of an enum that is
/// not in the expected ranges
InvalidTagEncoding(usize),
/// Serde has a deserialize_any method that lets the format hint to the
/// object which route to take in deserializing.
DeserializeAnyNotSupported,
/// If (de)serializing a message takes more than the provided size limit, this
/// error is returned.
SizeLimit,
/// Bincode can not encode sequences of unknown length (like iterators).
SequenceMustHaveLength,
/// A custom error message from Serde.
Custom(String),
}
impl StdError for ErrorKind {
fn description(&self) -> &str {
match *self {
ErrorKind::Io(ref err) => error::Error::description(err),
ErrorKind::InvalidUtf8Encoding(_) => "string is not valid utf8",
ErrorKind::InvalidBoolEncoding(_) => "invalid u8 while decoding bool",
ErrorKind::InvalidCharEncoding => "char is not valid",
ErrorKind::InvalidTagEncoding(_) => "tag for enum is not valid",
ErrorKind::SequenceMustHaveLength => {
"Bincode can only encode sequences and maps that have a knowable size ahead of time"
}
ErrorKind::DeserializeAnyNotSupported => {
"Bincode doesn't support serde::Deserializer::deserialize_any"
}
ErrorKind::SizeLimit => "the size limit has been reached",
ErrorKind::Custom(ref msg) => msg,
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
ErrorKind::Io(ref err) => Some(err),
ErrorKind::InvalidUtf8Encoding(_) => None,
ErrorKind::InvalidBoolEncoding(_) => None,
ErrorKind::InvalidCharEncoding => None,
ErrorKind::InvalidTagEncoding(_) => None,
ErrorKind::SequenceMustHaveLength => None,
ErrorKind::DeserializeAnyNotSupported => None,
ErrorKind::SizeLimit => None,
ErrorKind::Custom(_) => None,
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
ErrorKind::Io(err).into()
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
ErrorKind::Io(ref ioerr) => write!(fmt, "io error: {}", ioerr),
ErrorKind::InvalidUtf8Encoding(ref e) => write!(fmt, "{}: {}", self.description(), e),
ErrorKind::InvalidBoolEncoding(b) => {
write!(fmt, "{}, expected 0 or 1, found {}", self.description(), b)
}
ErrorKind::InvalidCharEncoding => write!(fmt, "{}", self.description()),
ErrorKind::InvalidTagEncoding(tag) => {
write!(fmt, "{}, found {}", self.description(), tag)
}
ErrorKind::SequenceMustHaveLength => write!(fmt, "{}", self.description()),
ErrorKind::SizeLimit => write!(fmt, "{}", self.description()),
ErrorKind::DeserializeAnyNotSupported => write!(
fmt,
"Bincode does not support the serde::Deserializer::deserialize_any method"
),
ErrorKind::Custom(ref s) => s.fmt(fmt),
}
}
}
impl serde::de::Error for Error {
fn custom<T: fmt::Display>(desc: T) -> Error {
ErrorKind::Custom(desc.to_string()).into()
}
}
impl serde::ser::Error for Error {
fn custom<T: fmt::Display>(msg: T) -> Self {
ErrorKind::Custom(msg.to_string()).into()
}
}
use std::error::Error as StdError;
use std::io;
use std::str::Utf8Error;
use std::{error, fmt};
use serde;
/// The result of a serialization or deserialization operation.
pub type Result<T> = ::std::result::Result<T, Error>;
/// An error that can be produced during (de)serializing.
pub type Error = Box<ErrorKind>;
/// The kind of error that can be produced during a serialization or deserialization.
#[derive(Debug)]
pub enum ErrorKind {
/// If the error stems from the reader/writer that is being used
/// during (de)serialization, that error will be stored and returned here.
Io(io::Error),
/// Returned if the deserializer attempts to deserialize a string that is not valid utf8
InvalidUtf8Encoding(Utf8Error),
/// Returned if the deserializer attempts to deserialize a bool that was
/// not encoded as either a 1 or a 0
InvalidBoolEncoding(u8),
/// Returned if the deserializer attempts to deserialize a char that is not in the correct format.
InvalidCharEncoding,
/// Returned if the deserializer attempts to deserialize the tag of an enum that is
/// not in the expected ranges
InvalidTagEncoding(usize),
/// Serde has a deserialize_any method that lets the format hint to the
/// object which route to take in deserializing.
DeserializeAnyNotSupported,
/// If (de)serializing a message takes more than the provided size limit, this
/// error is returned.
SizeLimit,
/// Bincode can not encode sequences of unknown length (like iterators).
SequenceMustHaveLength,
/// A custom error message from Serde.
Custom(String),
}
impl StdError for ErrorKind {
fn description(&self) -> &str {
match *self {
ErrorKind::Io(ref err) => error::Error::description(err),
ErrorKind::InvalidUtf8Encoding(_) => "string is not valid utf8",
ErrorKind::InvalidBoolEncoding(_) => "invalid u8 while decoding bool",
ErrorKind::InvalidCharEncoding => "char is not valid",
ErrorKind::InvalidTagEncoding(_) => "tag for enum is not valid",
ErrorKind::SequenceMustHaveLength => {
"Bincode can only encode sequences and maps that have a knowable size ahead of time"
}
ErrorKind::DeserializeAnyNotSupported => {
"Bincode doesn't support serde::Deserializer::deserialize_any"
}
ErrorKind::SizeLimit => "the size limit has been reached",
ErrorKind::Custom(ref msg) => msg,
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
ErrorKind::Io(ref err) => Some(err),
ErrorKind::InvalidUtf8Encoding(_) => None,
ErrorKind::InvalidBoolEncoding(_) => None,
ErrorKind::InvalidCharEncoding => None,
ErrorKind::InvalidTagEncoding(_) => None,
ErrorKind::SequenceMustHaveLength => None,
ErrorKind::DeserializeAnyNotSupported => None,
ErrorKind::SizeLimit => None,
ErrorKind::Custom(_) => None,
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
ErrorKind::Io(err).into()
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
ErrorKind::Io(ref ioerr) => write!(fmt, "io error: {}", ioerr),
ErrorKind::InvalidUtf8Encoding(ref e) => write!(fmt, "{}: {}", self.description(), e),
ErrorKind::InvalidBoolEncoding(b) => {
write!(fmt, "{}, expected 0 or 1, found {}", self.description(), b)
}
ErrorKind::InvalidCharEncoding => write!(fmt, "{}", self.description()),
ErrorKind::InvalidTagEncoding(tag) => {
write!(fmt, "{}, found {}", self.description(), tag)
}
ErrorKind::SequenceMustHaveLength => write!(fmt, "{}", self.description()),
ErrorKind::SizeLimit => write!(fmt, "{}", self.description()),
ErrorKind::DeserializeAnyNotSupported => write!(
fmt,
"Bincode does not support the serde::Deserializer::deserialize_any method"
),
ErrorKind::Custom(ref s) => s.fmt(fmt),
}
}
}
impl serde::de::Error for Error {
fn custom<T: fmt::Display>(desc: T) -> Error {
ErrorKind::Custom(desc.to_string()).into()
}
}
impl serde::ser::Error for Error {
fn custom<T: fmt::Display>(msg: T) -> Self {
ErrorKind::Custom(msg.to_string()).into()
}
}

View File

@ -1,191 +1,124 @@
use serde;
use std::io::{Read, Write};
use std::marker::PhantomData;
use config::{Options, OptionsExt};
use de::read::BincodeRead;
use {ErrorKind, Result};
#[derive(Clone)]
struct CountSize<L: SizeLimit> {
total: u64,
other_limit: L,
}
pub(crate) fn serialize_into<W, T: ?Sized, O>(writer: W, value: &T, mut options: O) -> Result<()>
where
W: Write,
T: serde::Serialize,
O: Options,
{
if options.limit().limit().is_some() {
// "compute" the size for the side-effect
// of returning Err if the bound was reached.
serialized_size(value, &mut options)?;
}
let mut serializer = ::ser::Serializer::<_, O>::new(writer, options);
serde::Serialize::serialize(value, &mut serializer)
}
pub(crate) fn serialize<T: ?Sized, O>(value: &T, mut options: O) -> Result<Vec<u8>>
where
T: serde::Serialize,
O: Options,
{
let mut writer = {
let actual_size = serialized_size(value, &mut options)?;
Vec::with_capacity(actual_size as usize)
};
serialize_into(&mut writer, value, options.with_no_limit())?;
Ok(writer)
}
impl<L: SizeLimit> SizeLimit for CountSize<L> {
fn add(&mut self, c: u64) -> Result<()> {
self.other_limit.add(c)?;
self.total += c;
Ok(())
}
fn limit(&self) -> Option<u64> {
unreachable!();
}
}
pub(crate) fn serialized_size<T: ?Sized, O: Options>(value: &T, mut options: O) -> Result<u64>
where
T: serde::Serialize,
{
let old_limiter = options.limit().clone();
let mut size_counter = ::ser::SizeChecker {
options: ::config::WithOtherLimit::new(
options,
CountSize {
total: 0,
other_limit: old_limiter,
},
),
};
let result = value.serialize(&mut size_counter);
result.map(|_| size_counter.options.new_limit.total)
}
pub(crate) fn deserialize_from<R, T, O>(reader: R, options: O) -> Result<T>
where
R: Read,
T: serde::de::DeserializeOwned,
O: Options,
{
deserialize_from_seed(PhantomData, reader, options)
}
pub(crate) fn deserialize_from_seed<'a, R, T, O>(seed: T, reader: R, options: O) -> Result<T::Value>
where
R: Read,
T: serde::de::DeserializeSeed<'a>,
O: Options,
{
let reader = ::de::read::IoReader::new(reader);
deserialize_from_custom_seed(seed, reader, options)
}
pub(crate) fn deserialize_from_custom<'a, R, T, O>(reader: R, options: O) -> Result<T>
where
R: BincodeRead<'a>,
T: serde::de::DeserializeOwned,
O: Options,
{
deserialize_from_custom_seed(PhantomData, reader, options)
}
pub(crate) fn deserialize_from_custom_seed<'a, R, T, O>(
seed: T,
reader: R,
options: O,
) -> Result<T::Value>
where
R: BincodeRead<'a>,
T: serde::de::DeserializeSeed<'a>,
O: Options,
{
let mut deserializer = ::de::Deserializer::<_, O>::new(reader, options);
seed.deserialize(&mut deserializer)
}
pub(crate) fn deserialize_in_place<'a, R, T, O>(reader: R, options: O, place: &mut T) -> Result<()>
where
R: BincodeRead<'a>,
T: serde::de::Deserialize<'a>,
O: Options,
{
let mut deserializer = ::de::Deserializer::<_, _>::new(reader, options);
serde::Deserialize::deserialize_in_place(&mut deserializer, place)
}
pub(crate) fn deserialize<'a, T, O>(bytes: &'a [u8], options: O) -> Result<T>
where
T: serde::de::Deserialize<'a>,
O: Options,
{
deserialize_seed(PhantomData, bytes, options)
}
pub(crate) fn deserialize_seed<'a, T, O>(seed: T, bytes: &'a [u8], options: O) -> Result<T::Value>
where
T: serde::de::DeserializeSeed<'a>,
O: Options,
{
let reader = ::de::read::SliceReader::new(bytes);
let options = ::config::WithOtherLimit::new(options, Infinite);
deserialize_from_custom_seed(seed, reader, options)
}
pub(crate) trait SizeLimit: Clone {
/// Tells the SizeLimit that a certain number of bytes has been
/// read or written. Returns Err if the limit has been exceeded.
fn add(&mut self, n: u64) -> Result<()>;
/// Returns the hard limit (if one exists)
fn limit(&self) -> Option<u64>;
}
/// A SizeLimit that restricts serialized or deserialized messages from
/// exceeding a certain byte length.
#[derive(Copy, Clone)]
pub struct Bounded(pub u64);
/// A SizeLimit without a limit!
/// Use this if you don't care about the size of encoded or decoded messages.
#[derive(Copy, Clone)]
pub struct Infinite;
impl SizeLimit for Bounded {
#[inline(always)]
fn add(&mut self, n: u64) -> Result<()> {
if self.0 >= n {
self.0 -= n;
Ok(())
} else {
Err(Box::new(ErrorKind::SizeLimit))
}
}
#[inline(always)]
fn limit(&self) -> Option<u64> {
Some(self.0)
}
}
impl SizeLimit for Infinite {
#[inline(always)]
fn add(&mut self, _: u64) -> Result<()> {
Ok(())
}
#[inline(always)]
fn limit(&self) -> Option<u64> {
None
}
}
use serde;
use std::io::{Read, Write};
use std::marker::PhantomData;
use config::{Infinite, InternalOptions, Options, SizeLimit, TrailingBytes};
use de::read::BincodeRead;
use Result;
pub(crate) fn serialize_into<W, T: ?Sized, O>(writer: W, value: &T, mut options: O) -> Result<()>
where
W: Write,
T: serde::Serialize,
O: InternalOptions,
{
if options.limit().limit().is_some() {
// "compute" the size for the side-effect
// of returning Err if the bound was reached.
serialized_size(value, &mut options)?;
}
let mut serializer = ::ser::Serializer::<_, O>::new(writer, options);
serde::Serialize::serialize(value, &mut serializer)
}
pub(crate) fn serialize<T: ?Sized, O>(value: &T, mut options: O) -> Result<Vec<u8>>
where
T: serde::Serialize,
O: InternalOptions,
{
let mut writer = {
let actual_size = serialized_size(value, &mut options)?;
Vec::with_capacity(actual_size as usize)
};
serialize_into(&mut writer, value, options.with_no_limit())?;
Ok(writer)
}
pub(crate) fn serialized_size<T: ?Sized, O: InternalOptions>(value: &T, options: O) -> Result<u64>
where
T: serde::Serialize,
{
let mut size_counter = ::ser::SizeChecker { options, total: 0 };
let result = value.serialize(&mut size_counter);
result.map(|_| size_counter.total)
}
pub(crate) fn deserialize_from<R, T, O>(reader: R, options: O) -> Result<T>
where
R: Read,
T: serde::de::DeserializeOwned,
O: InternalOptions,
{
deserialize_from_seed(PhantomData, reader, options)
}
pub(crate) fn deserialize_from_seed<'a, R, T, O>(seed: T, reader: R, options: O) -> Result<T::Value>
where
R: Read,
T: serde::de::DeserializeSeed<'a>,
O: InternalOptions,
{
let reader = ::de::read::IoReader::new(reader);
deserialize_from_custom_seed(seed, reader, options)
}
pub(crate) fn deserialize_from_custom<'a, R, T, O>(reader: R, options: O) -> Result<T>
where
R: BincodeRead<'a>,
T: serde::de::DeserializeOwned,
O: InternalOptions,
{
deserialize_from_custom_seed(PhantomData, reader, options)
}
pub(crate) fn deserialize_from_custom_seed<'a, R, T, O>(
seed: T,
reader: R,
options: O,
) -> Result<T::Value>
where
R: BincodeRead<'a>,
T: serde::de::DeserializeSeed<'a>,
O: InternalOptions,
{
let mut deserializer = ::de::Deserializer::<_, O>::with_bincode_read(reader, options);
seed.deserialize(&mut deserializer)
}
pub(crate) fn deserialize_in_place<'a, R, T, O>(reader: R, options: O, place: &mut T) -> Result<()>
where
R: BincodeRead<'a>,
T: serde::de::Deserialize<'a>,
O: InternalOptions,
{
let mut deserializer = ::de::Deserializer::<_, _>::with_bincode_read(reader, options);
serde::Deserialize::deserialize_in_place(&mut deserializer, place)
}
pub(crate) fn deserialize<'a, T, O>(bytes: &'a [u8], options: O) -> Result<T>
where
T: serde::de::Deserialize<'a>,
O: InternalOptions,
{
deserialize_seed(PhantomData, bytes, options)
}
pub(crate) fn deserialize_seed<'a, T, O>(seed: T, bytes: &'a [u8], options: O) -> Result<T::Value>
where
T: serde::de::DeserializeSeed<'a>,
O: InternalOptions,
{
let options = ::config::WithOtherLimit::new(options, Infinite);
let reader = ::de::read::SliceReader::new(bytes);
let mut deserializer = ::de::Deserializer::with_bincode_read(reader, options);
let val = seed.deserialize(&mut deserializer)?;
match O::Trailing::check_end(&deserializer.reader) {
Ok(_) => Ok(val),
Err(err) => Err(err),
}
}

View File

@ -1,173 +1,201 @@
#![deny(missing_docs)]
//! Bincode is a crate for encoding and decoding using a tiny binary
//! serialization strategy. Using it, you can easily go from having
//! an object in memory, quickly serialize it to bytes, and then
//! deserialize it back just as fast!
//!
//! ### Using Basic Functions
//!
//! ```edition2018
//! fn main() {
//! // The object that we will serialize.
//! let target: Option<String> = Some("hello world".to_string());
//!
//! let encoded: Vec<u8> = bincode::serialize(&target).unwrap();
//! let decoded: Option<String> = bincode::deserialize(&encoded[..]).unwrap();
//! assert_eq!(target, decoded);
//! }
//! ```
//!
//! ### 128bit numbers
//!
//! Support for `i128` and `u128` is automatically enabled on Rust toolchains
//! greater than or equal to `1.26.0` and disabled for targets which do not support it
#![doc(html_root_url = "https://docs.rs/bincode/1.2.1")]
#![crate_name = "bincode"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
extern crate byteorder;
#[macro_use]
extern crate serde;
mod config;
mod de;
mod error;
mod internal;
mod ser;
pub use config::Config;
pub use de::read::{BincodeRead, IoReader, SliceReader};
pub use error::{Error, ErrorKind, Result};
/// An object that implements this trait can be passed a
/// serde::Deserializer without knowing its concrete type.
///
/// This trait should be used only for `with_deserializer` functions.
#[doc(hidden)]
pub trait DeserializerAcceptor<'a> {
/// The return type for the accept method
type Output;
/// Accept a serde::Deserializer and do whatever you want with it.
fn accept<T: serde::Deserializer<'a>>(self, T) -> Self::Output;
}
/// An object that implements this trait can be passed a
/// serde::Serializer without knowing its concrete type.
///
/// This trait should be used only for `with_serializer` functions.
#[doc(hidden)]
pub trait SerializerAcceptor {
/// The return type for the accept method
type Output;
/// Accept a serde::Serializer and do whatever you want with it.
fn accept<T: serde::Serializer>(self, T) -> Self::Output;
}
/// Get a default configuration object.
///
/// ### Default Configuration:
///
/// | Byte limit | Endianness |
/// |------------|------------|
/// | Unlimited | Little |
#[inline(always)]
pub fn config() -> Config {
Config::new()
}
/// Serializes an object directly into a `Writer` using the default configuration.
///
/// If the serialization would take more bytes than allowed by the size limit, an error
/// is returned and *no bytes* will be written into the `Writer`.
pub fn serialize_into<W, T: ?Sized>(writer: W, value: &T) -> Result<()>
where
W: std::io::Write,
T: serde::Serialize,
{
config().serialize_into(writer, value)
}
/// Serializes a serializable object into a `Vec` of bytes using the default configuration.
pub fn serialize<T: ?Sized>(value: &T) -> Result<Vec<u8>>
where
T: serde::Serialize,
{
config().serialize(value)
}
/// Deserializes an object directly from a `Read`er using the default configuration.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
pub fn deserialize_from<R, T>(reader: R) -> Result<T>
where
R: std::io::Read,
T: serde::de::DeserializeOwned,
{
config().deserialize_from(reader)
}
/// Deserializes an object from a custom `BincodeRead`er using the default configuration.
/// It is highly recommended to use `deserialize_from` unless you need to implement
/// `BincodeRead` for performance reasons.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
pub fn deserialize_from_custom<'a, R, T>(reader: R) -> Result<T>
where
R: de::read::BincodeRead<'a>,
T: serde::de::DeserializeOwned,
{
config().deserialize_from_custom(reader)
}
/// Only use this if you know what you're doing.
///
/// This is part of the public API.
#[doc(hidden)]
pub fn deserialize_in_place<'a, R, T>(reader: R, place: &mut T) -> Result<()>
where
T: serde::de::Deserialize<'a>,
R: BincodeRead<'a>,
{
config().deserialize_in_place(reader, place)
}
/// Deserializes a slice of bytes into an instance of `T` using the default configuration.
pub fn deserialize<'a, T>(bytes: &'a [u8]) -> Result<T>
where
T: serde::de::Deserialize<'a>,
{
config().deserialize(bytes)
}
/// Returns the size that an object would be if serialized using Bincode with the default configuration.
pub fn serialized_size<T: ?Sized>(value: &T) -> Result<u64>
where
T: serde::Serialize,
{
config().serialized_size(value)
}
/// Executes the acceptor with a serde::Deserializer instance.
/// NOT A PART OF THE STABLE PUBLIC API
#[doc(hidden)]
pub fn with_deserializer<'a, A, R>(reader: R, acceptor: A) -> A::Output
where
A: DeserializerAcceptor<'a>,
R: BincodeRead<'a>,
{
config().with_deserializer(reader, acceptor)
}
/// Executes the acceptor with a serde::Serializer instance.
/// NOT A PART OF THE STABLE PUBLIC API
#[doc(hidden)]
pub fn with_serializer<A, W>(writer: W, acceptor: A) -> A::Output
where
A: SerializerAcceptor,
W: std::io::Write,
{
config().with_serializer(writer, acceptor)
}
#![deny(missing_docs)]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
//! Bincode is a crate for encoding and decoding using a tiny binary
//! serialization strategy. Using it, you can easily go from having
//! an object in memory, quickly serialize it to bytes, and then
//! deserialize it back just as fast!
//!
//! ### Using Basic Functions
//!
//! ```edition2018
//! fn main() {
//! // The object that we will serialize.
//! let target: Option<String> = Some("hello world".to_string());
//!
//! let encoded: Vec<u8> = bincode::serialize(&target).unwrap();
//! let decoded: Option<String> = bincode::deserialize(&encoded[..]).unwrap();
//! assert_eq!(target, decoded);
//! }
//! ```
//!
//! ### 128bit numbers
//!
//! Support for `i128` and `u128` is automatically enabled on Rust toolchains
//! greater than or equal to `1.26.0` and disabled for targets which do not support it
#![doc(html_root_url = "https://docs.rs/bincode/1.3.3")]
#![crate_name = "bincode"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#[macro_use]
extern crate serde;
pub mod config;
/// Deserialize bincode data to a Rust data structure.
pub mod de;
mod byteorder;
mod error;
mod internal;
mod ser;
pub use config::{Config, DefaultOptions, Options};
pub use de::read::BincodeRead;
pub use de::Deserializer;
pub use error::{Error, ErrorKind, Result};
pub use ser::Serializer;
/// Get a default configuration object.
///
/// ### Default Configuration:
///
/// | Byte limit | Endianness |
/// |------------|------------|
/// | Unlimited | Little |
#[inline(always)]
#[deprecated(since = "1.3.0", note = "please use `options()` instead")]
pub fn config() -> Config {
Config::new()
}
/// Get a default configuration object.
///
/// **Warning:** the default configuration returned by this function
/// is not the same as that used by the other functions in this
/// module. See the
/// [config](config/index.html#options-struct-vs-bincode-functions)
/// module for more details
///
/// ### Default Configuration:
///
/// | Byte limit | Endianness | Int Encoding | Trailing Behavior |
/// |------------|------------|--------------|-------------------|
/// | Unlimited | Little | Varint | Reject |
#[inline(always)]
pub fn options() -> DefaultOptions {
DefaultOptions::new()
}
/// Serializes an object directly into a `Writer` using the default configuration.
///
/// If the serialization would take more bytes than allowed by the size limit, an error
/// is returned and *no bytes* will be written into the `Writer`.
///
/// **Warning:** the default configuration used by this function is not
/// the same as that used by the `DefaultOptions` struct. See the
/// [config](config/index.html#options-struct-vs-bincode-functions)
/// module for more details
pub fn serialize_into<W, T: ?Sized>(writer: W, value: &T) -> Result<()>
where
W: std::io::Write,
T: serde::Serialize,
{
DefaultOptions::new()
.with_fixint_encoding()
.serialize_into(writer, value)
}
/// Serializes a serializable object into a `Vec` of bytes using the default configuration.
///
/// **Warning:** the default configuration used by this function is not
/// the same as that used by the `DefaultOptions` struct. See the
/// [config](config/index.html#options-struct-vs-bincode-functions)
/// module for more details
pub fn serialize<T: ?Sized>(value: &T) -> Result<Vec<u8>>
where
T: serde::Serialize,
{
DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.serialize(value)
}
/// Deserializes an object directly from a `Read`er using the default configuration.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
///
/// **Warning:** the default configuration used by this function is not
/// the same as that used by the `DefaultOptions` struct. See the
/// [config](config/index.html#options-struct-vs-bincode-functions)
/// module for more details
pub fn deserialize_from<R, T>(reader: R) -> Result<T>
where
R: std::io::Read,
T: serde::de::DeserializeOwned,
{
DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.deserialize_from(reader)
}
/// Deserializes an object from a custom `BincodeRead`er using the default configuration.
/// It is highly recommended to use `deserialize_from` unless you need to implement
/// `BincodeRead` for performance reasons.
///
/// If this returns an `Error`, `reader` may be in an invalid state.
///
/// **Warning:** the default configuration used by this function is not
/// the same as that used by the `DefaultOptions` struct. See the
/// [config](config/index.html#options-struct-vs-bincode-functions)
/// module for more details
pub fn deserialize_from_custom<'a, R, T>(reader: R) -> Result<T>
where
R: de::read::BincodeRead<'a>,
T: serde::de::DeserializeOwned,
{
DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.deserialize_from_custom(reader)
}
/// Only use this if you know what you're doing.
///
/// This is part of the public API.
#[doc(hidden)]
pub fn deserialize_in_place<'a, R, T>(reader: R, place: &mut T) -> Result<()>
where
T: serde::de::Deserialize<'a>,
R: BincodeRead<'a>,
{
DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.deserialize_in_place(reader, place)
}
/// Deserializes a slice of bytes into an instance of `T` using the default configuration.
///
/// **Warning:** the default configuration used by this function is not
/// the same as that used by the `DefaultOptions` struct. See the
/// [config](config/index.html#options-struct-vs-bincode-functions)
/// module for more details
pub fn deserialize<'a, T>(bytes: &'a [u8]) -> Result<T>
where
T: serde::de::Deserialize<'a>,
{
DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.deserialize(bytes)
}
/// Returns the size that an object would be if serialized using Bincode with the default configuration.
///
/// **Warning:** the default configuration used by this function is not
/// the same as that used by the `DefaultOptions` struct. See the
/// [config](config/index.html#options-struct-vs-bincode-functions)
/// module for more details
pub fn serialized_size<T: ?Sized>(value: &T) -> Result<u64>
where
T: serde::Serialize,
{
DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
.serialized_size(value)
}

File diff suppressed because it is too large Load Diff

899
third_party/rust/bincode/tests/test.rs vendored Normal file
View File

@ -0,0 +1,899 @@
#[macro_use]
extern crate serde_derive;
extern crate bincode;
#[macro_use]
extern crate serde;
extern crate serde_bytes;
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt::{self, Debug};
use std::result::Result as StdResult;
use bincode::{
deserialize, deserialize_from, deserialize_in_place, serialize, serialized_size,
DefaultOptions, ErrorKind, Options, Result,
};
use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
const LEN_SIZE: u64 = 8;
fn the_same_impl<V, O>(element: V, options: &mut O)
where
V: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug + 'static,
O: Options,
{
let size = options.serialized_size(&element).unwrap();
{
let encoded = options.serialize(&element).unwrap();
let decoded: V = options.deserialize(&encoded[..]).unwrap();
let decoded_reader = options.deserialize_from(&mut &encoded[..]).unwrap();
assert_eq!(element, decoded);
assert_eq!(element, decoded_reader);
assert_eq!(size, encoded.len() as u64);
}
}
fn the_same<V>(element: V)
where
V: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug + Clone + 'static,
{
// add a new macro which calls the previous when you add a new option set
macro_rules! all_endians {
($element:expr, $options:expr) => {
the_same_impl($element.clone(), &mut $options.with_native_endian());
the_same_impl($element.clone(), &mut $options.with_big_endian());
the_same_impl($element.clone(), &mut $options.with_little_endian());
};
}
macro_rules! all_integer_encodings {
($element:expr, $options:expr) => {
all_endians!($element, $options.with_fixint_encoding());
all_endians!($element, $options.with_varint_encoding());
};
}
all_integer_encodings!(element, DefaultOptions::new());
}
#[test]
fn test_numbers() {
// unsigned positive
the_same(5u8);
the_same(5u16);
the_same(5u32);
the_same(5u64);
the_same(5usize);
// signed positive
the_same(5i8);
the_same(5i16);
the_same(5i32);
the_same(5i64);
the_same(5isize);
// signed negative
the_same(-5i8);
the_same(-5i16);
the_same(-5i32);
the_same(-5i64);
the_same(-5isize);
// floating
the_same(-100f32);
the_same(0f32);
the_same(5f32);
the_same(-100f64);
the_same(5f64);
}
serde_if_integer128! {
#[test]
fn test_numbers_128bit() {
// unsigned positive
the_same(5u128);
the_same(u128::max_value());
// signed positive
the_same(5i128);
the_same(i128::max_value());
// signed negative
the_same(-5i128);
the_same(i128::min_value());
}
}
#[test]
fn test_string() {
the_same("".to_string());
the_same("a".to_string());
}
#[test]
fn test_tuple() {
the_same((1isize,));
the_same((1isize, 2isize, 3isize));
the_same((1isize, "foo".to_string(), ()));
}
#[test]
fn test_basic_struct() {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
struct Easy {
x: isize,
s: String,
y: usize,
}
the_same(Easy {
x: -4,
s: "foo".to_string(),
y: 10,
});
}
#[test]
fn test_nested_struct() {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
struct Easy {
x: isize,
s: String,
y: usize,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
struct Nest {
f: Easy,
b: usize,
s: Easy,
}
the_same(Nest {
f: Easy {
x: -1,
s: "foo".to_string(),
y: 20,
},
b: 100,
s: Easy {
x: -100,
s: "bar".to_string(),
y: 20,
},
});
}
#[test]
fn test_struct_newtype() {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
struct NewtypeStr(usize);
the_same(NewtypeStr(5));
}
#[test]
fn test_struct_tuple() {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
struct TubStr(usize, String, f32);
the_same(TubStr(5, "hello".to_string(), 3.2));
}
#[test]
fn test_option() {
the_same(Some(5usize));
the_same(Some("foo bar".to_string()));
the_same(None::<usize>);
}
#[test]
fn test_enum() {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
enum TestEnum {
NoArg,
OneArg(usize),
Args(usize, usize),
AnotherNoArg,
StructLike { x: usize, y: f32 },
}
the_same(TestEnum::NoArg);
the_same(TestEnum::OneArg(4));
//the_same(TestEnum::Args(4, 5));
the_same(TestEnum::AnotherNoArg);
the_same(TestEnum::StructLike { x: 4, y: 3.14159 });
the_same(vec![
TestEnum::NoArg,
TestEnum::OneArg(5),
TestEnum::AnotherNoArg,
TestEnum::StructLike { x: 4, y: 1.4 },
]);
}
#[test]
fn test_vec() {
let v: Vec<u8> = vec![];
the_same(v);
the_same(vec![1u64]);
the_same(vec![1u64, 2, 3, 4, 5, 6]);
}
#[test]
fn test_map() {
let mut m = HashMap::new();
m.insert(4u64, "foo".to_string());
m.insert(0u64, "bar".to_string());
the_same(m);
}
#[test]
fn test_bool() {
the_same(true);
the_same(false);
}
#[test]
fn test_unicode() {
the_same("å".to_string());
the_same("aåååååååa".to_string());
}
#[test]
fn test_fixed_size_array() {
the_same([24u32; 32]);
the_same([1u64, 2, 3, 4, 5, 6, 7, 8]);
the_same([0u8; 19]);
}
#[test]
fn deserializing_errors() {
match *deserialize::<bool>(&vec![0xA][..]).unwrap_err() {
ErrorKind::InvalidBoolEncoding(0xA) => {}
_ => panic!(),
}
let invalid_str = vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF];
match *deserialize::<String>(&invalid_str[..]).unwrap_err() {
ErrorKind::InvalidUtf8Encoding(_) => {}
_ => panic!(),
}
// Out-of-bounds variant
#[derive(Serialize, Deserialize, Debug)]
enum Test {
One,
Two,
};
let invalid_enum = vec![0, 0, 0, 5];
match *deserialize::<Test>(&invalid_enum[..]).unwrap_err() {
// Error message comes from serde
ErrorKind::Custom(_) => {}
_ => panic!(),
}
match *deserialize::<Option<u8>>(&vec![5, 0][..]).unwrap_err() {
ErrorKind::InvalidTagEncoding(_) => {}
_ => panic!(),
}
}
#[test]
fn trailing_bytes() {
match DefaultOptions::new()
.deserialize::<char>(b"1x")
.map_err(|e| *e)
{
Err(ErrorKind::Custom(_)) => {}
other => panic!("Expecting TrailingBytes, got {:?}", other),
}
}
#[test]
fn too_big_deserialize() {
let serialized = vec![0, 0, 0, 3];
let deserialized: Result<u32> = DefaultOptions::new()
.with_fixint_encoding()
.with_limit(3)
.deserialize_from(&mut &serialized[..]);
assert!(deserialized.is_err());
let serialized = vec![0, 0, 0, 3];
let deserialized: Result<u32> = DefaultOptions::new()
.with_fixint_encoding()
.with_limit(4)
.deserialize_from(&mut &serialized[..]);
assert!(deserialized.is_ok());
}
#[test]
fn char_serialization() {
let chars = "Aa\0☺♪";
for c in chars.chars() {
let encoded = DefaultOptions::new()
.with_limit(4)
.serialize(&c)
.expect("serializing char failed");
let decoded: char = deserialize(&encoded).expect("deserializing failed");
assert_eq!(decoded, c);
}
}
#[test]
fn too_big_char_deserialize() {
let serialized = vec![0x41];
let deserialized: Result<char> = DefaultOptions::new()
.with_limit(1)
.deserialize_from(&mut &serialized[..]);
assert!(deserialized.is_ok());
assert_eq!(deserialized.unwrap(), 'A');
}
#[test]
fn too_big_serialize() {
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(3)
.serialize(&0u32)
.is_err());
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(4)
.serialize(&0u32)
.is_ok());
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(LEN_SIZE + 4)
.serialize(&"abcde")
.is_err());
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(LEN_SIZE + 5)
.serialize(&"abcde")
.is_ok());
}
#[test]
fn test_serialized_size() {
assert!(serialized_size(&0u8).unwrap() == 1);
assert!(serialized_size(&0u16).unwrap() == 2);
assert!(serialized_size(&0u32).unwrap() == 4);
assert!(serialized_size(&0u64).unwrap() == 8);
// length isize stored as u64
assert!(serialized_size(&"").unwrap() == LEN_SIZE);
assert!(serialized_size(&"a").unwrap() == LEN_SIZE + 1);
assert!(serialized_size(&vec![0u32, 1u32, 2u32]).unwrap() == LEN_SIZE + 3 * (4));
}
#[test]
fn test_serialized_size_bounded() {
// JUST RIGHT
assert!(
DefaultOptions::new()
.with_fixint_encoding()
.with_limit(1)
.serialized_size(&0u8)
.unwrap()
== 1
);
assert!(
DefaultOptions::new()
.with_fixint_encoding()
.with_limit(2)
.serialized_size(&0u16)
.unwrap()
== 2
);
assert!(
DefaultOptions::new()
.with_fixint_encoding()
.with_limit(4)
.serialized_size(&0u32)
.unwrap()
== 4
);
assert!(
DefaultOptions::new()
.with_fixint_encoding()
.with_limit(8)
.serialized_size(&0u64)
.unwrap()
== 8
);
assert!(
DefaultOptions::new()
.with_fixint_encoding()
.with_limit(8)
.serialized_size(&"")
.unwrap()
== LEN_SIZE
);
assert!(
DefaultOptions::new()
.with_fixint_encoding()
.with_limit(8 + 1)
.serialized_size(&"a")
.unwrap()
== LEN_SIZE + 1
);
assert!(
DefaultOptions::new()
.with_fixint_encoding()
.with_limit(LEN_SIZE + 3 * 4)
.serialized_size(&vec![0u32, 1u32, 2u32])
.unwrap()
== LEN_SIZE + 3 * 4
);
// Below
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(0)
.serialized_size(&0u8)
.is_err());
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(1)
.serialized_size(&0u16)
.is_err());
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(3)
.serialized_size(&0u32)
.is_err());
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(7)
.serialized_size(&0u64)
.is_err());
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(7)
.serialized_size(&"")
.is_err());
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(8 + 0)
.serialized_size(&"a")
.is_err());
assert!(DefaultOptions::new()
.with_fixint_encoding()
.with_limit(8 + 3 * 4 - 1)
.serialized_size(&vec![0u32, 1u32, 2u32])
.is_err());
}
#[test]
fn encode_box() {
the_same(Box::new(5));
}
#[test]
fn test_cow_serialize() {
let large_object = vec![1u32, 2, 3, 4, 5, 6];
let mut large_map = HashMap::new();
large_map.insert(1, 2);
#[derive(Serialize, Deserialize, Debug)]
enum Message<'a> {
M1(Cow<'a, Vec<u32>>),
M2(Cow<'a, HashMap<u32, u32>>),
}
// Test 1
{
let serialized = serialize(&Message::M1(Cow::Borrowed(&large_object))).unwrap();
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..]).unwrap();
match deserialized {
Message::M1(b) => assert!(&b.into_owned() == &large_object),
_ => assert!(false),
}
}
// Test 2
{
let serialized = serialize(&Message::M2(Cow::Borrowed(&large_map))).unwrap();
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..]).unwrap();
match deserialized {
Message::M2(b) => assert!(&b.into_owned() == &large_map),
_ => assert!(false),
}
}
}
#[test]
fn test_strbox_serialize() {
let strx: &'static str = "hello world";
let serialized = serialize(&Cow::Borrowed(strx)).unwrap();
let deserialized: Cow<'static, String> = deserialize_from(&mut &serialized[..]).unwrap();
let stringx: String = deserialized.into_owned();
assert!(strx == &stringx[..]);
}
#[test]
fn test_slicebox_serialize() {
let slice = [1u32, 2, 3, 4, 5];
let serialized = serialize(&Cow::Borrowed(&slice[..])).unwrap();
println!("{:?}", serialized);
let deserialized: Cow<'static, Vec<u32>> = deserialize_from(&mut &serialized[..]).unwrap();
{
let sb: &[u32] = &deserialized;
assert!(slice == sb);
}
let vecx: Vec<u32> = deserialized.into_owned();
assert!(slice == &vecx[..]);
}
#[test]
fn test_multi_strings_serialize() {
assert!(serialize(&("foo", "bar", "baz")).is_ok());
}
#[test]
fn test_oom_protection() {
use std::io::Cursor;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct FakeVec {
len: u64,
byte: u8,
}
let x = DefaultOptions::new()
.with_limit(10)
.serialize(&FakeVec {
len: 0xffffffffffffffffu64,
byte: 1,
})
.unwrap();
let y: Result<Vec<u8>> = DefaultOptions::new()
.with_limit(10)
.deserialize_from(&mut Cursor::new(&x[..]));
assert!(y.is_err());
}
#[test]
fn path_buf() {
use std::path::{Path, PathBuf};
let path = Path::new("foo").to_path_buf();
let serde_encoded = serialize(&path).unwrap();
let decoded: PathBuf = deserialize(&serde_encoded).unwrap();
assert!(path.to_str() == decoded.to_str());
}
#[test]
fn bytes() {
use serde_bytes::Bytes;
let data = b"abc\0123";
let s = serialize(&data[..]).unwrap();
let s2 = serialize(&Bytes::new(data)).unwrap();
assert_eq!(s[..], s2[..]);
}
#[test]
fn serde_bytes() {
use serde_bytes::ByteBuf;
the_same(ByteBuf::from(vec![1, 2, 3, 4, 5]));
}
#[test]
fn endian_difference() {
let x = 10u64;
let little = serialize(&x).unwrap();
let big = DefaultOptions::new()
.with_big_endian()
.serialize(&x)
.unwrap();
assert_ne!(little, big);
}
#[test]
fn test_zero_copy_parse() {
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
struct Foo<'a> {
borrowed_str: &'a str,
borrowed_bytes: &'a [u8],
}
let f = Foo {
borrowed_str: "hi",
borrowed_bytes: &[0, 1, 2, 3],
};
{
let encoded = serialize(&f).unwrap();
let out: Foo = deserialize(&encoded[..]).unwrap();
assert_eq!(out, f);
}
}
#[test]
fn test_zero_copy_parse_deserialize_into() {
use bincode::BincodeRead;
use std::io;
/// A BincodeRead implementation for byte slices
pub struct SliceReader<'storage> {
slice: &'storage [u8],
}
impl<'storage> SliceReader<'storage> {
#[inline(always)]
fn unexpected_eof() -> Box<::ErrorKind> {
return Box::new(::ErrorKind::Io(io::Error::new(
io::ErrorKind::UnexpectedEof,
"",
)));
}
}
impl<'storage> io::Read for SliceReader<'storage> {
#[inline(always)]
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
(&mut self.slice).read(out)
}
#[inline(always)]
fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {
(&mut self.slice).read_exact(out)
}
}
impl<'storage> BincodeRead<'storage> for SliceReader<'storage> {
#[inline(always)]
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>,
{
use ErrorKind;
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let string = match ::std::str::from_utf8(&self.slice[..length]) {
Ok(s) => s,
Err(e) => return Err(ErrorKind::InvalidUtf8Encoding(e).into()),
};
let r = visitor.visit_borrowed_str(string);
self.slice = &self.slice[length..];
r
}
#[inline(always)]
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let r = &self.slice[..length];
self.slice = &self.slice[length..];
Ok(r.to_vec())
}
#[inline(always)]
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>,
{
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let r = visitor.visit_borrowed_bytes(&self.slice[..length]);
self.slice = &self.slice[length..];
r
}
}
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
struct Foo<'a> {
borrowed_str: &'a str,
borrowed_bytes: &'a [u8],
}
let f = Foo {
borrowed_str: "hi",
borrowed_bytes: &[0, 1, 2, 3],
};
{
let encoded = serialize(&f).unwrap();
let mut target = Foo {
borrowed_str: "hello",
borrowed_bytes: &[10, 11, 12, 13],
};
deserialize_in_place(
SliceReader {
slice: &encoded[..],
},
&mut target,
)
.unwrap();
assert_eq!(target, f);
}
}
#[test]
fn not_human_readable() {
use std::net::Ipv4Addr;
let ip = Ipv4Addr::new(1, 2, 3, 4);
the_same(ip);
assert_eq!(&ip.octets()[..], &serialize(&ip).unwrap()[..]);
assert_eq!(
::std::mem::size_of::<Ipv4Addr>() as u64,
serialized_size(&ip).unwrap()
);
}
// The example is taken from serde::de::DeserializeSeed.
struct ExtendVec<'a, T: 'a>(&'a mut Vec<T>);
impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T>
where
T: Deserialize<'de>,
{
// The return type of the `deserialize` method. This implementation
// appends onto an existing vector but does not create any new data
// structure, so the return type is ().
type Value = ();
fn deserialize<D>(self, deserializer: D) -> StdResult<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
// Visitor implementation that will walk an inner array of the JSON
// input.
struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>);
impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T>
where
T: Deserialize<'de>,
{
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an array of integers")
}
fn visit_seq<A>(self, mut seq: A) -> StdResult<(), A::Error>
where
A: SeqAccess<'de>,
{
// Visit each element in the inner array and push it onto
// the existing vector.
while let Some(elem) = seq.next_element()? {
self.0.push(elem);
}
Ok(())
}
}
deserializer.deserialize_seq(ExtendVecVisitor(self.0))
}
}
#[test]
fn test_default_deserialize_seed() {
let config = DefaultOptions::new();
let data: Vec<_> = (10..100).collect();
let bytes = config.serialize(&data).expect("Config::serialize failed");
let mut seed_data: Vec<_> = (0..10).collect();
{
let seed = ExtendVec(&mut seed_data);
config
.deserialize_seed(seed, &bytes)
.expect("Config::deserialize_seed failed");
}
assert_eq!(seed_data, (0..100).collect::<Vec<_>>());
}
#[test]
fn test_big_endian_deserialize_seed() {
let config = DefaultOptions::new().with_big_endian();
let data: Vec<_> = (10..100).collect();
let bytes = config.serialize(&data).expect("Config::serialize failed");
let mut seed_data: Vec<_> = (0..10).collect();
{
let seed = ExtendVec(&mut seed_data);
config
.deserialize_seed(seed, &bytes)
.expect("Config::deserialize_seed failed");
}
assert_eq!(seed_data, (0..100).collect::<Vec<_>>());
}
#[test]
fn test_default_deserialize_from_seed() {
let config = DefaultOptions::new();
let data: Vec<_> = (10..100).collect();
let bytes = config.serialize(&data).expect("Config::serialize failed");
let mut seed_data: Vec<_> = (0..10).collect();
{
let seed = ExtendVec(&mut seed_data);
config
.deserialize_from_seed(seed, &mut &*bytes)
.expect("Config::deserialize_from_seed failed");
}
assert_eq!(seed_data, (0..100).collect::<Vec<_>>());
}
#[test]
fn test_big_endian_deserialize_from_seed() {
let config = DefaultOptions::new().with_big_endian();
let data: Vec<_> = (10..100).collect();
let bytes = config.serialize(&data).expect("Config::serialize failed");
let mut seed_data: Vec<_> = (0..10).collect();
{
let seed = ExtendVec(&mut seed_data);
config
.deserialize_from_seed(seed, &mut &*bytes)
.expect("Config::deserialize_from_seed failed");
}
assert_eq!(seed_data, (0..100).collect::<Vec<_>>());
}
#[test]
fn test_varint_length_prefixes() {
let a = vec![(); 127]; // should be a single byte
let b = vec![(); 250]; // also should be a single byte
let c = vec![(); 251];
let d = vec![(); u16::max_value() as usize + 1];
assert_eq!(
DefaultOptions::new()
.with_varint_encoding()
.serialized_size(&a[..])
.unwrap(),
1
); // 2 ** 7 - 1
assert_eq!(
DefaultOptions::new()
.with_varint_encoding()
.serialized_size(&b[..])
.unwrap(),
1
); // 250
assert_eq!(
DefaultOptions::new()
.with_varint_encoding()
.serialized_size(&c[..])
.unwrap(),
(1 + std::mem::size_of::<u16>()) as u64
); // 251
assert_eq!(
DefaultOptions::new()
.with_varint_encoding()
.serialized_size(&d[..])
.unwrap(),
(1 + std::mem::size_of::<u32>()) as u64
); // 2 ** 16 + 1
}
#[test]
fn test_byte_vec_struct() {
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
struct ByteVecs {
a: Vec<u8>,
b: Vec<u8>,
c: Vec<u8>,
};
let byte_struct = ByteVecs {
a: vec![2; 20],
b: vec![3; 30],
c: vec![1; 10],
};
the_same(byte_struct);
}