Added an option to encode a fixed array length or to skip it

This commit is contained in:
Victor Koenders 2021-10-14 21:31:47 +02:00
parent 19fed15463
commit 960b6066cd
5 changed files with 415 additions and 287 deletions

View File

@ -12,7 +12,10 @@
//! .with_little_endian()
//! // pick one of:
//! .with_variable_int_encoding()
//! .with_fixed_int_encoding();
//! .with_fixed_int_encoding()
//! // pick one of:
//! .skip_fixed_array_length()
//! .write_fixed_array_length();
//! ```
//!
//! See [Config] for more information on the configuration options.
@ -26,12 +29,15 @@ use core::marker::PhantomData;
///
/// - [with_little_endian] and [with_big_endian]
/// - [with_fixed_int_encoding] and [with_variable_int_encoding]
/// - [skip_fixed_array_length] and [write_fixed_array_length]
///
///
/// [with_little_endian]: #method.with_little_endian
/// [with_big_endian]: #method.with_big_endian
/// [with_fixed_int_encoding]: #method.with_fixed_int_encoding
/// [with_variable_int_encoding]: #method.with_variable_int_encoding
/// [skip_fixed_array_length]: #method.skip_fixed_array_length
/// [write_fixed_array_length]: #method.write_fixed_array_length
pub trait Config: InternalConfig {
/// Makes bincode encode all integer types in big endian.
fn with_big_endian(self) -> BigEndian<Self> {
@ -97,6 +103,16 @@ pub trait Config: InternalConfig {
fn with_fixed_int_encoding(self) -> Fixint<Self> {
Fixint { _pd: PhantomData }
}
/// Skip writing the length of fixed size arrays (`[u8; N]`) before writing the array
fn skip_fixed_array_length(self) -> SkipFixedArrayLength<Self> {
SkipFixedArrayLength { _pd: PhantomData }
}
/// Write the length of fixed size arrays (`[u8; N]`) before writing the array
fn write_fixed_array_length(self) -> WriteFixedArrayLength<Self> {
WriteFixedArrayLength { _pd: PhantomData }
}
}
impl<T: InternalConfig> Config for T {}
@ -104,6 +120,7 @@ impl<T: InternalConfig> Config for T {}
/// The default config. By default this will be:
/// - Little endian
/// - Variable int encoding
/// - Skip fixed array length
#[derive(Copy, Clone)]
pub struct Default;
@ -112,6 +129,7 @@ impl InternalConfig for Default {
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
const LIMIT: Option<u64> = None;
const ALLOW_TRAILING: bool = true;
const SKIP_FIXED_ARRAY_LENGTH: bool = true;
}
#[doc(hidden)]
@ -125,6 +143,7 @@ impl<C: InternalConfig> InternalConfig for BigEndian<C> {
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
const LIMIT: Option<u64> = C::LIMIT;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = C::SKIP_FIXED_ARRAY_LENGTH;
}
#[doc(hidden)]
@ -138,6 +157,7 @@ impl<C: InternalConfig> InternalConfig for LittleEndian<C> {
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
const LIMIT: Option<u64> = C::LIMIT;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = C::SKIP_FIXED_ARRAY_LENGTH;
}
#[doc(hidden)]
@ -151,6 +171,7 @@ impl<C: InternalConfig> InternalConfig for Fixint<C> {
const INT_ENCODING: IntEncoding = IntEncoding::Fixed;
const LIMIT: Option<u64> = C::LIMIT;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = C::SKIP_FIXED_ARRAY_LENGTH;
}
#[doc(hidden)]
@ -164,6 +185,35 @@ impl<C: InternalConfig> InternalConfig for Varint<C> {
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
const LIMIT: Option<u64> = C::LIMIT;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = C::SKIP_FIXED_ARRAY_LENGTH;
}
#[doc(hidden)]
#[derive(Copy, Clone)]
pub struct SkipFixedArrayLength<C: Config> {
_pd: PhantomData<C>,
}
impl<C: InternalConfig> InternalConfig for SkipFixedArrayLength<C> {
const ENDIAN: Endian = C::ENDIAN;
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
const LIMIT: Option<u64> = C::LIMIT;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = true;
}
#[doc(hidden)]
#[derive(Copy, Clone)]
pub struct WriteFixedArrayLength<C: Config> {
_pd: PhantomData<C>,
}
impl<C: InternalConfig> InternalConfig for WriteFixedArrayLength<C> {
const ENDIAN: Endian = C::ENDIAN;
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
const LIMIT: Option<u64> = C::LIMIT;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = false;
}
mod internal {
@ -172,6 +222,7 @@ mod internal {
const INT_ENCODING: IntEncoding;
const LIMIT: Option<u64>;
const ALLOW_TRAILING: bool;
const SKIP_FIXED_ARRAY_LENGTH: bool;
}
#[derive(PartialEq, Eq)]
@ -194,5 +245,6 @@ mod internal {
const INT_ENCODING: IntEncoding = C::INT_ENCODING;
const LIMIT: Option<u64> = C::LIMIT;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = C::SKIP_FIXED_ARRAY_LENGTH;
}
}

View File

@ -1,281 +1,290 @@
use super::{
read::{BorrowReader, Reader},
BorrowDecode, Decode,
};
use crate::{
config::{Config, Endian, IntEncoding},
error::DecodeError,
};
use core::marker::PhantomData;
/// A Decoder that reads bytes from a given reader `R`.
///
/// This struct should rarely be used.
/// In most cases, prefer any of the `decode` functions.
///
/// The ByteOrder that is chosen will impact the endianness that
/// is used to read integers out of the reader.
///
/// ```
/// # let slice: &[u8] = &[0, 0, 0, 0];
/// # let some_reader = bincode::de::read::SliceReader::new(slice);
/// use bincode::de::{Decoder, Decodable};
/// use bincode::config;
/// let mut decoder = Decoder::new(some_reader, config::Default);
/// // this u32 can be any Decodable
/// let value = u32::decode(&mut decoder).unwrap();
/// ```
pub struct Decoder<R, C: Config> {
reader: R,
config: PhantomData<C>,
}
impl<'de, R: Reader<'de>, C: Config> Decoder<R, C> {
/// Construct a new Decoder
pub fn new(reader: R, _config: C) -> Decoder<R, C> {
Decoder {
reader,
config: PhantomData,
}
}
/// Consume the decoder and return the inner reader
pub fn into_reader(self) -> R {
self.reader
}
}
impl<'a, 'de, R: BorrowReader<'de>, C: Config> BorrowDecode<'de> for &'a mut Decoder<R, C> {
fn decode_slice(&mut self, len: usize) -> Result<&'de [u8], DecodeError> {
self.reader.take_bytes(len)
}
}
impl<'a, 'de, R: Reader<'de>, C: Config> Decode for &'a mut Decoder<R, C> {
fn decode_u8(&mut self) -> Result<u8, DecodeError> {
let mut bytes = [0u8; 1];
self.reader.read(&mut bytes)?;
Ok(bytes[0])
}
fn decode_u16(&mut self) -> Result<u16, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u16(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 2];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u16::from_le_bytes(bytes),
Endian::Big => u16::from_be_bytes(bytes),
})
}
}
}
fn decode_u32(&mut self) -> Result<u32, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u32(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 4];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u32::from_le_bytes(bytes),
Endian::Big => u32::from_be_bytes(bytes),
})
}
}
}
fn decode_u64(&mut self) -> Result<u64, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u64(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u64::from_le_bytes(bytes),
Endian::Big => u64::from_be_bytes(bytes),
})
}
}
}
fn decode_u128(&mut self) -> Result<u128, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u128(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 16];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u128::from_le_bytes(bytes),
Endian::Big => u128::from_be_bytes(bytes),
})
}
}
}
fn decode_usize(&mut self) -> Result<usize, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => {
crate::varint::varint_decode_usize(&mut self.reader, C::ENDIAN)
}
IntEncoding::Fixed => {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u64::from_le_bytes(bytes),
Endian::Big => u64::from_be_bytes(bytes),
} as usize)
}
}
}
fn decode_i8(&mut self) -> Result<i8, DecodeError> {
let mut bytes = [0u8; 1];
self.reader.read(&mut bytes)?;
Ok(bytes[0] as i8)
}
fn decode_i16(&mut self) -> Result<i16, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i16(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 2];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i16::from_le_bytes(bytes),
Endian::Big => i16::from_be_bytes(bytes),
})
}
}
}
fn decode_i32(&mut self) -> Result<i32, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i32(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 4];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i32::from_le_bytes(bytes),
Endian::Big => i32::from_be_bytes(bytes),
})
}
}
}
fn decode_i64(&mut self) -> Result<i64, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i64(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i64::from_le_bytes(bytes),
Endian::Big => i64::from_be_bytes(bytes),
})
}
}
}
fn decode_i128(&mut self) -> Result<i128, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i128(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 16];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i128::from_le_bytes(bytes),
Endian::Big => i128::from_be_bytes(bytes),
})
}
}
}
fn decode_isize(&mut self) -> Result<isize, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => {
crate::varint::varint_decode_isize(&mut self.reader, C::ENDIAN)
}
IntEncoding::Fixed => {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i64::from_le_bytes(bytes),
Endian::Big => i64::from_be_bytes(bytes),
} as isize)
}
}
}
fn decode_f32(&mut self) -> Result<f32, DecodeError> {
let mut bytes = [0u8; 4];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => f32::from_le_bytes(bytes),
Endian::Big => f32::from_be_bytes(bytes),
})
}
fn decode_f64(&mut self) -> Result<f64, DecodeError> {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => f64::from_le_bytes(bytes),
Endian::Big => f64::from_be_bytes(bytes),
})
}
fn decode_array<const N: usize>(&mut self) -> Result<[u8; N], DecodeError> {
let mut array = [0u8; N];
self.reader.read(&mut array)?;
Ok(array)
}
fn decode_char(&mut self) -> Result<char, DecodeError> {
let mut array = [0u8; 4];
// Look at the first byte to see how many bytes must be read
self.reader.read(&mut array[..1])?;
let width = utf8_char_width(array[0]);
if width == 0 {
return Err(DecodeError::InvalidCharEncoding(array));
}
if width == 1 {
return Ok(array[0] as char);
}
// read the remaining pain
self.reader.read(&mut array[1..width])?;
let res = core::str::from_utf8(&array[..width])
.ok()
.and_then(|s| s.chars().next())
.ok_or(DecodeError::InvalidCharEncoding(array))?;
Ok(res)
}
}
const 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
const fn utf8_char_width(b: u8) -> usize {
UTF8_CHAR_WIDTH[b as usize] as usize
}
use super::{
read::{BorrowReader, Reader},
BorrowDecode, Decode,
};
use crate::{
config::{Config, Endian, IntEncoding},
error::DecodeError,
};
use core::marker::PhantomData;
/// A Decoder that reads bytes from a given reader `R`.
///
/// This struct should rarely be used.
/// In most cases, prefer any of the `decode` functions.
///
/// The ByteOrder that is chosen will impact the endianness that
/// is used to read integers out of the reader.
///
/// ```
/// # let slice: &[u8] = &[0, 0, 0, 0];
/// # let some_reader = bincode::de::read::SliceReader::new(slice);
/// use bincode::de::{Decoder, Decodable};
/// use bincode::config;
/// let mut decoder = Decoder::new(some_reader, config::Default);
/// // this u32 can be any Decodable
/// let value = u32::decode(&mut decoder).unwrap();
/// ```
pub struct Decoder<R, C: Config> {
reader: R,
config: PhantomData<C>,
}
impl<'de, R: Reader<'de>, C: Config> Decoder<R, C> {
/// Construct a new Decoder
pub fn new(reader: R, _config: C) -> Decoder<R, C> {
Decoder {
reader,
config: PhantomData,
}
}
/// Consume the decoder and return the inner reader
pub fn into_reader(self) -> R {
self.reader
}
}
impl<'a, 'de, R: BorrowReader<'de>, C: Config> BorrowDecode<'de> for &'a mut Decoder<R, C> {
fn decode_slice(&mut self, len: usize) -> Result<&'de [u8], DecodeError> {
self.reader.take_bytes(len)
}
}
impl<'a, 'de, R: Reader<'de>, C: Config> Decode for &'a mut Decoder<R, C> {
fn decode_u8(&mut self) -> Result<u8, DecodeError> {
let mut bytes = [0u8; 1];
self.reader.read(&mut bytes)?;
Ok(bytes[0])
}
fn decode_u16(&mut self) -> Result<u16, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u16(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 2];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u16::from_le_bytes(bytes),
Endian::Big => u16::from_be_bytes(bytes),
})
}
}
}
fn decode_u32(&mut self) -> Result<u32, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u32(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 4];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u32::from_le_bytes(bytes),
Endian::Big => u32::from_be_bytes(bytes),
})
}
}
}
fn decode_u64(&mut self) -> Result<u64, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u64(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u64::from_le_bytes(bytes),
Endian::Big => u64::from_be_bytes(bytes),
})
}
}
}
fn decode_u128(&mut self) -> Result<u128, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u128(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 16];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u128::from_le_bytes(bytes),
Endian::Big => u128::from_be_bytes(bytes),
})
}
}
}
fn decode_usize(&mut self) -> Result<usize, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => {
crate::varint::varint_decode_usize(&mut self.reader, C::ENDIAN)
}
IntEncoding::Fixed => {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => u64::from_le_bytes(bytes),
Endian::Big => u64::from_be_bytes(bytes),
} as usize)
}
}
}
fn decode_i8(&mut self) -> Result<i8, DecodeError> {
let mut bytes = [0u8; 1];
self.reader.read(&mut bytes)?;
Ok(bytes[0] as i8)
}
fn decode_i16(&mut self) -> Result<i16, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i16(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 2];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i16::from_le_bytes(bytes),
Endian::Big => i16::from_be_bytes(bytes),
})
}
}
}
fn decode_i32(&mut self) -> Result<i32, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i32(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 4];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i32::from_le_bytes(bytes),
Endian::Big => i32::from_be_bytes(bytes),
})
}
}
}
fn decode_i64(&mut self) -> Result<i64, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i64(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i64::from_le_bytes(bytes),
Endian::Big => i64::from_be_bytes(bytes),
})
}
}
}
fn decode_i128(&mut self) -> Result<i128, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i128(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => {
let mut bytes = [0u8; 16];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i128::from_le_bytes(bytes),
Endian::Big => i128::from_be_bytes(bytes),
})
}
}
}
fn decode_isize(&mut self) -> Result<isize, DecodeError> {
match C::INT_ENCODING {
IntEncoding::Variable => {
crate::varint::varint_decode_isize(&mut self.reader, C::ENDIAN)
}
IntEncoding::Fixed => {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => i64::from_le_bytes(bytes),
Endian::Big => i64::from_be_bytes(bytes),
} as isize)
}
}
}
fn decode_f32(&mut self) -> Result<f32, DecodeError> {
let mut bytes = [0u8; 4];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => f32::from_le_bytes(bytes),
Endian::Big => f32::from_be_bytes(bytes),
})
}
fn decode_f64(&mut self) -> Result<f64, DecodeError> {
let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN {
Endian::Little => f64::from_le_bytes(bytes),
Endian::Big => f64::from_be_bytes(bytes),
})
}
fn decode_array<const N: usize>(&mut self) -> Result<[u8; N], DecodeError> {
let mut array = [0u8; N];
if !C::SKIP_FIXED_ARRAY_LENGTH {
let length = self.decode_usize()?;
if length != N {
return Err(DecodeError::ArrayLengthMismatch {
found: length,
required: N,
});
}
}
self.reader.read(&mut array)?;
Ok(array)
}
fn decode_char(&mut self) -> Result<char, DecodeError> {
let mut array = [0u8; 4];
// Look at the first byte to see how many bytes must be read
self.reader.read(&mut array[..1])?;
let width = utf8_char_width(array[0]);
if width == 0 {
return Err(DecodeError::InvalidCharEncoding(array));
}
if width == 1 {
return Ok(array[0] as char);
}
// read the remaining pain
self.reader.read(&mut array[1..width])?;
let res = core::str::from_utf8(&array[..width])
.ok()
.and_then(|s| s.chars().next())
.ok_or(DecodeError::InvalidCharEncoding(array))?;
Ok(res)
}
}
const 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
const fn utf8_char_width(b: u8) -> usize {
UTF8_CHAR_WIDTH[b as usize] as usize
}

