mirror of https://git.sr.ht/~stygianentity/bincode
Added config options for endian and int_encoding, added full coverage for all basic integer types
This commit is contained in:
parent
78cb27f782
commit
ffb565c405
|
|
@ -1,19 +1,87 @@
|
|||
pub(crate) use self::internal::*;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub trait Config: InternalConfig + Sized {}
|
||||
|
||||
pub struct Default;
|
||||
|
||||
impl InternalConfig for Default {}
|
||||
pub trait Config: InternalConfig + Copy + Clone + Sized {
|
||||
fn with_big_endian(self) -> BigEndian<Self> {
|
||||
BigEndian { _pd: PhantomData }
|
||||
}
|
||||
fn with_little_endian(self) -> LittleEndian<Self> {
|
||||
LittleEndian { _pd: PhantomData }
|
||||
}
|
||||
fn with_variable_int_encoding(self) -> Varint<Self> {
|
||||
Varint { _pd: PhantomData }
|
||||
}
|
||||
fn with_fixed_int_encoding(self) -> Fixint<Self> {
|
||||
Fixint { _pd: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InternalConfig> Config for T {}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Default;
|
||||
|
||||
impl InternalConfig for Default {
|
||||
const ENDIAN: Endian = Endian::Little;
|
||||
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
|
||||
const LIMIT: Option<u64> = None;
|
||||
const ALLOW_TRAILING: bool = true;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct BigEndian<C: Config> {
|
||||
_pd: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: InternalConfig> InternalConfig for BigEndian<C> {
|
||||
const ENDIAN: Endian = Endian::Big;
|
||||
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
|
||||
const LIMIT: Option<u64> = C::LIMIT;
|
||||
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct LittleEndian<C: Config> {
|
||||
_pd: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: InternalConfig> InternalConfig for LittleEndian<C> {
|
||||
const ENDIAN: Endian = Endian::Little;
|
||||
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
|
||||
const LIMIT: Option<u64> = C::LIMIT;
|
||||
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Fixint<C: Config> {
|
||||
_pd: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: InternalConfig> InternalConfig for Fixint<C> {
|
||||
const ENDIAN: Endian = C::ENDIAN;
|
||||
const INT_ENCODING: IntEncoding = IntEncoding::Fixed;
|
||||
const LIMIT: Option<u64> = C::LIMIT;
|
||||
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Varint<C: Config> {
|
||||
_pd: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: InternalConfig> InternalConfig for Varint<C> {
|
||||
const ENDIAN: Endian = C::ENDIAN;
|
||||
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
|
||||
const LIMIT: Option<u64> = C::LIMIT;
|
||||
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
|
||||
}
|
||||
|
||||
mod internal {
|
||||
pub trait InternalConfig {
|
||||
const ENDIAN: Endian = Endian::Little;
|
||||
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
|
||||
const LIMIT: Option<u64> = None;
|
||||
const ALLOW_TRAILING: bool = true;
|
||||
pub trait InternalConfig: Copy + Clone {
|
||||
const ENDIAN: Endian;
|
||||
const INT_ENCODING: IntEncoding;
|
||||
const LIMIT: Option<u64>;
|
||||
const ALLOW_TRAILING: bool;
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
|
|
@ -28,7 +96,10 @@ mod internal {
|
|||
Variable,
|
||||
}
|
||||
|
||||
impl<'a, C: InternalConfig> InternalConfig for &'a mut C {
|
||||
impl<'a, C: InternalConfig> InternalConfig for &'a mut C
|
||||
where
|
||||
&'a mut C: Copy + Clone,
|
||||
{
|
||||
const ENDIAN: Endian = C::ENDIAN;
|
||||
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
|
||||
const LIMIT: Option<u64> = C::LIMIT;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ pub struct Decoder<R, C: Config> {
|
|||
}
|
||||
|
||||
impl<'de, R: Reader<'de>, C: Config> Decoder<R, C> {
|
||||
pub fn new(reader: R) -> Decoder<R, C> {
|
||||
pub fn new(reader: R, _config: C) -> Decoder<R, C> {
|
||||
Decoder {
|
||||
reader,
|
||||
config: PhantomData,
|
||||
|
|
|
|||
|
|
@ -73,6 +73,24 @@ impl Decodable for isize {
|
|||
}
|
||||
}
|
||||
|
||||
impl Decodable for f32 {
|
||||
fn decode<D: Decode>(mut decoder: D) -> Result<Self, DecodeError> {
|
||||
decoder.decode_f32()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for f64 {
|
||||
fn decode<D: Decode>(mut decoder: D) -> Result<Self, DecodeError> {
|
||||
decoder.decode_f64()
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Decodable for [u8; N] {
|
||||
fn decode<D: Decode>(mut decoder: D) -> Result<Self, DecodeError> {
|
||||
decoder.decode_array()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Decode for &'a mut T
|
||||
where
|
||||
T: Decode,
|
||||
|
|
|
|||
20
src/lib.rs
20
src/lib.rs
|
|
@ -21,21 +21,37 @@ pub mod enc;
|
|||
pub mod error;
|
||||
|
||||
pub use bincode_derive::{Decodable, Encodable};
|
||||
use config::Config;
|
||||
|
||||
pub(crate) mod varint;
|
||||
|
||||
pub fn encode_into_slice<E: enc::Encodeable>(
|
||||
val: E,
|
||||
dst: &mut [u8],
|
||||
) -> Result<usize, error::EncodeError> {
|
||||
encode_into_slice_with_config(val, dst, config::Default)
|
||||
}
|
||||
|
||||
pub fn encode_into_slice_with_config<E: enc::Encodeable, C: Config>(
|
||||
val: E,
|
||||
dst: &mut [u8],
|
||||
_config: C,
|
||||
) -> Result<usize, error::EncodeError> {
|
||||
let writer = enc::write::SliceWriter::new(dst);
|
||||
let mut encoder = enc::Encoder::<_, config::Default>::new(writer);
|
||||
let mut encoder = enc::Encoder::<_, C>::new(writer);
|
||||
val.encode(&mut encoder)?;
|
||||
Ok(encoder.into_writer().bytes_written())
|
||||
}
|
||||
|
||||
pub fn decode<D: de::Decodable>(src: &mut [u8]) -> Result<D, error::DecodeError> {
|
||||
decode_with_config(src, config::Default)
|
||||
}
|
||||
|
||||
pub fn decode_with_config<D: de::Decodable, C: Config>(
|
||||
src: &mut [u8],
|
||||
_config: C,
|
||||
) -> Result<D, error::DecodeError> {
|
||||
let reader = de::read::SliceReader::new(src);
|
||||
let mut decoder = de::Decoder::<_, config::Default>::new(reader);
|
||||
let mut decoder = de::Decoder::<_, C>::new(reader, _config);
|
||||
D::decode(&mut decoder)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,19 @@ pub fn varint_decode_i16<'a, R: Reader<'a>>(
|
|||
read: &mut R,
|
||||
endian: Endian,
|
||||
) -> Result<i16, DecodeError> {
|
||||
unimplemented!()
|
||||
let n = super::varint_decode_u16(read, endian)?;
|
||||
Ok(if n % 2 == 0 {
|
||||
// positive number
|
||||
(n / 2) as _
|
||||
} 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 _
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -15,7 +27,19 @@ pub fn varint_decode_i32<'a, R: Reader<'a>>(
|
|||
read: &mut R,
|
||||
endian: Endian,
|
||||
) -> Result<i32, DecodeError> {
|
||||
unimplemented!()
|
||||
let n = super::varint_decode_u32(read, endian)?;
|
||||
Ok(if n % 2 == 0 {
|
||||
// positive number
|
||||
(n / 2) as _
|
||||
} 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 _
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -23,7 +47,19 @@ pub fn varint_decode_i64<'a, R: Reader<'a>>(
|
|||
read: &mut R,
|
||||
endian: Endian,
|
||||
) -> Result<i64, DecodeError> {
|
||||
unimplemented!()
|
||||
let n = super::varint_decode_u64(read, endian)?;
|
||||
Ok(if n % 2 == 0 {
|
||||
// positive number
|
||||
(n / 2) as _
|
||||
} 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 _
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -31,7 +67,19 @@ pub fn varint_decode_i128<'a, R: Reader<'a>>(
|
|||
read: &mut R,
|
||||
endian: Endian,
|
||||
) -> Result<i128, DecodeError> {
|
||||
unimplemented!()
|
||||
let n = super::varint_decode_u128(read, endian)?;
|
||||
Ok(if n % 2 == 0 {
|
||||
// positive number
|
||||
(n / 2) as _
|
||||
} 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 _
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -39,5 +87,5 @@ pub fn varint_decode_isize<'a, R: Reader<'a>>(
|
|||
read: &mut R,
|
||||
endian: Endian,
|
||||
) -> Result<isize, DecodeError> {
|
||||
unimplemented!()
|
||||
varint_decode_i64(read, endian).map(|v| v as isize)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,63 @@
|
|||
extern crate bincode;
|
||||
|
||||
use bincode::config::{self, Config};
|
||||
use core::fmt::Debug;
|
||||
|
||||
fn the_same_with_config<V, C>(element: V, config: C)
|
||||
where
|
||||
V: bincode::enc::Encodeable + bincode::de::Decodable + PartialEq + Debug + Clone + 'static,
|
||||
C: Config,
|
||||
{
|
||||
let mut buffer = [0u8; 32];
|
||||
bincode::encode_into_slice_with_config(element.clone(), &mut buffer, config).unwrap();
|
||||
let decoded: V = bincode::decode_with_config(&mut buffer, config).unwrap();
|
||||
|
||||
assert_eq!(element, decoded);
|
||||
}
|
||||
fn the_same<V>(element: V)
|
||||
where
|
||||
V: bincode::enc::Encodeable + bincode::de::Decodable + PartialEq + Debug + Clone + 'static,
|
||||
{
|
||||
let mut buffer = [0u8; 32];
|
||||
bincode::encode_into_slice(element.clone(), &mut buffer).unwrap();
|
||||
let decoded: V = bincode::decode(&mut buffer).unwrap();
|
||||
|
||||
assert_eq!(element, decoded);
|
||||
the_same_with_config(
|
||||
element.clone(),
|
||||
config::Default
|
||||
.with_little_endian()
|
||||
.with_fixed_int_encoding(),
|
||||
);
|
||||
the_same_with_config(
|
||||
element.clone(),
|
||||
config::Default.with_big_endian().with_fixed_int_encoding(),
|
||||
);
|
||||
the_same_with_config(
|
||||
element.clone(),
|
||||
config::Default
|
||||
.with_little_endian()
|
||||
.with_variable_int_encoding(),
|
||||
);
|
||||
the_same_with_config(
|
||||
element,
|
||||
config::Default
|
||||
.with_big_endian()
|
||||
.with_variable_int_encoding(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_numbers() {
|
||||
the_same(5u8);
|
||||
the_same(5u16);
|
||||
the_same(5u32);
|
||||
the_same(5u64);
|
||||
the_same(5u128);
|
||||
the_same(5usize);
|
||||
|
||||
the_same(5i8);
|
||||
the_same(5i16);
|
||||
the_same(5i32);
|
||||
the_same(5i64);
|
||||
the_same(5i128);
|
||||
the_same(5isize);
|
||||
|
||||
the_same(5.0f32);
|
||||
the_same(5.0f64);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue