add LEB128 types

This commit is contained in:
Jean-Marie Mineau 2023-08-22 15:46:14 +02:00
parent 1a9030267c
commit 33e770e04a
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
5 changed files with 430 additions and 17 deletions

View file

@ -0,0 +1,318 @@
//! The implementation of serializable for LEB128 types.
use std::io::Write;
use crate::{Error, ReadSeek, Result, Serializable};
/// Signed LEB128, variable-length
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Sleb128(i32);
/// Unsigned LEB128, variable-length
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Uleb128(u32);
/// Unsigned LEB128 plus 1, variable-length
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Uleb128p1(u32);
impl Sleb128 {
fn get_serialized_bytes(&self) -> Vec<u8> {
let Self(mut val) = self;
let mut bytes = vec![];
loop {
let byte = val as u8 & 0b0111_1111;
val /= 64;
if val == 0 || val == -1 {
bytes.push(byte);
return bytes;
} else {
val /= 2;
}
bytes.push(byte | 0b1000_0000);
}
}
}
impl Serializable for Sleb128 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output
.write_all(&self.get_serialized_bytes())
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialize Sleb128 to output: {err}"
))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut shift = 0;
let mut uvalue: u64 = 0;
let mut buffer = [0u8; 1];
for _ in 0..5 {
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for Sleb128 from the input".into())
})?;
let byte = buffer[0];
let is_last_byte = byte & 0b1000_0000 == 0;
if is_last_byte {
uvalue += ((byte & 0b0011_1111) as u64) << shift;
let sign = ((byte & 0b0100_0000) as u64) << shift;
let value = uvalue as i64 - sign as i64;
let value: i32 = value.try_into().map_err(|err| Error::DeserializationError(
format!("Failed to parse the Sleb128 value, the encoded value is supposed to fit in 32 bits: {err}")
))?;
return Ok(Self(value));
} else {
uvalue |= ((byte & 0b0111_1111) as u64) << shift;
shift += 7;
}
}
Err(Error::DeserializationError(
"Malfored LEB128 encoding: the value cannot be longer than 5 bytes".into(),
))
}
fn size(&self) -> usize {
self.get_serialized_bytes().len()
}
}
impl Uleb128 {
fn get_serialized_bytes(&self) -> Vec<u8> {
let Self(mut val) = self;
let mut bytes = vec![];
loop {
let byte = val as u8 & 0b0111_1111;
val /= 128;
if val == 0 {
bytes.push(byte);
return bytes;
}
bytes.push(byte | 0b1000_0000);
}
}
}
impl Serializable for Uleb128 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output
.write_all(&self.get_serialized_bytes())
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialize Uleb128 to output: {err}"
))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut shift = 0;
let mut value: u32 = 0;
let mut buffer = [0u8; 1];
for _ in 0..5 {
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for Uleb128 from the input".into())
})?;
let byte = buffer[0];
let is_last_byte = byte & 0b1000_0000 == 0;
value += ((byte & 0b0111_1111) as u32) << shift;
if is_last_byte {
return Ok(Self(value));
}
shift += 7;
}
Err(Error::DeserializationError(
"Malfored LEB128 encoding: the value cannot be longer than 5 bytes".into(),
))
}
fn size(&self) -> usize {
self.get_serialized_bytes().len()
}
}
impl Uleb128p1 {
pub const MINUS_ONE: Uleb128p1 = Uleb128p1(0xFFFFFFFF);
}
impl Serializable for Uleb128p1 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
let Self(val) = self;
Uleb128(val.overflowing_add(1).0).serialize(output)
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let Uleb128(val) = Uleb128::deserialize(input)?;
Ok(Self(val.overflowing_sub(1).0))
}
fn size(&self) -> usize {
let Self(val) = self;
Uleb128(val.overflowing_add(1).0).size()
}
}
impl From<i32> for Sleb128 {
fn from(item: i32) -> Self {
Self(item)
}
}
impl From<u32> for Uleb128 {
fn from(item: u32) -> Self {
Self(item)
}
}
impl From<u32> for Uleb128p1 {
fn from(item: u32) -> Self {
Self(item)
}
}
impl From<Sleb128> for i32 {
fn from(item: Sleb128) -> Self {
item.0
}
}
impl From<Uleb128> for u32 {
fn from(item: Uleb128) -> Self {
item.0
}
}
impl From<Uleb128p1> for u32 {
fn from(item: Uleb128p1) -> Self {
item.0
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn serialize_sleb128() {
assert_eq!(Sleb128(0).serialize_to_vec().unwrap(), vec![0x00u8]);
assert_eq!(Sleb128(1).serialize_to_vec().unwrap(), vec![0x01u8]);
assert_eq!(Sleb128(-1).serialize_to_vec().unwrap(), vec![0x7Fu8]);
assert_eq!(
Sleb128(-128).serialize_to_vec().unwrap(),
vec![0x80u8, 0x7F]
);
}
#[test]
fn deserialize_sleb128() {
assert_eq!(
Sleb128::deserialize_from_slice(&[0x00u8]).unwrap(),
Sleb128(0)
);
assert_eq!(
Sleb128::deserialize_from_slice(&[0x01u8]).unwrap(),
Sleb128(1)
);
assert_eq!(
Sleb128::deserialize_from_slice(&[0x7Fu8]).unwrap(),
Sleb128(-1)
);
assert_eq!(
Sleb128::deserialize_from_slice(&[0x80u8, 0x7Fu8]).unwrap(),
Sleb128(-128)
);
}
#[test]
fn size_sleb128() {
assert_eq!(Sleb128(0).size(), 1);
assert_eq!(Sleb128(1).size(), 1);
assert_eq!(Sleb128(-1).size(), 1);
assert_eq!(Sleb128(-128).size(), 2);
}
#[test]
fn serialize_uleb128() {
assert_eq!(Uleb128(0).serialize_to_vec().unwrap(), vec![0x00u8]);
assert_eq!(Uleb128(1).serialize_to_vec().unwrap(), vec![0x01u8]);
assert_eq!(Uleb128(127).serialize_to_vec().unwrap(), vec![0x7Fu8]);
assert_eq!(
Uleb128(16256).serialize_to_vec().unwrap(),
vec![0x80u8, 0x7F]
);
}
#[test]
fn deserialize_uleb128() {
assert_eq!(
Uleb128::deserialize_from_slice(&[0x00u8]).unwrap(),
Uleb128(0)
);
assert_eq!(
Uleb128::deserialize_from_slice(&[0x01u8]).unwrap(),
Uleb128(1)
);
assert_eq!(
Uleb128::deserialize_from_slice(&[0x7Fu8]).unwrap(),
Uleb128(127)
);
assert_eq!(
Uleb128::deserialize_from_slice(&[0x80u8, 0x7Fu8]).unwrap(),
Uleb128(16256)
);
}
#[test]
fn size_uleb128() {
assert_eq!(Uleb128(0).size(), 1);
assert_eq!(Uleb128(1).size(), 1);
assert_eq!(Uleb128(127).size(), 1);
assert_eq!(Uleb128(16256).size(), 2);
}
#[test]
fn serialize_uleb128p1() {
assert_eq!(
Uleb128p1::MINUS_ONE.serialize_to_vec().unwrap(),
vec![0x00u8]
);
assert_eq!(Uleb128p1(0).serialize_to_vec().unwrap(), vec![0x01u8]);
assert_eq!(Uleb128p1(126).serialize_to_vec().unwrap(), vec![0x7Fu8]);
assert_eq!(
Uleb128p1(16255).serialize_to_vec().unwrap(),
vec![0x80u8, 0x7F]
);
}
#[test]
fn deserialize_uleb128p1() {
assert_eq!(
Uleb128p1::deserialize_from_slice(&[0x00u8]).unwrap(),
Uleb128p1::MINUS_ONE
);
assert_eq!(
Uleb128p1::deserialize_from_slice(&[0x01u8]).unwrap(),
Uleb128p1(0)
);
assert_eq!(
Uleb128p1::deserialize_from_slice(&[0x7Fu8]).unwrap(),
Uleb128p1(126)
);
assert_eq!(
Uleb128p1::deserialize_from_slice(&[0x80u8, 0x7Fu8]).unwrap(),
Uleb128p1(16255)
);
}
#[test]
fn size_uleb128p1() {
assert_eq!(Uleb128p1::MINUS_ONE.size(), 1);
assert_eq!(Uleb128p1(0).size(), 1);
assert_eq!(Uleb128p1(126).size(), 1);
assert_eq!(Uleb128p1(16255).size(), 2);
}
}

View file

@ -0,0 +1,852 @@
/// The main core of the parser.
///
/// TODO: split into more module (error, trait, base type)
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
pub use androscalpel_serializer_derive::*;
mod leb;
pub use leb::*;
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
InputTooSmall(String), // TODO: find a better name
SerializationError(String),
DeserializationError(String),
}
pub type Result<T> = core::result::Result<T, Error>;
pub trait ReadSeek: Read + Seek {}
impl<T: Read + Seek> ReadSeek for T {}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::InputTooSmall(msg) => write!(f, "Error: {}", msg),
Self::SerializationError(msg) => write!(f, "Error: {}", msg),
Self::DeserializationError(msg) => write!(f, "Error: {}", msg),
}
}
}
impl std::error::Error for Error {}
pub trait Serializable {
fn serialize(&self, output: &mut dyn Write) -> Result<()>;
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self>
where
Self: Sized;
fn size(&self) -> usize;
fn serialize_to_vec(&self) -> Result<Vec<u8>> {
let mut output = Cursor::new(Vec::<u8>::new());
self.serialize(&mut output)?;
Ok(output.into_inner())
}
fn deserialize_from_slice(input: &[u8]) -> Result<Self>
where
Self: Sized,
{
let mut buffer = Cursor::new(input);
Self::deserialize(&mut buffer)
}
}
pub trait SerializableUntil<D: Serializable, U: Serializable + Eq> {
fn serialize(&self, output: &mut dyn Write, end_val: U) -> Result<()>;
fn deserialize(input: &mut dyn ReadSeek, end_val: U) -> Result<Self>
where
Self: Sized;
fn size(&self, end_val: U) -> usize;
fn serialize_to_vec(&self, end_val: U) -> Result<Vec<u8>> {
let mut output = Cursor::new(Vec::<u8>::new());
self.serialize(&mut output, end_val)?;
Ok(output.into_inner())
}
fn deserialize_from_slice(input: &[u8], end_val: U) -> Result<Self>
where
Self: Sized,
{
let mut buffer = Cursor::new(input);
Self::deserialize(&mut buffer, end_val)
}
}
impl<D: Serializable, U: Serializable + Eq> SerializableUntil<D, U> for Vec<D> {
fn serialize(&self, output: &mut dyn Write, end_val: U) -> Result<()> {
for data in self {
data.serialize(output)?;
}
end_val.serialize(output)
}
fn deserialize(input: &mut dyn ReadSeek, end_val: U) -> Result<Self>
where
Self: Sized,
{
let mut data = Self::new();
loop {
let pos = input.stream_position().map_err(|err| {
Error::SerializationError(format!("Failled to get position in steam: {err}"))
})?;
match U::deserialize(input) {
Ok(val) if val == end_val => break Ok(data),
Err(err) => break Err(err),
Ok(_) => input.seek(SeekFrom::Start(pos)).map_err(|err| {
Error::SerializationError(format!("Failled to get to position in steam: {err}"))
})?,
};
data.push(D::deserialize(input)?);
}
}
fn size(&self, end_val: U) -> usize {
self.iter().map(|data| data.size()).sum::<usize>() + end_val.size()
}
}
impl Serializable for u8 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize u8 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 1];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for u8 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
1
}
}
impl Serializable for i8 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize i8 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 1];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for i8 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
1
}
}
impl Serializable for u16 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize u16 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 2];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for u16 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
2
}
}
impl Serializable for i16 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize i16 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 2];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for i16 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
2
}
}
impl Serializable for u32 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize u32 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 4];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for u32 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
4
}
}
impl Serializable for i32 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize i32 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 4];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for i32 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
4
}
}
impl Serializable for u64 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize u64 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 8];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for u64 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
8
}
}
impl Serializable for i64 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize i64 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 8];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for i64 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
8
}
}
impl Serializable for u128 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize u128 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 16];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for u128 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
16
}
}
impl Serializable for i128 {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
output.write_all(&self.to_be_bytes()).map_err(|err| {
Error::SerializationError(format!("Failed to write serialize i128 to output: {err}"))
})?;
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 16];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall("Failed to read all bytes for i128 from the input".into())
})?;
Ok(Self::from_be_bytes(buffer))
}
fn size(&self) -> usize {
16
}
}
#[cfg(test)]
mod test {
use super::*;
// Hacky hack to refere to "crate" by its name
use crate as androscalpel_serializer;
#[test]
fn serialize_u8() {
assert_eq!(42u8.serialize_to_vec().unwrap(), vec![42u8]);
}
#[test]
fn deserialize_u8() {
assert_eq!(u8::deserialize_from_slice(&[42u8]).unwrap(), 42u8);
}
#[test]
fn size_u8() {
assert_eq!(42u8.size(), 1);
}
#[test]
fn serialize_u16() {
assert_eq!(0x1234u16.serialize_to_vec().unwrap(), vec![0x12u8, 0x34u8]);
}
#[test]
fn deserialize_u16() {
assert_eq!(
u16::deserialize_from_slice(&[0x12u8, 0x34u8]).unwrap(),
0x1234u16
);
}
#[test]
fn size_u16() {
assert_eq!(0x1234u16.size(), 2);
}
#[test]
fn serialize_u32() {
assert_eq!(
0x12345678u32.serialize_to_vec().unwrap(),
vec![0x12u8, 0x34u8, 0x56u8, 0x78u8]
);
}
#[test]
fn deserialize_u32() {
assert_eq!(
u32::deserialize_from_slice(&[0x12u8, 0x34u8, 0x56u8, 0x78u8]).unwrap(),
0x12345678u32
);
}
#[test]
fn size_u32() {
assert_eq!(0x12345678u32.size(), 4);
}
#[test]
fn serialize_u64() {
assert_eq!(
0x123456789ABCDEF0u64.serialize_to_vec().unwrap(),
vec![0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8]
);
}
#[test]
fn deserialize_u64() {
assert_eq!(
u64::deserialize_from_slice(&[
0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8
])
.unwrap(),
0x123456789ABCDEF0u64
);
}
#[test]
fn size_u64() {
assert_eq!(0x123456789ABCDEF0u64.size(), 8);
}
#[test]
fn serialize_u128() {
assert_eq!(
0x123456789ABCDEF0123456789ABCDEF0u128
.serialize_to_vec()
.unwrap(),
vec![
0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8,
0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8
]
);
}
#[test]
fn deserialize_u128() {
assert_eq!(
u128::deserialize_from_slice(&[
0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8,
0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8
])
.unwrap(),
0x123456789ABCDEF0123456789ABCDEF0u128
);
}
#[test]
fn size_u128() {
assert_eq!(0x123456789ABCDEF0123456789ABCDEF0u128.size(), 16);
}
#[derive(Serializable, Debug, PartialEq, Eq)]
struct NamedComposedTest {
a: u8,
b: u16,
c: u32,
d: u64,
f: u128,
}
#[derive(Serializable, Debug, PartialEq, Eq)]
struct UnamedComposedTest(u8, u16, u32, u64, u128);
#[test]
fn serialize_unnamed_derived() {
let t = UnamedComposedTest(
42u8,
0x1234u16,
0x12345678u32,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0123456789ABCDEF0u128,
);
assert_eq!(
t.serialize_to_vec().unwrap(),
vec![
42u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8,
0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8
]
);
}
#[test]
fn deserialize_named_derived() {
let t = UnamedComposedTest(
42u8,
0x1234u16,
0x12345678u32,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0123456789ABCDEF0u128,
);
let serialized = vec![
42u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8,
0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8,
];
assert_eq!(
UnamedComposedTest::deserialize_from_slice(&serialized).unwrap(),
t
);
}
#[test]
fn size_unnamed_derived() {
let t = UnamedComposedTest(
42u8,
0x1234u16,
0x12345678u32,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0123456789ABCDEF0u128,
);
assert_eq!(t.size(), 1 + 2 + 4 + 8 + 16);
}
#[derive(Serializable, Debug, PartialEq, Eq)]
struct NamedArrayComposedTest {
a: [u8; 1],
b: [u16; 2],
c: [u32; 3],
d: [u64; 4],
e: [u128; 5],
}
#[derive(Serializable, Debug, PartialEq, Eq)]
struct UnamedArrayComposedTest([u8; 1], [u16; 2], [u32; 3], [u64; 4], [u128; 5]);
#[test]
fn serialize_array_unamed_derived() {
let t = UnamedArrayComposedTest(
[42u8],
[0x1234u16, 0x1234u16],
[0x12345678u32, 0x12345678u32, 0x12345678u32],
[
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
],
[
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
],
);
assert_eq!(
t.serialize_to_vec().unwrap(),
vec![
42u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8,
0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8,
0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8,
0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8,
0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8,
0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8,
0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8
]
);
}
#[test]
fn deserialize_array_unamed_derived() {
let t = UnamedArrayComposedTest(
[42u8],
[0x1234u16, 0x1234u16],
[0x12345678u32, 0x12345678u32, 0x12345678u32],
[
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
],
[
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
],
);
let serialized = vec![
42u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8,
0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8,
0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8,
0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8,
0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8,
0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8,
0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8,
0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8,
0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8,
];
assert_eq!(
UnamedArrayComposedTest::deserialize_from_slice(&serialized).unwrap(),
t
);
}
#[test]
fn size_array_unamed_derived() {
let t = UnamedArrayComposedTest(
[42u8],
[0x1234u16, 0x1234u16],
[0x12345678u32, 0x12345678u32, 0x12345678u32],
[
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
],
[
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
],
);
assert_eq!(t.size(), 1 + 2 * 2 + 4 * 3 + 8 * 4 + 16 * 5);
}
#[test]
fn serialize_array_named_derived() {
let t = NamedArrayComposedTest {
a: [42u8],
b: [0x1234u16, 0x1234u16],
c: [0x12345678u32, 0x12345678u32, 0x12345678u32],
d: [
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
],
e: [
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
],
};
assert_eq!(
t.serialize_to_vec().unwrap(),
vec![
42u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8,
0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8,
0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8,
0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8,
0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8,
0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8,
0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8
]
);
}
#[test]
fn deserialize_array_named_derived() {
let t = NamedArrayComposedTest {
a: [42u8],
b: [0x1234u16, 0x1234u16],
c: [0x12345678u32, 0x12345678u32, 0x12345678u32],
d: [
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
],
e: [
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
],
};
let serialized = vec![
42u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8,
0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8,
0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8,
0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8,
0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8,
0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8,
0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8,
0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8,
0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8,
0xBCu8, 0xDEu8, 0xF0u8, 0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8,
0x12u8, 0x34u8, 0x56u8, 0x78u8, 0x9Au8, 0xBCu8, 0xDEu8, 0xF0u8,
];
assert_eq!(
NamedArrayComposedTest::deserialize_from_slice(&serialized).unwrap(),
t
);
}
#[test]
fn size_array_named_derived() {
let t = NamedArrayComposedTest {
a: [42u8],
b: [0x1234u16, 0x1234u16],
c: [0x12345678u32, 0x12345678u32, 0x12345678u32],
d: [
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
0x123456789ABCDEF0u64,
],
e: [
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
0x123456789ABCDEF0123456789ABCDEF0u128,
],
};
assert_eq!(t.size(), 1 + 2 * 2 + 4 * 3 + 8 * 4 + 16 * 5);
}
#[test]
fn size_vec_serializable_until() {
#[derive(Serializable, PartialEq, Eq)]
struct UntilArray([u8; 3]);
let v = vec![0u8, 1u8, 2u8, 3u8];
assert_eq!(v.size(UntilArray([0, 0, 0])), 7);
assert_eq!(v.size(0u8), 5);
}
#[test]
fn serialize_vec_serializable_until() {
#[derive(Serializable, PartialEq, Eq)]
struct UntilArray([u8; 3]);
let v = vec![0u8, 1u8, 2u8, 3u8];
assert_eq!(
v.serialize_to_vec(UntilArray([0, 0, 0])).unwrap(),
vec![0u8, 1u8, 2u8, 3u8, 0u8, 0u8, 0u8]
);
assert_eq!(
v.serialize_to_vec(0u8).unwrap(),
vec![0u8, 1u8, 2u8, 3u8, 0u8]
);
}
#[test]
fn deserialize_vec_serializable_until() {
#[derive(Serializable, PartialEq, Eq)]
struct UntilArray([u8; 3]);
let v1 = vec![0u8, 1u8, 2u8, 3u8];
let serialized_1 = &[0u8, 1u8, 2u8, 3u8, 0u8, 0u8, 0u8];
let serialized_2 = &[0u8, 1u8, 2u8, 3u8, 0u8];
assert_eq!(
v1,
Vec::<u8>::deserialize_from_slice(serialized_1, UntilArray([0, 0, 0])).unwrap()
);
assert_eq!(
Vec::<u8>::new(),
Vec::<u8>::deserialize_from_slice(serialized_2, 0u8).unwrap()
);
}
#[derive(Serializable, PartialEq, Eq, Debug)]
struct UntilArray2([u8; 2]);
#[derive(Serializable, Debug, PartialEq, Eq)]
struct SerializableUntilNamed {
pr: u16,
#[until(u8, UntilArray2, UntilArray2([0u8, 0u8]))]
v: Vec<u8>,
ps: u32,
}
#[test]
fn size_named_serializable_until() {
let v = SerializableUntilNamed {
pr: 0,
v: vec![1, 2, 3],
ps: 0,
};
assert_eq!(v.size(), 2 + 3 + 2 + 4);
}
#[test]
fn serialize_named_serializable_until() {
let v = SerializableUntilNamed {
pr: 0,
v: vec![1, 2, 3],
ps: 0x80000000,
};
assert_eq!(
v.serialize_to_vec().unwrap(),
vec![0, 0, 1, 2, 3, 0, 0, 0x80, 0, 0, 0],
);
}
#[test]
fn deserialize_named_serializable_until() {
let v = SerializableUntilNamed {
pr: 0,
v: vec![1, 2, 3],
ps: 0x80000000,
};
let s = &[0, 0, 1, 2, 3, 0, 0, 0x80, 0, 0, 0];
assert_eq!(
v,
SerializableUntilNamed::deserialize_from_slice(s).unwrap()
);
}
#[derive(Serializable, PartialEq, Eq, Debug)]
#[prefix_type(u8)]
enum TestEnum {
#[prefix(0)]
Zero,
#[prefix(1)]
One(u32),
#[prefix(2)]
Two { a: u16, b: u32 },
}
#[test]
fn size_enum() {
assert_eq!(TestEnum::Zero.size(), 1);
assert_eq!(TestEnum::One(42).size(), 5);
assert_eq!(TestEnum::Two { a: 1, b: 2 }.size(), 7);
}
#[test]
fn serialize_enum() {
assert_eq!(TestEnum::Zero.serialize_to_vec().unwrap(), vec![0u8]);
assert_eq!(
TestEnum::One(42).serialize_to_vec().unwrap(),
vec![1u8, 0u8, 0u8, 0u8, 42u8]
);
assert_eq!(
TestEnum::Two { a: 1, b: 2 }.serialize_to_vec().unwrap(),
vec![2u8, 0u8, 1u8, 0u8, 0u8, 0u8, 2u8]
);
}
#[test]
fn deserialize_enum() {
assert_eq!(
TestEnum::deserialize_from_slice(&[0u8]).unwrap(),
TestEnum::Zero
);
assert_eq!(
TestEnum::deserialize_from_slice(&[1u8, 0u8, 0u8, 0u8, 42u8]).unwrap(),
TestEnum::One(42)
);
assert_eq!(
TestEnum::deserialize_from_slice(&[2u8, 0u8, 1u8, 0u8, 0u8, 0u8, 2u8]).unwrap(),
TestEnum::Two { a: 1, b: 2 }
);
assert!(TestEnum::deserialize_from_slice(&[255u8]).is_err());
}
}