Turned Config::INT_ENCODING back into a const, made a ton of varint_encode functions
This commit is contained in:
parent
7448b7bb87
commit
723bdd312a
10
docs/spec.md
10
docs/spec.md
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
Related issue: https://github.com/serde-rs/serde/issues/1756#issuecomment-689682123
|
||||
|
||||
## Endian
|
||||
|
||||
By default `bincode` will serialize values in little endian encoding. This can be overwritten in the `Config`.
|
||||
|
||||
## Basic types
|
||||
|
||||
Boolean types are encoded with 1 byte for each boolean type, with `0` being `false`, `1` being true. Whilst deserilizing every other value will throw an error.
|
||||
|
|
@ -23,10 +27,10 @@ assert_eq!(encoded.as_slice(), &[
|
|||
```
|
||||
|
||||
## IntEncoding
|
||||
Bincode currently supports 2 different types of `IntEncoding`:
|
||||
Bincode currently supports 2 different types of `IntEncoding`. With the default config, `VarintEncoding` is selected.
|
||||
|
||||
### VarintEncoding
|
||||
Encoding an unsigned integer v (of any type excepting u8) works as follows:
|
||||
Encoding an unsigned integer v (of any type excepting u8/i8) works as follows:
|
||||
|
||||
1. If `u < 251`, encode it as a single byte with that value.
|
||||
1. If `251 <= u < 2**16`, encode it as a literal byte 251, followed by a u16 with value `u`.
|
||||
|
|
@ -34,6 +38,8 @@ Encoding an unsigned integer v (of any type excepting u8) works as follows:
|
|||
1. If `2**32 <= u < 2**64`, encode it as a literal byte 253, followed by a u64 with value `u`.
|
||||
1. If `2**64 <= u < 2**128`, encode it as a literal byte 254, followed by a u128 with value `u`.
|
||||
|
||||
`usize` is being encoded/decoded as a `u64` and `isize` is being encoded/decoded as a `i64`.
|
||||
|
||||
See the documentation of [VarintEncoding](https://docs.rs/bincode/latest/bincode/config/struct.VarintEncoding.html) for more information.
|
||||
|
||||
### FixintEncoding
|
||||
|
|
|
|||
|
|
@ -1,26 +1,19 @@
|
|||
use crate::int_encoding::FixintEncoding;
|
||||
|
||||
pub(crate) use self::internal::*;
|
||||
|
||||
pub trait Config: InternalConfig + Sized {}
|
||||
|
||||
pub struct Default;
|
||||
|
||||
impl InternalConfig for Default {
|
||||
type IntEncoding = FixintEncoding;
|
||||
}
|
||||
impl InternalConfig for Default {}
|
||||
|
||||
impl<T: InternalConfig> Config for T {}
|
||||
|
||||
mod internal {
|
||||
use crate::int_encoding::IntEncoding;
|
||||
|
||||
pub trait InternalConfig {
|
||||
const ENDIAN: Endian = Endian::Little;
|
||||
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
|
||||
const LIMIT: Option<u64> = None;
|
||||
const ALLOW_TRAILING: bool = true;
|
||||
|
||||
type IntEncoding: IntEncoding;
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
|
|
@ -29,11 +22,16 @@ mod internal {
|
|||
Big,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum IntEncoding {
|
||||
Fixed,
|
||||
Variable,
|
||||
}
|
||||
|
||||
impl<'a, C: InternalConfig> InternalConfig for &'a mut 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;
|
||||
|
||||
type IntEncoding = C::IntEncoding;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
use super::write::Writer;
|
||||
use super::Encode;
|
||||
use crate::{config::Config, error::Error, int_encoding::IntEncoding};
|
||||
use crate::{
|
||||
config::{Config, Endian, IntEncoding},
|
||||
error::Error,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
pub struct Encoder<W: Writer, C: Config> {
|
||||
|
|
@ -27,23 +30,63 @@ impl<'a, W: Writer, C: Config> Encode for &'a mut Encoder<W, C> {
|
|||
}
|
||||
|
||||
fn encode_u16(&mut self, val: u16) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_u16(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_u16(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_u32(&mut self, val: u32) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_u32(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_u32(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_u64(&mut self, val: u64) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_u64(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_u64(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_u128(&mut self, val: u128) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_u128(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_u128(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_usize(&mut self, val: usize) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_usize(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_usize(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_i8(&mut self, val: i8) -> Result<(), Error> {
|
||||
|
|
@ -51,31 +94,83 @@ impl<'a, W: Writer, C: Config> Encode for &'a mut Encoder<W, C> {
|
|||
}
|
||||
|
||||
fn encode_i16(&mut self, val: i16) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_i16(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_i16(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_i32(&mut self, val: i32) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_i32(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_i32(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_i64(&mut self, val: i64) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_i64(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_i64(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_i128(&mut self, val: i128) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_i128(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_i128(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_isize(&mut self, val: isize) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_isize(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => {
|
||||
crate::varint_encoding::varint_encode_isize(&mut self.writer, C::ENDIAN, val)
|
||||
}
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_f32(&mut self, val: f32) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_f32(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => unimplemented!(), // crate::int_encoding::varint_encode_f32(&mut self.writer, C::ENDIAN, val),
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_f64(&mut self, val: f64) -> Result<(), Error> {
|
||||
<C::IntEncoding as IntEncoding>::int_encode_f64(&mut self.writer, C::ENDIAN, val)
|
||||
match C::INT_ENCODING {
|
||||
IntEncoding::Variable => unimplemented!(), // crate::int_encoding::varint_encode_f64(&mut self.writer, C::ENDIAN, val),
|
||||
IntEncoding::Fixed => match C::ENDIAN {
|
||||
Endian::Big => self.writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => self.writer.write(&val.to_le_bytes()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_slice(&mut self, val: &[u8]) -> Result<(), Error> {
|
||||
|
|
|
|||
|
|
@ -1,120 +0,0 @@
|
|||
use crate::{config::Endian, enc::write::Writer, error::Error};
|
||||
|
||||
pub trait IntEncoding {
|
||||
fn int_encode_u16<W: Writer>(writer: &mut W, endian: Endian, val: u16) -> Result<(), Error>;
|
||||
fn int_encode_u32<W: Writer>(writer: &mut W, endian: Endian, val: u32) -> Result<(), Error>;
|
||||
fn int_encode_u64<W: Writer>(writer: &mut W, endian: Endian, val: u64) -> Result<(), Error>;
|
||||
fn int_encode_u128<W: Writer>(writer: &mut W, endian: Endian, val: u128) -> Result<(), Error>;
|
||||
fn int_encode_usize<W: Writer>(writer: &mut W, endian: Endian, val: usize)
|
||||
-> Result<(), Error>;
|
||||
|
||||
fn int_encode_i16<W: Writer>(writer: &mut W, endian: Endian, val: i16) -> Result<(), Error>;
|
||||
fn int_encode_i32<W: Writer>(writer: &mut W, endian: Endian, val: i32) -> Result<(), Error>;
|
||||
fn int_encode_i64<W: Writer>(writer: &mut W, endian: Endian, val: i64) -> Result<(), Error>;
|
||||
fn int_encode_i128<W: Writer>(writer: &mut W, endian: Endian, val: i128) -> Result<(), Error>;
|
||||
fn int_encode_isize<W: Writer>(writer: &mut W, endian: Endian, val: isize)
|
||||
-> Result<(), Error>;
|
||||
|
||||
fn int_encode_f32<W: Writer>(writer: &mut W, endian: Endian, val: f32) -> Result<(), Error>;
|
||||
fn int_encode_f64<W: Writer>(writer: &mut W, endian: Endian, val: f64) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct VarintEncoding;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct FixintEncoding;
|
||||
|
||||
impl IntEncoding for FixintEncoding {
|
||||
fn int_encode_u16<W: Writer>(writer: &mut W, endian: Endian, val: u16) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_u32<W: Writer>(writer: &mut W, endian: Endian, val: u32) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_u64<W: Writer>(writer: &mut W, endian: Endian, val: u64) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_u128<W: Writer>(writer: &mut W, endian: Endian, val: u128) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_usize<W: Writer>(
|
||||
writer: &mut W,
|
||||
endian: Endian,
|
||||
val: usize,
|
||||
) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_i16<W: Writer>(writer: &mut W, endian: Endian, val: i16) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_i32<W: Writer>(writer: &mut W, endian: Endian, val: i32) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_i64<W: Writer>(writer: &mut W, endian: Endian, val: i64) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_i128<W: Writer>(writer: &mut W, endian: Endian, val: i128) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_isize<W: Writer>(
|
||||
writer: &mut W,
|
||||
endian: Endian,
|
||||
val: isize,
|
||||
) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_f32<W: Writer>(writer: &mut W, endian: Endian, val: f32) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
fn int_encode_f64<W: Writer>(writer: &mut W, endian: Endian, val: f64) -> Result<(), Error> {
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ pub mod error;
|
|||
|
||||
pub use bincode_derive::{Decodable, Encodable};
|
||||
|
||||
pub(crate) mod int_encoding;
|
||||
pub(crate) mod varint_encoding;
|
||||
|
||||
pub fn encode_into_slice<E: enc::Encodeable>(
|
||||
val: E,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
mod signed;
|
||||
mod unsigned;
|
||||
|
||||
pub use self::signed::{
|
||||
varint_encode_i128, varint_encode_i16, varint_encode_i32, varint_encode_i64,
|
||||
varint_encode_isize,
|
||||
};
|
||||
pub use self::unsigned::{
|
||||
varint_encode_u128, varint_encode_u16, varint_encode_u32, varint_encode_u64,
|
||||
varint_encode_usize,
|
||||
};
|
||||
|
||||
pub(self) const SINGLE_BYTE_MAX: u8 = 250;
|
||||
pub(self) const U16_BYTE: u8 = 251;
|
||||
pub(self) const U32_BYTE: u8 = 252;
|
||||
pub(self) const U64_BYTE: u8 = 253;
|
||||
pub(self) const U128_BYTE: u8 = 254;
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
use super::{varint_encode_u128, varint_encode_u16, varint_encode_u32, varint_encode_u64};
|
||||
use crate::{config::Endian, enc::write::Writer, error::Error};
|
||||
|
||||
pub fn varint_encode_i16<W: Writer>(writer: &mut W, endian: Endian, val: i16) -> Result<(), Error> {
|
||||
varint_encode_u16(
|
||||
writer,
|
||||
endian,
|
||||
if val < 0 {
|
||||
// let's avoid the edge case of i16::min_value()
|
||||
// !n is equal to `-n - 1`, so this is:
|
||||
// !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
|
||||
!(val as u16) * 2 + 1
|
||||
} else {
|
||||
(val as u16) * 2
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn varint_encode_i32<W: Writer>(writer: &mut W, endian: Endian, val: i32) -> Result<(), Error> {
|
||||
varint_encode_u32(
|
||||
writer,
|
||||
endian,
|
||||
if val < 0 {
|
||||
// let's avoid the edge case of i32::min_value()
|
||||
// !n is equal to `-n - 1`, so this is:
|
||||
// !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
|
||||
!(val as u32) * 2 + 1
|
||||
} else {
|
||||
(val as u32) * 2
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn varint_encode_i64<W: Writer>(writer: &mut W, endian: Endian, val: i64) -> Result<(), Error> {
|
||||
varint_encode_u64(
|
||||
writer,
|
||||
endian,
|
||||
if val < 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
|
||||
!(val as u64) * 2 + 1
|
||||
} else {
|
||||
(val as u64) * 2
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn varint_encode_i128<W: Writer>(
|
||||
writer: &mut W,
|
||||
endian: Endian,
|
||||
val: i128,
|
||||
) -> Result<(), Error> {
|
||||
varint_encode_u128(
|
||||
writer,
|
||||
endian,
|
||||
if val < 0 {
|
||||
// let's avoid the edge case of i128::min_value()
|
||||
// !n is equal to `-n - 1`, so this is:
|
||||
// !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
|
||||
!(val as u128) * 2 + 1
|
||||
} else {
|
||||
(val as u128) * 2
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn varint_encode_isize<W: Writer>(
|
||||
writer: &mut W,
|
||||
endian: Endian,
|
||||
val: isize,
|
||||
) -> Result<(), Error> {
|
||||
// isize is being encoded as a i64
|
||||
varint_encode_i64(writer, endian, val as i64)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_i16() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_i32() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_i64() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_i128() {
|
||||
// TODO
|
||||
}
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
use super::{SINGLE_BYTE_MAX, U128_BYTE, U16_BYTE, U32_BYTE, U64_BYTE};
|
||||
use crate::{config::Endian, enc::write::Writer, error::Error};
|
||||
|
||||
pub fn varint_encode_u16<W: Writer>(writer: &mut W, endian: Endian, val: u16) -> Result<(), Error> {
|
||||
if val <= SINGLE_BYTE_MAX as _ {
|
||||
writer.write(&[val as u8])
|
||||
} else {
|
||||
writer.write(&[U16_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn varint_encode_u32<W: Writer>(writer: &mut W, endian: Endian, val: u32) -> Result<(), Error> {
|
||||
if val <= SINGLE_BYTE_MAX as _ {
|
||||
writer.write(&[val as u8])
|
||||
} else if val <= u16::MAX as _ {
|
||||
writer.write(&[U16_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&(val as u16).to_be_bytes()),
|
||||
Endian::Little => writer.write(&(val as u16).to_le_bytes()),
|
||||
}
|
||||
} else {
|
||||
writer.write(&[U32_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn varint_encode_u64<W: Writer>(writer: &mut W, endian: Endian, val: u64) -> Result<(), Error> {
|
||||
if val <= SINGLE_BYTE_MAX as _ {
|
||||
writer.write(&[val as u8])
|
||||
} else if val <= u16::MAX as _ {
|
||||
writer.write(&[U16_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&(val as u16).to_be_bytes()),
|
||||
Endian::Little => writer.write(&(val as u16).to_le_bytes()),
|
||||
}
|
||||
} else if val <= u32::MAX as _ {
|
||||
writer.write(&[U32_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&(val as u32).to_be_bytes()),
|
||||
Endian::Little => writer.write(&(val as u32).to_le_bytes()),
|
||||
}
|
||||
} else {
|
||||
writer.write(&[U64_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn varint_encode_u128<W: Writer>(
|
||||
writer: &mut W,
|
||||
endian: Endian,
|
||||
val: u128,
|
||||
) -> Result<(), Error> {
|
||||
if val <= SINGLE_BYTE_MAX as _ {
|
||||
writer.write(&[val as u8])
|
||||
} else if val <= u16::MAX as _ {
|
||||
writer.write(&[U16_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&(val as u16).to_be_bytes()),
|
||||
Endian::Little => writer.write(&(val as u16).to_le_bytes()),
|
||||
}
|
||||
} else if val <= u32::MAX as _ {
|
||||
writer.write(&[U32_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&(val as u32).to_be_bytes()),
|
||||
Endian::Little => writer.write(&(val as u32).to_le_bytes()),
|
||||
}
|
||||
} else if val <= u64::MAX as _ {
|
||||
writer.write(&[U64_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&(val as u64).to_be_bytes()),
|
||||
Endian::Little => writer.write(&(val as u64).to_le_bytes()),
|
||||
}
|
||||
} else {
|
||||
writer.write(&[U128_BYTE])?;
|
||||
match endian {
|
||||
Endian::Big => writer.write(&val.to_be_bytes()),
|
||||
Endian::Little => writer.write(&val.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn varint_encode_usize<W: Writer>(
|
||||
writer: &mut W,
|
||||
endian: Endian,
|
||||
val: usize,
|
||||
) -> Result<(), Error> {
|
||||
// usize is being encoded as a u64
|
||||
varint_encode_u64(writer, endian, val as u64)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_u16() {
|
||||
use crate::enc::write::SliceWriter;
|
||||
let mut buffer = [0u8; 20];
|
||||
|
||||
// these should all encode to a single byte
|
||||
for i in 0u16..=SINGLE_BYTE_MAX as u16 {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u16(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 1);
|
||||
assert_eq!(buffer[0] as u16, i);
|
||||
|
||||
// Assert endianness doesn't matter
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u16(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 1);
|
||||
assert_eq!(buffer[0] as u16, i);
|
||||
}
|
||||
|
||||
// these values should encode in 3 bytes (leading byte + 2 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [
|
||||
SINGLE_BYTE_MAX as u16 + 1,
|
||||
300,
|
||||
500,
|
||||
700,
|
||||
888,
|
||||
1234,
|
||||
u16::MAX,
|
||||
] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u16(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 3);
|
||||
assert_eq!(buffer[0], U16_BYTE);
|
||||
assert_eq!(&buffer[1..3], &i.to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u16(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 3);
|
||||
assert_eq!(buffer[0], U16_BYTE);
|
||||
assert_eq!(&buffer[1..3], &i.to_le_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_u32() {
|
||||
use crate::enc::write::SliceWriter;
|
||||
let mut buffer = [0u8; 20];
|
||||
|
||||
// these should all encode to a single byte
|
||||
for i in 0u32..=SINGLE_BYTE_MAX as u32 {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u32(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 1);
|
||||
assert_eq!(buffer[0] as u32, i);
|
||||
|
||||
// Assert endianness doesn't matter
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u32(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 1);
|
||||
assert_eq!(buffer[0] as u32, i);
|
||||
}
|
||||
|
||||
// these values should encode in 3 bytes (leading byte + 2 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [
|
||||
SINGLE_BYTE_MAX as u32 + 1,
|
||||
300,
|
||||
500,
|
||||
700,
|
||||
888,
|
||||
1234,
|
||||
u16::MAX as u32,
|
||||
] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u32(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 3);
|
||||
assert_eq!(buffer[0], U16_BYTE);
|
||||
assert_eq!(&buffer[1..3], &(i as u16).to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u32(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 3);
|
||||
assert_eq!(buffer[0], U16_BYTE);
|
||||
assert_eq!(&buffer[1..3], &(i as u16).to_le_bytes());
|
||||
}
|
||||
|
||||
// these values should encode in 5 bytes (leading byte + 4 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [u16::MAX as u32 + 1, 100_000, 1_000_000, u32::MAX] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u32(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 5);
|
||||
assert_eq!(buffer[0], U32_BYTE);
|
||||
assert_eq!(&buffer[1..5], &i.to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u32(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 5);
|
||||
assert_eq!(buffer[0], U32_BYTE);
|
||||
assert_eq!(&buffer[1..5], &i.to_le_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_u64() {
|
||||
use crate::enc::write::SliceWriter;
|
||||
let mut buffer = [0u8; 20];
|
||||
|
||||
// these should all encode to a single byte
|
||||
for i in 0u64..=SINGLE_BYTE_MAX as u64 {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u64(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 1);
|
||||
assert_eq!(buffer[0] as u64, i);
|
||||
|
||||
// Assert endianness doesn't matter
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u64(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 1);
|
||||
assert_eq!(buffer[0] as u64, i);
|
||||
}
|
||||
|
||||
// these values should encode in 3 bytes (leading byte + 2 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [
|
||||
SINGLE_BYTE_MAX as u64 + 1,
|
||||
300,
|
||||
500,
|
||||
700,
|
||||
888,
|
||||
1234,
|
||||
u16::MAX as u64,
|
||||
] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u64(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 3);
|
||||
assert_eq!(buffer[0], U16_BYTE);
|
||||
assert_eq!(&buffer[1..3], &(i as u16).to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u64(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 3);
|
||||
assert_eq!(buffer[0], U16_BYTE);
|
||||
assert_eq!(&buffer[1..3], &(i as u16).to_le_bytes());
|
||||
}
|
||||
|
||||
// these values should encode in 5 bytes (leading byte + 4 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [u16::MAX as u64 + 1, 100_000, 1_000_000, u32::MAX as u64] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u64(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 5);
|
||||
assert_eq!(buffer[0], U32_BYTE);
|
||||
assert_eq!(&buffer[1..5], &(i as u32).to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u64(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 5);
|
||||
assert_eq!(buffer[0], U32_BYTE);
|
||||
assert_eq!(&buffer[1..5], &(i as u32).to_le_bytes());
|
||||
}
|
||||
|
||||
// these values should encode in 9 bytes (leading byte + 8 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [u32::MAX as u64 + 1, 500_0000_000, u64::MAX] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u64(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 9);
|
||||
assert_eq!(buffer[0], U64_BYTE);
|
||||
assert_eq!(&buffer[1..9], &i.to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u64(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 9);
|
||||
assert_eq!(buffer[0], U64_BYTE);
|
||||
assert_eq!(&buffer[1..9], &i.to_le_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_u128() {
|
||||
use crate::enc::write::SliceWriter;
|
||||
let mut buffer = [0u8; 20];
|
||||
|
||||
// these should all encode to a single byte
|
||||
for i in 0u128..=SINGLE_BYTE_MAX as u128 {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 1);
|
||||
assert_eq!(buffer[0] as u128, i);
|
||||
|
||||
// Assert endianness doesn't matter
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 1);
|
||||
assert_eq!(buffer[0] as u128, i);
|
||||
}
|
||||
|
||||
// these values should encode in 3 bytes (leading byte + 2 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [
|
||||
SINGLE_BYTE_MAX as u128 + 1,
|
||||
300,
|
||||
500,
|
||||
700,
|
||||
888,
|
||||
1234,
|
||||
u16::MAX as u128,
|
||||
] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 3);
|
||||
assert_eq!(buffer[0], U16_BYTE);
|
||||
assert_eq!(&buffer[1..3], &(i as u16).to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 3);
|
||||
assert_eq!(buffer[0], U16_BYTE);
|
||||
assert_eq!(&buffer[1..3], &(i as u16).to_le_bytes());
|
||||
}
|
||||
|
||||
// these values should encode in 5 bytes (leading byte + 4 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [u16::MAX as u128 + 1, 100_000, 1_000_000, u32::MAX as u128] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 5);
|
||||
assert_eq!(buffer[0], U32_BYTE);
|
||||
assert_eq!(&buffer[1..5], &(i as u32).to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 5);
|
||||
assert_eq!(buffer[0], U32_BYTE);
|
||||
assert_eq!(&buffer[1..5], &(i as u32).to_le_bytes());
|
||||
}
|
||||
|
||||
// these values should encode in 9 bytes (leading byte + 8 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [u32::MAX as u128 + 1, 500_0000_000, u64::MAX as u128] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 9);
|
||||
assert_eq!(buffer[0], U64_BYTE);
|
||||
assert_eq!(&buffer[1..9], &(i as u64).to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 9);
|
||||
assert_eq!(buffer[0], U64_BYTE);
|
||||
assert_eq!(&buffer[1..9], &(i as u64).to_le_bytes());
|
||||
}
|
||||
|
||||
// these values should encode in 17 bytes (leading byte + 16 bytes)
|
||||
// Values chosen at random, add new cases as needed
|
||||
for i in [u64::MAX as u128 + 1, u128::MAX] {
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Big, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 17);
|
||||
assert_eq!(buffer[0], U128_BYTE);
|
||||
assert_eq!(&buffer[1..17], &i.to_be_bytes());
|
||||
|
||||
let mut writer = SliceWriter::new(&mut buffer);
|
||||
varint_encode_u128(&mut writer, Endian::Little, i).unwrap();
|
||||
assert_eq!(writer.bytes_written(), 17);
|
||||
assert_eq!(buffer[0], U128_BYTE);
|
||||
assert_eq!(&buffer[1..17], &i.to_le_bytes());
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,6 @@ fn test_encodable() {
|
|||
};
|
||||
let mut slice = [0u8; 1024];
|
||||
let bytes_written = bincode::encode_into_slice(start, &mut slice).unwrap();
|
||||
assert_eq!(bytes_written, 9);
|
||||
assert_eq!(&slice[..bytes_written], &[5, 0, 0, 0, 10, 0, 0, 0, 20]);
|
||||
assert_eq!(bytes_written, 3);
|
||||
assert_eq!(&slice[..bytes_written], &[10, 10, 20]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue