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::*;
|
pub(crate) use self::internal::*;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub trait Config: InternalConfig + Sized {}
|
pub trait Config: InternalConfig + Copy + Clone + Sized {
|
||||||
|
fn with_big_endian(self) -> BigEndian<Self> {
|
||||||
pub struct Default;
|
BigEndian { _pd: PhantomData }
|
||||||
|
}
|
||||||
impl InternalConfig for Default {}
|
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 {}
|
impl<T: InternalConfig> Config for T {}
|
||||||
|
|
||||||
mod internal {
|
#[derive(Copy, Clone)]
|
||||||
pub trait InternalConfig {
|
pub struct Default;
|
||||||
|
|
||||||
|
impl InternalConfig for Default {
|
||||||
const ENDIAN: Endian = Endian::Little;
|
const ENDIAN: Endian = Endian::Little;
|
||||||
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
|
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
|
||||||
const LIMIT: Option<u64> = None;
|
const LIMIT: Option<u64> = None;
|
||||||
const ALLOW_TRAILING: bool = true;
|
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: Copy + Clone {
|
||||||
|
const ENDIAN: Endian;
|
||||||
|
const INT_ENCODING: IntEncoding;
|
||||||
|
const LIMIT: Option<u64>;
|
||||||
|
const ALLOW_TRAILING: bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
|
|
@ -28,7 +96,10 @@ mod internal {
|
||||||
Variable,
|
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 ENDIAN: Endian = C::ENDIAN;
|
||||||
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
|
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
|
||||||
const LIMIT: Option<u64> = C::LIMIT;
|
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> {
|
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 {
|
Decoder {
|
||||||
reader,
|
reader,
|
||||||
config: PhantomData,
|
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
|
impl<'a, T> Decode for &'a mut T
|
||||||
where
|
where
|
||||||
T: Decode,
|
T: Decode,
|
||||||
|
|
|
||||||
20
src/lib.rs
20
src/lib.rs
|
|
@ -21,21 +21,37 @@ pub mod enc;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
pub use bincode_derive::{Decodable, Encodable};
|
pub use bincode_derive::{Decodable, Encodable};
|
||||||
|
use config::Config;
|
||||||
|
|
||||||
pub(crate) mod varint;
|
pub(crate) mod varint;
|
||||||
|
|
||||||
pub fn encode_into_slice<E: enc::Encodeable>(
|
pub fn encode_into_slice<E: enc::Encodeable>(
|
||||||
val: E,
|
val: E,
|
||||||
dst: &mut [u8],
|
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> {
|
) -> Result<usize, error::EncodeError> {
|
||||||
let writer = enc::write::SliceWriter::new(dst);
|
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)?;
|
val.encode(&mut encoder)?;
|
||||||
Ok(encoder.into_writer().bytes_written())
|
Ok(encoder.into_writer().bytes_written())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode<D: de::Decodable>(src: &mut [u8]) -> Result<D, error::DecodeError> {
|
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 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)
|
D::decode(&mut decoder)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,19 @@ pub fn varint_decode_i16<'a, R: Reader<'a>>(
|
||||||
read: &mut R,
|
read: &mut R,
|
||||||
endian: Endian,
|
endian: Endian,
|
||||||
) -> Result<i16, DecodeError> {
|
) -> 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)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -15,7 +27,19 @@ pub fn varint_decode_i32<'a, R: Reader<'a>>(
|
||||||
read: &mut R,
|
read: &mut R,
|
||||||
endian: Endian,
|
endian: Endian,
|
||||||
) -> Result<i32, DecodeError> {
|
) -> 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)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -23,7 +47,19 @@ pub fn varint_decode_i64<'a, R: Reader<'a>>(
|
||||||
read: &mut R,
|
read: &mut R,
|
||||||
endian: Endian,
|
endian: Endian,
|
||||||
) -> Result<i64, DecodeError> {
|
) -> 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)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -31,7 +67,19 @@ pub fn varint_decode_i128<'a, R: Reader<'a>>(
|
||||||
read: &mut R,
|
read: &mut R,
|
||||||
endian: Endian,
|
endian: Endian,
|
||||||
) -> Result<i128, DecodeError> {
|
) -> 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)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -39,5 +87,5 @@ pub fn varint_decode_isize<'a, R: Reader<'a>>(
|
||||||
read: &mut R,
|
read: &mut R,
|
||||||
endian: Endian,
|
endian: Endian,
|
||||||
) -> Result<isize, DecodeError> {
|
) -> Result<isize, DecodeError> {
|
||||||
unimplemented!()
|
varint_decode_i64(read, endian).map(|v| v as isize)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,63 @@
|
||||||
extern crate bincode;
|
extern crate bincode;
|
||||||
|
|
||||||
|
use bincode::config::{self, Config};
|
||||||
use core::fmt::Debug;
|
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)
|
fn the_same<V>(element: V)
|
||||||
where
|
where
|
||||||
V: bincode::enc::Encodeable + bincode::de::Decodable + PartialEq + Debug + Clone + 'static,
|
V: bincode::enc::Encodeable + bincode::de::Decodable + PartialEq + Debug + Clone + 'static,
|
||||||
{
|
{
|
||||||
let mut buffer = [0u8; 32];
|
the_same_with_config(
|
||||||
bincode::encode_into_slice(element.clone(), &mut buffer).unwrap();
|
element.clone(),
|
||||||
let decoded: V = bincode::decode(&mut buffer).unwrap();
|
config::Default
|
||||||
|
.with_little_endian()
|
||||||
assert_eq!(element, decoded);
|
.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]
|
#[test]
|
||||||
fn test_numbers() {
|
fn test_numbers() {
|
||||||
|
the_same(5u8);
|
||||||
|
the_same(5u16);
|
||||||
the_same(5u32);
|
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