View File

@ -195,6 +195,9 @@ impl<'a, W: Writer, C: Config> Encode for &'a mut Encoder<W, C> {
}
fn encode_array<const N: usize>(&mut self, val: [u8; N]) -> Result<(), EncodeError> {
if !C::SKIP_FIXED_ARRAY_LENGTH {
self.encode_usize(N)?;
}
self.writer.write(&val)
}

View File

@ -52,6 +52,14 @@ pub enum DecodeError {
/// The decoder tried to decode a `bool` and failed. The given value is what is actually read.
InvalidBooleanValue(u8),
/// The decoder tried to decode an array of length `required`, but the binary data contained an array of length `found`.
ArrayLengthMismatch {
/// The length of the array required by the rust type.
required: usize,
/// The length of the array found in the binary format.
found: usize,
},
}
/// Integer types. Used by [DecodeError]. These types have no purpose other than being shown in errors.

View File

@ -11,7 +11,7 @@ where
+ 'static,
C: Config,
{
let mut buffer = [0u8; 32];
let mut buffer = [0u8; 1024];
let len = bincode::encode_into_slice_with_config(element.clone(), &mut buffer, config).unwrap();
println!(
"{:?}: {:?} ({:?})",
@ -32,27 +32,62 @@ where
+ Clone
+ 'static,
{
// A matrix of each different config option possible
the_same_with_config(
element.clone(),
config::Default
.with_little_endian()
.with_fixed_int_encoding(),
.with_fixed_int_encoding()
.skip_fixed_array_length(),
);
the_same_with_config(
element.clone(),
config::Default.with_big_endian().with_fixed_int_encoding(),
config::Default
.with_big_endian()
.with_fixed_int_encoding()
.skip_fixed_array_length(),
);
the_same_with_config(
element.clone(),
config::Default
.with_little_endian()
.with_variable_int_encoding(),
.with_variable_int_encoding()
.skip_fixed_array_length(),
);
the_same_with_config(
element.clone(),
config::Default
.with_big_endian()
.with_variable_int_encoding()
.skip_fixed_array_length(),
);
the_same_with_config(
element.clone(),
config::Default
.with_little_endian()
.with_fixed_int_encoding()
.write_fixed_array_length(),
);
the_same_with_config(
element.clone(),
config::Default
.with_big_endian()
.with_fixed_int_encoding()
.write_fixed_array_length(),
);
the_same_with_config(
element.clone(),
config::Default
.with_little_endian()
.with_variable_int_encoding()
.write_fixed_array_length(),
);
the_same_with_config(
element,
config::Default
.with_big_endian()
.with_variable_int_encoding(),
.with_variable_int_encoding()
.write_fixed_array_length(),
);
}
@ -95,6 +130,27 @@ fn test_numbers() {
the_same((1u8, 2u8, 3u8, 4u8, 5u8, 6u8));
the_same((1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8));
the_same((1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8));
// arrays
#[rustfmt::skip]
the_same([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
]);
}
#[test]