mirror of https://git.sr.ht/~stygianentity/bincode
Varint enum tags and lengths (#306)
Adds varint encoding to all numbers, including sequence lengths and enum discriminants. Varints are encoded according to the following scheme 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`. Signed integers are first encoded using zigzag format (see docs for details) Co-authored-by: Maciej Hirsz <maciej.hirsz@gmail.com> Co-authored-by: Nicole Mazzuca <nicole@strega-nil.co>
This commit is contained in:
parent
559b593ba3
commit
c27e9c6874
734
src/config.rs
734
src/config.rs
|
|
@ -4,6 +4,7 @@ use error::{ErrorKind, Result};
|
|||
use serde;
|
||||
use std::io::{Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::size_of;
|
||||
|
||||
pub(crate) use self::internal::*;
|
||||
|
||||
|
|
@ -11,10 +12,9 @@ use self::EndianOption::*;
|
|||
use self::LimitOption::*;
|
||||
|
||||
/// The default options for bincode serialization/deserialization.
|
||||
/// Implements OptionsExt to allow building configuration object for non-default settings.
|
||||
///
|
||||
/// ### Defaults
|
||||
/// By default bincode will use little-endian encoding for mult-byte integers, and will not
|
||||
/// By default bincode will use little-endian encoding for multi-byte integers, and will not
|
||||
/// limit the number of serialized/deserialized bytes.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct DefaultOptions(Infinite);
|
||||
|
|
@ -38,9 +38,10 @@ impl Default for DefaultOptions {
|
|||
}
|
||||
}
|
||||
|
||||
impl Options for DefaultOptions {
|
||||
impl InternalOptions for DefaultOptions {
|
||||
type Limit = Infinite;
|
||||
type Endian = LittleEndian;
|
||||
type IntEncoding = FixintEncoding;
|
||||
|
||||
#[inline(always)]
|
||||
fn limit(&mut self) -> &mut Infinite {
|
||||
|
|
@ -64,7 +65,7 @@ impl Options for DefaultOptions {
|
|||
/// serialization that goes over the limit.
|
||||
/// Sets the byte limit to be unlimited.
|
||||
/// This is the default.
|
||||
pub trait OptionsExt: Options + Sized {
|
||||
pub trait Options: InternalOptions + Sized {
|
||||
/// Sets the byte limit to be unlimited.
|
||||
/// This is the default.
|
||||
fn with_no_limit(self) -> WithOtherLimit<Self, Infinite> {
|
||||
|
|
@ -92,6 +93,16 @@ pub trait OptionsExt: Options + Sized {
|
|||
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)
|
||||
}
|
||||
|
||||
/// 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>> {
|
||||
|
|
@ -188,7 +199,7 @@ pub trait OptionsExt: Options + Sized {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Options> OptionsExt for T {}
|
||||
impl<T: InternalOptions> Options for T {}
|
||||
|
||||
/// A SizeLimit that restricts serialized or deserialized messages from
|
||||
/// exceeding a certain byte length.
|
||||
|
|
@ -253,6 +264,533 @@ impl BincodeByteOrder for NativeEndian {
|
|||
type Endian = byteorder::NativeEndian;
|
||||
}
|
||||
|
||||
/// 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()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum LimitOption {
|
||||
Unlimited,
|
||||
|
|
@ -303,6 +841,12 @@ pub struct WithOtherEndian<O: Options, E: BincodeByteOrder> {
|
|||
_endian: PhantomData<E>,
|
||||
}
|
||||
|
||||
/// A configuration struct with a user-specified length encoding
|
||||
pub struct WithOtherIntEncoding<O: Options, I: IntEncoding> {
|
||||
options: O,
|
||||
_length: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<O: Options, L: SizeLimit> WithOtherLimit<O, L> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn new(options: O, limit: L) -> WithOtherLimit<O, L> {
|
||||
|
|
@ -323,9 +867,20 @@ impl<O: Options, E: BincodeByteOrder> WithOtherEndian<O, E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<O: Options, E: BincodeByteOrder + 'static> Options for WithOtherEndian<O, E> {
|
||||
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, E: BincodeByteOrder + 'static> InternalOptions for WithOtherEndian<O, E> {
|
||||
type Limit = O::Limit;
|
||||
type Endian = E;
|
||||
type IntEncoding = O::IntEncoding;
|
||||
|
||||
#[inline(always)]
|
||||
fn limit(&mut self) -> &mut O::Limit {
|
||||
|
|
@ -333,15 +888,26 @@ impl<O: Options, E: BincodeByteOrder + 'static> Options for WithOtherEndian<O, E
|
|||
}
|
||||
}
|
||||
|
||||
impl<O: Options, L: SizeLimit + 'static> Options for WithOtherLimit<O, L> {
|
||||
impl<O: Options, L: SizeLimit + 'static> InternalOptions for WithOtherLimit<O, L> {
|
||||
type Limit = L;
|
||||
type Endian = O::Endian;
|
||||
type IntEncoding = O::IntEncoding;
|
||||
|
||||
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;
|
||||
|
||||
fn limit(&mut self) -> &mut O::Limit {
|
||||
self.options.limit()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! config_map {
|
||||
($self:expr, $opts:ident => $call:expr) => {
|
||||
match ($self.limit, $self.endian) {
|
||||
|
|
@ -531,16 +1097,18 @@ mod internal {
|
|||
use super::*;
|
||||
use byteorder::ByteOrder;
|
||||
|
||||
pub trait Options {
|
||||
pub trait InternalOptions {
|
||||
type Limit: SizeLimit + 'static;
|
||||
type Endian: BincodeByteOrder + 'static;
|
||||
type IntEncoding: IntEncoding + 'static;
|
||||
|
||||
fn limit(&mut self) -> &mut Self::Limit;
|
||||
}
|
||||
|
||||
impl<'a, O: Options> Options for &'a mut O {
|
||||
impl<'a, O: InternalOptions> InternalOptions for &'a mut O {
|
||||
type Limit = O::Limit;
|
||||
type Endian = O::Endian;
|
||||
type IntEncoding = O::IntEncoding;
|
||||
|
||||
#[inline(always)]
|
||||
fn limit(&mut self) -> &mut Self::Limit {
|
||||
|
|
@ -560,4 +1128,152 @@ mod internal {
|
|||
pub trait BincodeByteOrder {
|
||||
type Endian: ByteOrder + 'static;
|
||||
}
|
||||
|
||||
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>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
105
src/de/mod.rs
105
src/de/mod.rs
|
|
@ -3,7 +3,7 @@ use std::io::Read;
|
|||
|
||||
use self::read::{BincodeRead, IoReader, SliceReader};
|
||||
use byteorder::ReadBytesExt;
|
||||
use config::SizeLimit;
|
||||
use config::{IntEncoding, SizeLimit};
|
||||
use serde;
|
||||
use serde::de::Error as DeError;
|
||||
use serde::de::IntoDeserializer;
|
||||
|
|
@ -30,6 +30,18 @@ pub struct Deserializer<R, O: Options> {
|
|||
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, R: BincodeRead<'de>, O: Options> Deserializer<R, O> {
|
||||
/// Creates a new Deserializer with a given `Read`er and options.
|
||||
pub fn with_reader<IR: Read>(r: IR, options: O) -> Deserializer<IoReader<IR>, O> {
|
||||
|
|
@ -52,17 +64,30 @@ impl<'de, R: BincodeRead<'de>, O: Options> 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_type<T>(&mut self) -> Result<()> {
|
||||
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: usize = serde::Deserialize::deserialize(&mut *self)?;
|
||||
let len = O::IntEncoding::deserialize_len(self)?;
|
||||
self.read_bytes(len as u64)?;
|
||||
self.reader.get_byte_buffer(len)
|
||||
}
|
||||
|
|
@ -73,17 +98,16 @@ impl<'de, R: BincodeRead<'de>, O: Options> Deserializer<R, O> {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_nums {
|
||||
($ty:ty, $dser_method:ident, $visitor_method:ident, $reader_method:ident) => {
|
||||
macro_rules! impl_deserialize_int {
|
||||
($name:ident = $visitor_method:ident ($dser_method:ident)) => {
|
||||
#[inline]
|
||||
fn $dser_method<V>(self, visitor: V) -> Result<V::Value>
|
||||
where V: serde::de::Visitor<'de>,
|
||||
fn $name<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: serde::de::Visitor<'de>,
|
||||
{
|
||||
self.read_type::<$ty>()?;
|
||||
let value = self.reader.$reader_method::<<O::Endian as BincodeByteOrder>::Endian>()?;
|
||||
visitor.$visitor_method(value)
|
||||
}
|
||||
visitor.$visitor_method(O::IntEncoding::$dser_method(self)?)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<'de, 'a, R, O> serde::Deserializer<'de> for &'a mut Deserializer<R, O>
|
||||
|
|
@ -105,26 +129,45 @@ where
|
|||
where
|
||||
V: serde::de::Visitor<'de>,
|
||||
{
|
||||
let value: u8 = serde::Deserialize::deserialize(self)?;
|
||||
match value {
|
||||
match self.deserialize_byte()? {
|
||||
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);
|
||||
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_nums!(u128, deserialize_u128, visit_u128, read_u128);
|
||||
impl_nums!(i128, deserialize_i128, visit_i128, read_i128);
|
||||
impl_deserialize_int!(deserialize_u128 = visit_u128(deserialize_u128));
|
||||
impl_deserialize_int!(deserialize_i128 = visit_i128(deserialize_i128));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -132,8 +175,7 @@ where
|
|||
where
|
||||
V: serde::de::Visitor<'de>,
|
||||
{
|
||||
self.read_type::<u8>()?;
|
||||
visitor.visit_u8(self.reader.read_u8()?)
|
||||
visitor.visit_u8(self.deserialize_byte()? as u8)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -141,8 +183,7 @@ where
|
|||
where
|
||||
V: serde::de::Visitor<'de>,
|
||||
{
|
||||
self.read_type::<i8>()?;
|
||||
visitor.visit_i8(self.reader.read_i8()?)
|
||||
visitor.visit_i8(self.deserialize_byte()? as i8)
|
||||
}
|
||||
|
||||
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
|
||||
|
|
@ -187,7 +228,7 @@ where
|
|||
where
|
||||
V: serde::de::Visitor<'de>,
|
||||
{
|
||||
let len: usize = serde::Deserialize::deserialize(&mut *self)?;
|
||||
let len = O::IntEncoding::deserialize_len(self)?;
|
||||
self.read_bytes(len as u64)?;
|
||||
self.reader.forward_read_str(len, visitor)
|
||||
}
|
||||
|
|
@ -203,7 +244,7 @@ where
|
|||
where
|
||||
V: serde::de::Visitor<'de>,
|
||||
{
|
||||
let len: usize = serde::Deserialize::deserialize(&mut *self)?;
|
||||
let len = O::IntEncoding::deserialize_len(self)?;
|
||||
self.read_bytes(len as u64)?;
|
||||
self.reader.forward_read_bytes(len, visitor)
|
||||
}
|
||||
|
|
@ -236,7 +277,7 @@ where
|
|||
where
|
||||
V: serde::de::DeserializeSeed<'de>,
|
||||
{
|
||||
let idx: u32 = serde::de::Deserialize::deserialize(&mut *self)?;
|
||||
let idx: u32 = O::IntEncoding::deserialize_u32(self)?;
|
||||
let val: Result<_> = seed.deserialize(idx.into_deserializer());
|
||||
Ok((val?, self))
|
||||
}
|
||||
|
|
@ -300,7 +341,7 @@ where
|
|||
where
|
||||
V: serde::de::Visitor<'de>,
|
||||
{
|
||||
let len = serde::Deserialize::deserialize(&mut *self)?;
|
||||
let len = O::IntEncoding::deserialize_len(self)?;
|
||||
|
||||
self.deserialize_tuple(len, visitor)
|
||||
}
|
||||
|
|
@ -346,7 +387,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
let len = serde::Deserialize::deserialize(&mut *self)?;
|
||||
let len = O::IntEncoding::deserialize_len(self)?;
|
||||
|
||||
visitor.visit_map(Access {
|
||||
deserializer: self,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use serde;
|
|||
use std::io::{Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use config::{Infinite, Options, OptionsExt, SizeLimit};
|
||||
use config::{Infinite, InternalOptions, Options, SizeLimit};
|
||||
use de::read::BincodeRead;
|
||||
use Result;
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ pub(crate) fn serialize_into<W, T: ?Sized, O>(writer: W, value: &T, mut options:
|
|||
where
|
||||
W: Write,
|
||||
T: serde::Serialize,
|
||||
O: Options,
|
||||
O: InternalOptions,
|
||||
{
|
||||
if options.limit().limit().is_some() {
|
||||
// "compute" the size for the side-effect
|
||||
|
|
@ -25,7 +25,7 @@ where
|
|||
pub(crate) fn serialize<T: ?Sized, O>(value: &T, mut options: O) -> Result<Vec<u8>>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
O: Options,
|
||||
O: InternalOptions,
|
||||
{
|
||||
let mut writer = {
|
||||
let actual_size = serialized_size(value, &mut options)?;
|
||||
|
|
@ -36,7 +36,7 @@ where
|
|||
Ok(writer)
|
||||
}
|
||||
|
||||
pub(crate) fn serialized_size<T: ?Sized, O: Options>(value: &T, options: O) -> Result<u64>
|
||||
pub(crate) fn serialized_size<T: ?Sized, O: InternalOptions>(value: &T, options: O) -> Result<u64>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
{
|
||||
|
|
@ -50,7 +50,7 @@ pub(crate) fn deserialize_from<R, T, O>(reader: R, options: O) -> Result<T>
|
|||
where
|
||||
R: Read,
|
||||
T: serde::de::DeserializeOwned,
|
||||
O: Options,
|
||||
O: InternalOptions,
|
||||
{
|
||||
deserialize_from_seed(PhantomData, reader, options)
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ pub(crate) fn deserialize_from_seed<'a, R, T, O>(seed: T, reader: R, options: O)
|
|||
where
|
||||
R: Read,
|
||||
T: serde::de::DeserializeSeed<'a>,
|
||||
O: Options,
|
||||
O: InternalOptions,
|
||||
{
|
||||
let reader = ::de::read::IoReader::new(reader);
|
||||
deserialize_from_custom_seed(seed, reader, options)
|
||||
|
|
@ -69,7 +69,7 @@ pub(crate) fn deserialize_from_custom<'a, R, T, O>(reader: R, options: O) -> Res
|
|||
where
|
||||
R: BincodeRead<'a>,
|
||||
T: serde::de::DeserializeOwned,
|
||||
O: Options,
|
||||
O: InternalOptions,
|
||||
{
|
||||
deserialize_from_custom_seed(PhantomData, reader, options)
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ pub(crate) fn deserialize_from_custom_seed<'a, R, T, O>(
|
|||
where
|
||||
R: BincodeRead<'a>,
|
||||
T: serde::de::DeserializeSeed<'a>,
|
||||
O: Options,
|
||||
O: InternalOptions,
|
||||
{
|
||||
let mut deserializer = ::de::Deserializer::<_, O>::with_bincode_read(reader, options);
|
||||
seed.deserialize(&mut deserializer)
|
||||
|
|
@ -92,7 +92,7 @@ pub(crate) fn deserialize_in_place<'a, R, T, O>(reader: R, options: O, place: &m
|
|||
where
|
||||
R: BincodeRead<'a>,
|
||||
T: serde::de::Deserialize<'a>,
|
||||
O: Options,
|
||||
O: InternalOptions,
|
||||
{
|
||||
let mut deserializer = ::de::Deserializer::<_, _>::with_bincode_read(reader, options);
|
||||
serde::Deserialize::deserialize_in_place(&mut deserializer, place)
|
||||
|
|
@ -101,7 +101,7 @@ where
|
|||
pub(crate) fn deserialize<'a, T, O>(bytes: &'a [u8], options: O) -> Result<T>
|
||||
where
|
||||
T: serde::de::Deserialize<'a>,
|
||||
O: Options,
|
||||
O: InternalOptions,
|
||||
{
|
||||
deserialize_seed(PhantomData, bytes, options)
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ where
|
|||
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,
|
||||
O: InternalOptions,
|
||||
{
|
||||
let reader = ::de::read::SliceReader::new(bytes);
|
||||
let options = ::config::WithOtherLimit::new(options, Infinite);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ mod error;
|
|||
mod internal;
|
||||
mod ser;
|
||||
|
||||
pub use config::{Config, DefaultOptions, OptionsExt};
|
||||
pub use config::{Config, DefaultOptions, Options};
|
||||
pub use de::read::BincodeRead;
|
||||
pub use de::Deserializer;
|
||||
pub use error::{Error, ErrorKind, Result};
|
||||
|
|
|
|||
208
src/ser/mod.rs
208
src/ser/mod.rs
|
|
@ -5,9 +5,10 @@ use serde;
|
|||
|
||||
use byteorder::WriteBytesExt;
|
||||
|
||||
use super::config::SizeLimit;
|
||||
use super::config::{IntEncoding, SizeLimit};
|
||||
use super::{Error, ErrorKind, Result};
|
||||
use config::{BincodeByteOrder, Options};
|
||||
use std::mem::size_of;
|
||||
|
||||
/// An Serializer that encodes values directly into a Writer.
|
||||
///
|
||||
|
|
@ -21,6 +22,16 @@ pub struct Serializer<W, O: Options> {
|
|||
_options: O,
|
||||
}
|
||||
|
||||
macro_rules! impl_serialize_literal {
|
||||
($ser_method:ident($ty:ty) = $write:ident()) => {
|
||||
pub(crate) fn $ser_method(&mut self, v: $ty) -> Result<()> {
|
||||
self.writer
|
||||
.$write::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<W: Write, O: Options> Serializer<W, O> {
|
||||
/// Creates a new Serializer with the given `Write`r.
|
||||
pub fn new(w: W, options: O) -> Serializer<W, O> {
|
||||
|
|
@ -29,6 +40,26 @@ impl<W: Write, O: Options> Serializer<W, O> {
|
|||
_options: options,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn serialize_byte(&mut self, v: u8) -> Result<()> {
|
||||
self.writer.write_u8(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
impl_serialize_literal! {serialize_literal_u16(u16) = write_u16()}
|
||||
impl_serialize_literal! {serialize_literal_u32(u32) = write_u32()}
|
||||
impl_serialize_literal! {serialize_literal_u64(u64) = write_u64()}
|
||||
|
||||
serde_if_integer128! {
|
||||
impl_serialize_literal!{serialize_literal_u128(u128) = write_u128()}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_serialize_int {
|
||||
($ser_method:ident($ty:ty) = $ser_int:ident()) => {
|
||||
fn $ser_method(self, v: $ty) -> Result<()> {
|
||||
O::IntEncoding::$ser_int(self, v)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
||||
|
|
@ -51,79 +82,44 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
|||
}
|
||||
|
||||
fn serialize_bool(self, v: bool) -> Result<()> {
|
||||
self.writer
|
||||
.write_u8(if v { 1 } else { 0 })
|
||||
.map_err(Into::into)
|
||||
self.serialize_byte(v as u8)
|
||||
}
|
||||
|
||||
fn serialize_u8(self, v: u8) -> Result<()> {
|
||||
self.writer.write_u8(v).map_err(Into::into)
|
||||
self.serialize_byte(v)
|
||||
}
|
||||
|
||||
fn serialize_u16(self, v: u16) -> Result<()> {
|
||||
self.writer
|
||||
.write_u16::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_u32(self, v: u32) -> Result<()> {
|
||||
self.writer
|
||||
.write_u32::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_u64(self, v: u64) -> Result<()> {
|
||||
self.writer
|
||||
.write_u64::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
impl_serialize_int! {serialize_u16(u16) = serialize_u16()}
|
||||
impl_serialize_int! {serialize_u32(u32) = serialize_u32()}
|
||||
impl_serialize_int! {serialize_u64(u64) = serialize_u64()}
|
||||
|
||||
fn serialize_i8(self, v: i8) -> Result<()> {
|
||||
self.writer.write_i8(v).map_err(Into::into)
|
||||
self.serialize_byte(v as u8)
|
||||
}
|
||||
|
||||
fn serialize_i16(self, v: i16) -> Result<()> {
|
||||
self.writer
|
||||
.write_i16::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_i32(self, v: i32) -> Result<()> {
|
||||
self.writer
|
||||
.write_i32::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_i64(self, v: i64) -> Result<()> {
|
||||
self.writer
|
||||
.write_i64::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
impl_serialize_int! {serialize_i16(i16) = serialize_i16()}
|
||||
impl_serialize_int! {serialize_i32(i32) = serialize_i32()}
|
||||
impl_serialize_int! {serialize_i64(i64) = serialize_i64()}
|
||||
|
||||
serde_if_integer128! {
|
||||
fn serialize_u128(self, v: u128) -> Result<()> {
|
||||
self.writer.write_u128::<<O::Endian as BincodeByteOrder>::Endian>(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_i128(self, v: i128) -> Result<()> {
|
||||
self.writer.write_i128::<<O::Endian as BincodeByteOrder>::Endian>(v).map_err(Into::into)
|
||||
}
|
||||
impl_serialize_int!{serialize_u128(u128) = serialize_u128()}
|
||||
impl_serialize_int!{serialize_i128(i128) = serialize_i128()}
|
||||
}
|
||||
|
||||
fn serialize_f32(self, v: f32) -> Result<()> {
|
||||
self.writer
|
||||
.write_f32::<<<O as Options>::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.write_f32::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_f64(self, v: f64) -> Result<()> {
|
||||
self.writer
|
||||
.write_f64::<<<O as Options>::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.write_f64::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_str(self, v: &str) -> Result<()> {
|
||||
self.serialize_u64(v.len() as u64)?;
|
||||
O::IntEncoding::serialize_len(self, v.len())?;
|
||||
self.writer.write_all(v.as_bytes()).map_err(Into::into)
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +130,7 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
|||
}
|
||||
|
||||
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
|
||||
self.serialize_u64(v.len() as u64)?;
|
||||
O::IntEncoding::serialize_len(self, v.len())?;
|
||||
self.writer.write_all(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +148,7 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
|||
|
||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
|
||||
let len = len.ok_or(ErrorKind::SequenceMustHaveLength)?;
|
||||
self.serialize_u64(len as u64)?;
|
||||
O::IntEncoding::serialize_len(self, len)?;
|
||||
Ok(Compound { ser: self })
|
||||
}
|
||||
|
||||
|
|
@ -175,13 +171,13 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant> {
|
||||
self.serialize_u32(variant_index)?;
|
||||
O::IntEncoding::serialize_u32(self, variant_index)?;
|
||||
Ok(Compound { ser: self })
|
||||
}
|
||||
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
|
||||
let len = len.ok_or(ErrorKind::SequenceMustHaveLength)?;
|
||||
self.serialize_u64(len as u64)?;
|
||||
O::IntEncoding::serialize_len(self, len)?;
|
||||
Ok(Compound { ser: self })
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +192,7 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeStructVariant> {
|
||||
self.serialize_u32(variant_index)?;
|
||||
O::IntEncoding::serialize_u32(self, variant_index)?;
|
||||
Ok(Compound { ser: self })
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +213,7 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
|||
where
|
||||
T: serde::ser::Serialize,
|
||||
{
|
||||
self.serialize_u32(variant_index)?;
|
||||
O::IntEncoding::serialize_u32(self, variant_index)?;
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +223,7 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
|||
variant_index: u32,
|
||||
_variant: &'static str,
|
||||
) -> Result<()> {
|
||||
self.serialize_u32(variant_index)
|
||||
O::IntEncoding::serialize_u32(self, variant_index)
|
||||
}
|
||||
|
||||
fn is_human_readable(&self) -> bool {
|
||||
|
|
@ -248,10 +244,23 @@ impl<O: Options> SizeChecker<O> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn add_value<T>(&mut self, t: T) -> Result<()> {
|
||||
use std::mem::size_of_val;
|
||||
self.add_raw(size_of_val(&t) as u64)
|
||||
fn add_discriminant(&mut self, idx: u32) -> Result<()> {
|
||||
let bytes = O::IntEncoding::u32_size(idx);
|
||||
self.add_raw(bytes)
|
||||
}
|
||||
|
||||
fn add_len(&mut self, len: usize) -> Result<()> {
|
||||
let bytes = O::IntEncoding::len_size(len);
|
||||
self.add_raw(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_size_int {
|
||||
($ser_method:ident($ty:ty) = $size_method:ident()) => {
|
||||
fn $ser_method(self, v: $ty) -> Result<()> {
|
||||
self.add_raw(O::IntEncoding::$size_method(v))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<'a, O: Options> serde::Serializer for &'a mut SizeChecker<O> {
|
||||
|
|
@ -274,61 +283,38 @@ impl<'a, O: Options> serde::Serializer for &'a mut SizeChecker<O> {
|
|||
}
|
||||
|
||||
fn serialize_bool(self, _: bool) -> Result<()> {
|
||||
self.add_value(0 as u8)
|
||||
self.add_raw(1)
|
||||
}
|
||||
|
||||
fn serialize_u8(self, v: u8) -> Result<()> {
|
||||
self.add_value(v)
|
||||
fn serialize_u8(self, _: u8) -> Result<()> {
|
||||
self.add_raw(1)
|
||||
}
|
||||
fn serialize_i8(self, _: i8) -> Result<()> {
|
||||
self.add_raw(1)
|
||||
}
|
||||
|
||||
fn serialize_u16(self, v: u16) -> Result<()> {
|
||||
self.add_value(v)
|
||||
}
|
||||
|
||||
fn serialize_u32(self, v: u32) -> Result<()> {
|
||||
self.add_value(v)
|
||||
}
|
||||
|
||||
fn serialize_u64(self, v: u64) -> Result<()> {
|
||||
self.add_value(v)
|
||||
}
|
||||
|
||||
fn serialize_i8(self, v: i8) -> Result<()> {
|
||||
self.add_value(v)
|
||||
}
|
||||
|
||||
fn serialize_i16(self, v: i16) -> Result<()> {
|
||||
self.add_value(v)
|
||||
}
|
||||
|
||||
fn serialize_i32(self, v: i32) -> Result<()> {
|
||||
self.add_value(v)
|
||||
}
|
||||
|
||||
fn serialize_i64(self, v: i64) -> Result<()> {
|
||||
self.add_value(v)
|
||||
}
|
||||
impl_size_int! {serialize_u16(u16) = u16_size()}
|
||||
impl_size_int! {serialize_u32(u32) = u32_size()}
|
||||
impl_size_int! {serialize_u64(u64) = u64_size()}
|
||||
impl_size_int! {serialize_i16(i16) = i16_size()}
|
||||
impl_size_int! {serialize_i32(i32) = i32_size()}
|
||||
impl_size_int! {serialize_i64(i64) = i64_size()}
|
||||
|
||||
serde_if_integer128! {
|
||||
fn serialize_u128(self, v: u128) -> Result<()> {
|
||||
self.add_value(v)
|
||||
impl_size_int!{serialize_u128(u128) = u128_size()}
|
||||
impl_size_int!{serialize_i128(i128) = i128_size()}
|
||||
}
|
||||
|
||||
fn serialize_i128(self, v: i128) -> Result<()> {
|
||||
self.add_value(v)
|
||||
}
|
||||
fn serialize_f32(self, _: f32) -> Result<()> {
|
||||
self.add_raw(size_of::<f32>() as u64)
|
||||
}
|
||||
|
||||
fn serialize_f32(self, v: f32) -> Result<()> {
|
||||
self.add_value(v)
|
||||
}
|
||||
|
||||
fn serialize_f64(self, v: f64) -> Result<()> {
|
||||
self.add_value(v)
|
||||
fn serialize_f64(self, _: f64) -> Result<()> {
|
||||
self.add_raw(size_of::<f64>() as u64)
|
||||
}
|
||||
|
||||
fn serialize_str(self, v: &str) -> Result<()> {
|
||||
self.add_value(0 as u64)?;
|
||||
self.add_len(v.len())?;
|
||||
self.add_raw(v.len() as u64)
|
||||
}
|
||||
|
||||
|
|
@ -337,26 +323,26 @@ impl<'a, O: Options> serde::Serializer for &'a mut SizeChecker<O> {
|
|||
}
|
||||
|
||||
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
|
||||
self.add_value(0 as u64)?;
|
||||
self.add_len(v.len())?;
|
||||
self.add_raw(v.len() as u64)
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<()> {
|
||||
self.add_value(0 as u8)
|
||||
self.add_raw(1)
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, v: &T) -> Result<()>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
{
|
||||
self.add_value(1 as u8)?;
|
||||
self.add_raw(1)?;
|
||||
v.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
|
||||
let len = len.ok_or(ErrorKind::SequenceMustHaveLength)?;
|
||||
|
||||
self.serialize_u64(len as u64)?;
|
||||
self.add_len(len)?;
|
||||
Ok(SizeCompound { ser: self })
|
||||
}
|
||||
|
||||
|
|
@ -379,14 +365,14 @@ impl<'a, O: Options> serde::Serializer for &'a mut SizeChecker<O> {
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant> {
|
||||
self.add_value(variant_index)?;
|
||||
self.add_raw(O::IntEncoding::u32_size(variant_index))?;
|
||||
Ok(SizeCompound { ser: self })
|
||||
}
|
||||
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
|
||||
let len = len.ok_or(ErrorKind::SequenceMustHaveLength)?;
|
||||
|
||||
self.serialize_u64(len as u64)?;
|
||||
self.add_len(len)?;
|
||||
Ok(SizeCompound { ser: self })
|
||||
}
|
||||
|
||||
|
|
@ -401,7 +387,7 @@ impl<'a, O: Options> serde::Serializer for &'a mut SizeChecker<O> {
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeStructVariant> {
|
||||
self.add_value(variant_index)?;
|
||||
self.add_discriminant(variant_index)?;
|
||||
Ok(SizeCompound { ser: self })
|
||||
}
|
||||
|
||||
|
|
@ -419,7 +405,7 @@ impl<'a, O: Options> serde::Serializer for &'a mut SizeChecker<O> {
|
|||
variant_index: u32,
|
||||
_variant: &'static str,
|
||||
) -> Result<()> {
|
||||
self.add_value(variant_index)
|
||||
self.add_discriminant(variant_index)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<V: serde::Serialize + ?Sized>(
|
||||
|
|
@ -429,7 +415,7 @@ impl<'a, O: Options> serde::Serializer for &'a mut SizeChecker<O> {
|
|||
_variant: &'static str,
|
||||
value: &V,
|
||||
) -> Result<()> {
|
||||
self.add_value(variant_index)?;
|
||||
self.add_discriminant(variant_index)?;
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
|
|
|
|||
132
tests/test.rs
132
tests/test.rs
|
|
@ -14,43 +14,53 @@ use std::result::Result as StdResult;
|
|||
|
||||
use bincode::{
|
||||
deserialize, deserialize_from, deserialize_in_place, serialize, serialized_size,
|
||||
DefaultOptions, ErrorKind, OptionsExt, Result,
|
||||
DefaultOptions, ErrorKind, Options, Result,
|
||||
};
|
||||
use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
|
||||
|
||||
fn the_same<V>(element: V)
|
||||
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 = serialized_size(&element).unwrap();
|
||||
let size = options.serialized_size(&element).unwrap();
|
||||
|
||||
{
|
||||
let encoded = serialize(&element).unwrap();
|
||||
let decoded = deserialize(&encoded[..]).unwrap();
|
||||
|
||||
assert_eq!(element, decoded);
|
||||
assert_eq!(size, encoded.len() as u64);
|
||||
}
|
||||
|
||||
{
|
||||
let encoded = DefaultOptions::new()
|
||||
.with_big_endian()
|
||||
.serialize(&element)
|
||||
.unwrap();
|
||||
let decoded = DefaultOptions::new()
|
||||
.with_big_endian()
|
||||
.deserialize(&encoded[..])
|
||||
.unwrap();
|
||||
let decoded_reader = DefaultOptions::new()
|
||||
.with_big_endian()
|
||||
.deserialize_from(&mut &encoded[..])
|
||||
.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
|
||||
|
|
@ -109,7 +119,7 @@ fn test_tuple() {
|
|||
|
||||
#[test]
|
||||
fn test_basic_struct() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||
struct Easy {
|
||||
x: isize,
|
||||
s: String,
|
||||
|
|
@ -124,13 +134,13 @@ fn test_basic_struct() {
|
|||
|
||||
#[test]
|
||||
fn test_nested_struct() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||
struct Easy {
|
||||
x: isize,
|
||||
s: String,
|
||||
y: usize,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||
struct Nest {
|
||||
f: Easy,
|
||||
b: usize,
|
||||
|
|
@ -154,7 +164,7 @@ fn test_nested_struct() {
|
|||
|
||||
#[test]
|
||||
fn test_struct_newtype() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||
struct NewtypeStr(usize);
|
||||
|
||||
the_same(NewtypeStr(5));
|
||||
|
|
@ -162,7 +172,7 @@ fn test_struct_newtype() {
|
|||
|
||||
#[test]
|
||||
fn test_struct_tuple() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||
struct TubStr(usize, String, f32);
|
||||
|
||||
the_same(TubStr(5, "hello".to_string(), 3.2));
|
||||
|
|
@ -177,7 +187,7 @@ fn test_option() {
|
|||
|
||||
#[test]
|
||||
fn test_enum() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
||||
enum TestEnum {
|
||||
NoArg,
|
||||
OneArg(usize),
|
||||
|
|
@ -239,7 +249,10 @@ fn deserializing_errors() {
|
|||
ErrorKind::InvalidBoolEncoding(0xA) => {}
|
||||
_ => panic!(),
|
||||
}
|
||||
match *deserialize::<String>(&vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF][..]).unwrap_err() {
|
||||
|
||||
let invalid_str = vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF];
|
||||
|
||||
match *deserialize::<String>(&invalid_str[..]).unwrap_err() {
|
||||
ErrorKind::InvalidUtf8Encoding(_) => {}
|
||||
_ => panic!(),
|
||||
}
|
||||
|
|
@ -251,7 +264,9 @@ fn deserializing_errors() {
|
|||
Two,
|
||||
};
|
||||
|
||||
match *deserialize::<Test>(&vec![0, 0, 0, 5][..]).unwrap_err() {
|
||||
let invalid_enum = vec![0, 0, 0, 5];
|
||||
|
||||
match *deserialize::<Test>(&invalid_enum[..]).unwrap_err() {
|
||||
// Error message comes from serde
|
||||
ErrorKind::Custom(_) => {}
|
||||
_ => panic!(),
|
||||
|
|
@ -309,11 +324,11 @@ fn too_big_serialize() {
|
|||
assert!(DefaultOptions::new().with_limit(4).serialize(&0u32).is_ok());
|
||||
|
||||
assert!(DefaultOptions::new()
|
||||
.with_limit(8 + 4)
|
||||
.with_limit(LEN_SIZE + 4)
|
||||
.serialize(&"abcde")
|
||||
.is_err());
|
||||
assert!(DefaultOptions::new()
|
||||
.with_limit(8 + 5)
|
||||
.with_limit(LEN_SIZE + 5)
|
||||
.serialize(&"abcde")
|
||||
.is_ok());
|
||||
}
|
||||
|
|
@ -326,10 +341,10 @@ fn test_serialized_size() {
|
|||
assert!(serialized_size(&0u64).unwrap() == 8);
|
||||
|
||||
// length isize stored as u64
|
||||
assert!(serialized_size(&"").unwrap() == 8);
|
||||
assert!(serialized_size(&"a").unwrap() == 8 + 1);
|
||||
assert!(serialized_size(&"").unwrap() == LEN_SIZE);
|
||||
assert!(serialized_size(&"a").unwrap() == LEN_SIZE + 1);
|
||||
|
||||
assert!(serialized_size(&vec![0u32, 1u32, 2u32]).unwrap() == 8 + 3 * (4));
|
||||
assert!(serialized_size(&vec![0u32, 1u32, 2u32]).unwrap() == LEN_SIZE + 3 * (4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -368,21 +383,21 @@ fn test_serialized_size_bounded() {
|
|||
.with_limit(8)
|
||||
.serialized_size(&"")
|
||||
.unwrap()
|
||||
== 8
|
||||
== LEN_SIZE
|
||||
);
|
||||
assert!(
|
||||
DefaultOptions::new()
|
||||
.with_limit(8 + 1)
|
||||
.serialized_size(&"a")
|
||||
.unwrap()
|
||||
== 8 + 1
|
||||
== LEN_SIZE + 1
|
||||
);
|
||||
assert!(
|
||||
DefaultOptions::new()
|
||||
.with_limit(8 + 3 * 4)
|
||||
.with_limit(LEN_SIZE + 3 * 4)
|
||||
.serialized_size(&vec![0u32, 1u32, 2u32])
|
||||
.unwrap()
|
||||
== 8 + 3 * 4
|
||||
== LEN_SIZE + 3 * 4
|
||||
);
|
||||
// Below
|
||||
assert!(DefaultOptions::new()
|
||||
|
|
@ -794,3 +809,40 @@ fn test_big_endian_deserialize_from_seed() {
|
|||
|
||||
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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue