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() //! .with_little_endian()
//! // pick one of: //! // pick one of:
//! .with_variable_int_encoding() //! .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. //! 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_little_endian] and [with_big_endian]
/// - [with_fixed_int_encoding] and [with_variable_int_encoding] /// - [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_little_endian]: #method.with_little_endian
/// [with_big_endian]: #method.with_big_endian /// [with_big_endian]: #method.with_big_endian
/// [with_fixed_int_encoding]: #method.with_fixed_int_encoding /// [with_fixed_int_encoding]: #method.with_fixed_int_encoding
/// [with_variable_int_encoding]: #method.with_variable_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 { pub trait Config: InternalConfig {
/// Makes bincode encode all integer types in big endian. /// Makes bincode encode all integer types in big endian.
fn with_big_endian(self) -> BigEndian<Self> { fn with_big_endian(self) -> BigEndian<Self> {
@ -97,6 +103,16 @@ pub trait Config: InternalConfig {
fn with_fixed_int_encoding(self) -> Fixint<Self> { fn with_fixed_int_encoding(self) -> Fixint<Self> {
Fixint { _pd: PhantomData } 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 {} impl<T: InternalConfig> Config for T {}
@ -104,6 +120,7 @@ impl<T: InternalConfig> Config for T {}
/// The default config. By default this will be: /// The default config. By default this will be:
/// - Little endian /// - Little endian
/// - Variable int encoding /// - Variable int encoding
/// - Skip fixed array length
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Default; pub struct Default;
@ -112,6 +129,7 @@ impl InternalConfig for Default {
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;
const SKIP_FIXED_ARRAY_LENGTH: bool = true;
} }
#[doc(hidden)] #[doc(hidden)]
@ -125,6 +143,7 @@ impl<C: InternalConfig> InternalConfig for BigEndian<C> {
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;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING; const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = C::SKIP_FIXED_ARRAY_LENGTH;
} }
#[doc(hidden)] #[doc(hidden)]
@ -138,6 +157,7 @@ impl<C: InternalConfig> InternalConfig for LittleEndian<C> {
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;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING; const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = C::SKIP_FIXED_ARRAY_LENGTH;
} }
#[doc(hidden)] #[doc(hidden)]
@ -151,6 +171,7 @@ impl<C: InternalConfig> InternalConfig for Fixint<C> {
const INT_ENCODING: IntEncoding = IntEncoding::Fixed; const INT_ENCODING: IntEncoding = IntEncoding::Fixed;
const LIMIT: Option<u64> = C::LIMIT; const LIMIT: Option<u64> = C::LIMIT;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING; const ALLOW_TRAILING: bool = C::ALLOW_TRAILING;
const SKIP_FIXED_ARRAY_LENGTH: bool = C::SKIP_FIXED_ARRAY_LENGTH;
} }
#[doc(hidden)] #[doc(hidden)]
@ -164,6 +185,35 @@ impl<C: InternalConfig> InternalConfig for Varint<C> {
const INT_ENCODING: IntEncoding = IntEncoding::Variable; const INT_ENCODING: IntEncoding = IntEncoding::Variable;
const LIMIT: Option<u64> = C::LIMIT; const LIMIT: Option<u64> = C::LIMIT;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING; 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 { mod internal {
@ -172,6 +222,7 @@ mod internal {
const INT_ENCODING: IntEncoding; const INT_ENCODING: IntEncoding;
const LIMIT: Option<u64>; const LIMIT: Option<u64>;
const ALLOW_TRAILING: bool; const ALLOW_TRAILING: bool;
const SKIP_FIXED_ARRAY_LENGTH: bool;
} }
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
@ -194,5 +245,6 @@ mod internal {
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;
const ALLOW_TRAILING: bool = C::ALLOW_TRAILING; 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::{ use super::{
read::{BorrowReader, Reader}, read::{BorrowReader, Reader},
BorrowDecode, Decode, BorrowDecode, Decode,
}; };
use crate::{ use crate::{
config::{Config, Endian, IntEncoding}, config::{Config, Endian, IntEncoding},
error::DecodeError, error::DecodeError,
}; };
use core::marker::PhantomData; use core::marker::PhantomData;
/// A Decoder that reads bytes from a given reader `R`. /// A Decoder that reads bytes from a given reader `R`.
/// ///
/// This struct should rarely be used. /// This struct should rarely be used.
/// In most cases, prefer any of the `decode` functions. /// In most cases, prefer any of the `decode` functions.
/// ///
/// The ByteOrder that is chosen will impact the endianness that /// The ByteOrder that is chosen will impact the endianness that
/// is used to read integers out of the reader. /// is used to read integers out of the reader.
/// ///
/// ``` /// ```
/// # let slice: &[u8] = &[0, 0, 0, 0]; /// # let slice: &[u8] = &[0, 0, 0, 0];
/// # let some_reader = bincode::de::read::SliceReader::new(slice); /// # let some_reader = bincode::de::read::SliceReader::new(slice);
/// use bincode::de::{Decoder, Decodable}; /// use bincode::de::{Decoder, Decodable};
/// use bincode::config; /// use bincode::config;
/// let mut decoder = Decoder::new(some_reader, config::Default); /// let mut decoder = Decoder::new(some_reader, config::Default);
/// // this u32 can be any Decodable /// // this u32 can be any Decodable
/// let value = u32::decode(&mut decoder).unwrap(); /// let value = u32::decode(&mut decoder).unwrap();
/// ``` /// ```
pub struct Decoder<R, C: Config> { pub struct Decoder<R, C: Config> {
reader: R, reader: R,
config: PhantomData<C>, config: PhantomData<C>,
} }
impl<'de, R: Reader<'de>, C: Config> Decoder<R, C> { impl<'de, R: Reader<'de>, C: Config> Decoder<R, C> {
/// Construct a new Decoder /// Construct a new Decoder
pub fn new(reader: R, _config: C) -> Decoder<R, C> { pub fn new(reader: R, _config: C) -> Decoder<R, C> {
Decoder { Decoder {
reader, reader,
config: PhantomData, config: PhantomData,
} }
} }
/// Consume the decoder and return the inner reader /// Consume the decoder and return the inner reader
pub fn into_reader(self) -> R { pub fn into_reader(self) -> R {
self.reader self.reader
} }
} }
impl<'a, 'de, R: BorrowReader<'de>, C: Config> BorrowDecode<'de> for &'a mut Decoder<R, C> { 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> { fn decode_slice(&mut self, len: usize) -> Result<&'de [u8], DecodeError> {
self.reader.take_bytes(len) self.reader.take_bytes(len)
} }
} }
impl<'a, 'de, R: Reader<'de>, C: Config> Decode for &'a mut Decoder<R, C> { impl<'a, 'de, R: Reader<'de>, C: Config> Decode for &'a mut Decoder<R, C> {
fn decode_u8(&mut self) -> Result<u8, DecodeError> { fn decode_u8(&mut self) -> Result<u8, DecodeError> {
let mut bytes = [0u8; 1]; let mut bytes = [0u8; 1];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(bytes[0]) Ok(bytes[0])
} }
fn decode_u16(&mut self) -> Result<u16, DecodeError> { fn decode_u16(&mut self) -> Result<u16, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u16(&mut self.reader, C::ENDIAN), IntEncoding::Variable => crate::varint::varint_decode_u16(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 2]; let mut bytes = [0u8; 2];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => u16::from_le_bytes(bytes), Endian::Little => u16::from_le_bytes(bytes),
Endian::Big => u16::from_be_bytes(bytes), Endian::Big => u16::from_be_bytes(bytes),
}) })
} }
} }
} }
fn decode_u32(&mut self) -> Result<u32, DecodeError> { fn decode_u32(&mut self) -> Result<u32, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u32(&mut self.reader, C::ENDIAN), IntEncoding::Variable => crate::varint::varint_decode_u32(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 4]; let mut bytes = [0u8; 4];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => u32::from_le_bytes(bytes), Endian::Little => u32::from_le_bytes(bytes),
Endian::Big => u32::from_be_bytes(bytes), Endian::Big => u32::from_be_bytes(bytes),
}) })
} }
} }
} }
fn decode_u64(&mut self) -> Result<u64, DecodeError> { fn decode_u64(&mut self) -> Result<u64, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u64(&mut self.reader, C::ENDIAN), IntEncoding::Variable => crate::varint::varint_decode_u64(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 8]; let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => u64::from_le_bytes(bytes), Endian::Little => u64::from_le_bytes(bytes),
Endian::Big => u64::from_be_bytes(bytes), Endian::Big => u64::from_be_bytes(bytes),
}) })
} }
} }
} }
fn decode_u128(&mut self) -> Result<u128, DecodeError> { fn decode_u128(&mut self) -> Result<u128, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_u128(&mut self.reader, C::ENDIAN), IntEncoding::Variable => crate::varint::varint_decode_u128(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 16]; let mut bytes = [0u8; 16];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => u128::from_le_bytes(bytes), Endian::Little => u128::from_le_bytes(bytes),
Endian::Big => u128::from_be_bytes(bytes), Endian::Big => u128::from_be_bytes(bytes),
}) })
} }
} }
} }
fn decode_usize(&mut self) -> Result<usize, DecodeError> { fn decode_usize(&mut self) -> Result<usize, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => { IntEncoding::Variable => {
crate::varint::varint_decode_usize(&mut self.reader, C::ENDIAN) crate::varint::varint_decode_usize(&mut self.reader, C::ENDIAN)
} }
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 8]; let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => u64::from_le_bytes(bytes), Endian::Little => u64::from_le_bytes(bytes),
Endian::Big => u64::from_be_bytes(bytes), Endian::Big => u64::from_be_bytes(bytes),
} as usize) } as usize)
} }
} }
} }
fn decode_i8(&mut self) -> Result<i8, DecodeError> { fn decode_i8(&mut self) -> Result<i8, DecodeError> {
let mut bytes = [0u8; 1]; let mut bytes = [0u8; 1];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(bytes[0] as i8) Ok(bytes[0] as i8)
} }
fn decode_i16(&mut self) -> Result<i16, DecodeError> { fn decode_i16(&mut self) -> Result<i16, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i16(&mut self.reader, C::ENDIAN), IntEncoding::Variable => crate::varint::varint_decode_i16(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 2]; let mut bytes = [0u8; 2];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => i16::from_le_bytes(bytes), Endian::Little => i16::from_le_bytes(bytes),
Endian::Big => i16::from_be_bytes(bytes), Endian::Big => i16::from_be_bytes(bytes),
}) })
} }
} }
} }
fn decode_i32(&mut self) -> Result<i32, DecodeError> { fn decode_i32(&mut self) -> Result<i32, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i32(&mut self.reader, C::ENDIAN), IntEncoding::Variable => crate::varint::varint_decode_i32(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 4]; let mut bytes = [0u8; 4];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => i32::from_le_bytes(bytes), Endian::Little => i32::from_le_bytes(bytes),
Endian::Big => i32::from_be_bytes(bytes), Endian::Big => i32::from_be_bytes(bytes),
}) })
} }
} }
} }
fn decode_i64(&mut self) -> Result<i64, DecodeError> { fn decode_i64(&mut self) -> Result<i64, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i64(&mut self.reader, C::ENDIAN), IntEncoding::Variable => crate::varint::varint_decode_i64(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 8]; let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => i64::from_le_bytes(bytes), Endian::Little => i64::from_le_bytes(bytes),
Endian::Big => i64::from_be_bytes(bytes), Endian::Big => i64::from_be_bytes(bytes),
}) })
} }
} }
} }
fn decode_i128(&mut self) -> Result<i128, DecodeError> { fn decode_i128(&mut self) -> Result<i128, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => crate::varint::varint_decode_i128(&mut self.reader, C::ENDIAN), IntEncoding::Variable => crate::varint::varint_decode_i128(&mut self.reader, C::ENDIAN),
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 16]; let mut bytes = [0u8; 16];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => i128::from_le_bytes(bytes), Endian::Little => i128::from_le_bytes(bytes),
Endian::Big => i128::from_be_bytes(bytes), Endian::Big => i128::from_be_bytes(bytes),
}) })
} }
} }
} }
fn decode_isize(&mut self) -> Result<isize, DecodeError> { fn decode_isize(&mut self) -> Result<isize, DecodeError> {
match C::INT_ENCODING { match C::INT_ENCODING {
IntEncoding::Variable => { IntEncoding::Variable => {
crate::varint::varint_decode_isize(&mut self.reader, C::ENDIAN) crate::varint::varint_decode_isize(&mut self.reader, C::ENDIAN)
} }
IntEncoding::Fixed => { IntEncoding::Fixed => {
let mut bytes = [0u8; 8]; let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => i64::from_le_bytes(bytes), Endian::Little => i64::from_le_bytes(bytes),
Endian::Big => i64::from_be_bytes(bytes), Endian::Big => i64::from_be_bytes(bytes),
} as isize) } as isize)
} }
} }
} }
fn decode_f32(&mut self) -> Result<f32, DecodeError> { fn decode_f32(&mut self) -> Result<f32, DecodeError> {
let mut bytes = [0u8; 4]; let mut bytes = [0u8; 4];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => f32::from_le_bytes(bytes), Endian::Little => f32::from_le_bytes(bytes),
Endian::Big => f32::from_be_bytes(bytes), Endian::Big => f32::from_be_bytes(bytes),
}) })
} }
fn decode_f64(&mut self) -> Result<f64, DecodeError> { fn decode_f64(&mut self) -> Result<f64, DecodeError> {
let mut bytes = [0u8; 8]; let mut bytes = [0u8; 8];
self.reader.read(&mut bytes)?; self.reader.read(&mut bytes)?;
Ok(match C::ENDIAN { Ok(match C::ENDIAN {
Endian::Little => f64::from_le_bytes(bytes), Endian::Little => f64::from_le_bytes(bytes),
Endian::Big => f64::from_be_bytes(bytes), Endian::Big => f64::from_be_bytes(bytes),
}) })
} }
fn decode_array<const N: usize>(&mut self) -> Result<[u8; N], DecodeError> { fn decode_array<const N: usize>(&mut self) -> Result<[u8; N], DecodeError> {
let mut array = [0u8; N]; let mut array = [0u8; N];
self.reader.read(&mut array)?; if !C::SKIP_FIXED_ARRAY_LENGTH {
Ok(array) let length = self.decode_usize()?;
} if length != N {
return Err(DecodeError::ArrayLengthMismatch {
fn decode_char(&mut self) -> Result<char, DecodeError> { found: length,
let mut array = [0u8; 4]; required: N,
});
// Look at the first byte to see how many bytes must be read }
self.reader.read(&mut array[..1])?; }
self.reader.read(&mut array)?;
let width = utf8_char_width(array[0]); Ok(array)
if width == 0 { }
return Err(DecodeError::InvalidCharEncoding(array));
} fn decode_char(&mut self) -> Result<char, DecodeError> {
if width == 1 { let mut array = [0u8; 4];
return Ok(array[0] as char);
} // Look at the first byte to see how many bytes must be read
self.reader.read(&mut array[..1])?;
// read the remaining pain
self.reader.read(&mut array[1..width])?; let width = utf8_char_width(array[0]);
let res = core::str::from_utf8(&array[..width]) if width == 0 {
.ok() return Err(DecodeError::InvalidCharEncoding(array));
.and_then(|s| s.chars().next()) }
.ok_or(DecodeError::InvalidCharEncoding(array))?; if width == 1 {
Ok(res) return Ok(array[0] as char);
} }
}
// read the remaining pain
const UTF8_CHAR_WIDTH: [u8; 256] = [ self.reader.read(&mut array[1..width])?;
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, let res = core::str::from_utf8(&array[..width])
1, // 0x1F .ok()
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, .and_then(|s| s.chars().next())
1, // 0x3F .ok_or(DecodeError::InvalidCharEncoding(array))?;
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, Ok(res)
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, const UTF8_CHAR_WIDTH: [u8; 256] = [
0, // 0x9F 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,
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, 1, // 0x1F
0, // 0xBF 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,
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, 1, // 0x3F
2, // 0xDF 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,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF 1, // 0x5F
4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF 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,
// This function is a copy of core::str::utf8_char_width 0, // 0x9F
const fn utf8_char_width(b: u8) -> usize { 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,
UTF8_CHAR_WIDTH[b as usize] as usize 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> { 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) 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. /// The decoder tried to decode a `bool` and failed. The given value is what is actually read.
InvalidBooleanValue(u8), 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. /// Integer types. Used by [DecodeError]. These types have no purpose other than being shown in errors.

View File

@ -11,7 +11,7 @@ where
+ 'static, + 'static,
C: Config, 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(); let len = bincode::encode_into_slice_with_config(element.clone(), &mut buffer, config).unwrap();
println!( println!(
"{:?}: {:?} ({:?})", "{:?}: {:?} ({:?})",
@ -32,27 +32,62 @@ where
+ Clone + Clone
+ 'static, + 'static,
{ {
// A matrix of each different config option possible
the_same_with_config( the_same_with_config(
element.clone(), element.clone(),
config::Default config::Default
.with_little_endian() .with_little_endian()
.with_fixed_int_encoding(), .with_fixed_int_encoding()
.skip_fixed_array_length(),
); );
the_same_with_config( the_same_with_config(
element.clone(), 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( the_same_with_config(
element.clone(), element.clone(),
config::Default config::Default
.with_little_endian() .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( the_same_with_config(
element, element,
config::Default config::Default
.with_big_endian() .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));
the_same((1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8)); the_same((1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8));
the_same((1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8)); 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] #[test]