#![cfg(feature = "alloc")]
#![allow(clippy::unusual_byte_groupings)]
#[cfg(any(feature = "bits", feature = "std"))]
use core::convert::{TryFrom, TryInto};
#[cfg(any(feature = "alloc", feature = "bits", feature = "std"))]
use deku::prelude::*;
mod test_common;
#[cfg(feature = "bits")]
#[derive(PartialEq, Debug, DekuRead, DekuWrite, DekuSize)]
pub struct DoubleNestedDeku {
pub data: u16,
}
#[cfg(feature = "bits")]
#[derive(PartialEq, Debug, DekuRead, DekuWrite, DekuSize)]
pub struct NestedDeku {
#[deku(bits = 6)]
pub nest_a: u8,
#[deku(bits = 2)]
pub nest_b: u8,
pub inner: DoubleNestedDeku,
}
#[cfg(feature = "bits")]
#[test]
fn test_nested_struct_sizes() {
assert_eq!(DoubleNestedDeku::SIZE_BYTES, Some(2));
assert_eq!(NestedDeku::SIZE_BYTES, Some(3));
}
#[cfg(all(feature = "bits", feature = "descriptive-errors"))]
#[test]
#[should_panic(expected = r#"Parse("Too much data: Read 0 but total length was 100")"#)]
fn test_read_too_much_data() {
#[derive(DekuRead)]
pub struct TestStruct {
#[expect(dead_code)]
#[deku(bits = 6)]
pub field_a: u8,
}
let test_data: &[u8] = &[0u8; 100];
TestStruct::try_from(test_data).unwrap();
}
#[cfg(feature = "bits")]
#[test]
fn test_unnamed_struct() {
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
pub struct TestUnamedStruct(
pub u8,
#[deku(bits = 2)] pub u8,
#[deku(bits = 6)] pub u8,
#[deku(bytes = 2)] pub u16,
#[deku(endian = "big")] pub u16,
pub NestedDeku,
#[deku(update = "self.7.len()")] pub u8,
#[deku(count = "field_6")] pub Vec<u8>,
);
let test_data: Vec<u8> = [
0xff,
0b1001_0110,
0xaa,
0xbb,
0xcc,
0xdd,
0b1001_0110,
0xcc,
0xdd,
0x02,
0xbe,
0xef,
]
.to_vec();
let ret_read = TestUnamedStruct::try_from(test_data.as_slice()).unwrap();
assert_eq!(
TestUnamedStruct(
0xff,
0b0000_0010,
0b0001_0110,
native_endian!(0xbbaau16),
0xccddu16,
NestedDeku {
nest_a: 0b00_100101,
nest_b: 0b10,
inner: DoubleNestedDeku {
data: native_endian!(0xddccu16)
}
},
0x02,
vec![0xbe, 0xef],
),
ret_read
);
let ret_write: Vec<u8> = ret_read.try_into().unwrap();
assert_eq!(test_data, ret_write);
}
#[cfg(feature = "bits")]
#[test]
fn test_named_struct() {
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
pub struct TestStruct {
pub field_a: u8,
#[deku(bits = 2)]
pub field_b: u8,
#[deku(bits = 6)]
pub field_c: u8,
#[deku(bytes = 2)]
pub field_d: u16,
#[deku(update = "1+self.field_d")]
#[deku(endian = "big")]
pub field_e: u16,
pub field_f: NestedDeku,
pub vec_len: u8,
#[deku(count = "vec_len")]
pub vec_data: Vec<u8>,
pub rest: u8,
}
let test_data: Vec<u8> = [
0xff,
0b1001_0110,
0xaa,
0xbb,
0xcc,
0xdd,
0b1001_0110,
0xcc,
0xdd,
0x02,
0xbe,
0xef,
0xff,
]
.to_vec();
let ret_read = TestStruct::try_from(test_data.as_slice()).unwrap();
assert_eq!(
TestStruct {
field_a: 0xff,
field_b: 0b0000_0010,
field_c: 0b0001_0110,
field_d: native_endian!(0xbbaau16),
field_e: 0xccddu16,
field_f: NestedDeku {
nest_a: 0b00_100101,
nest_b: 0b10,
inner: DoubleNestedDeku {
data: native_endian!(0xddccu16)
}
},
vec_len: 0x02,
vec_data: vec![0xbe, 0xef],
rest: 0xff
},
ret_read
);
let ret_write: Vec<u8> = ret_read.try_into().unwrap();
assert_eq!(test_data, ret_write);
}
#[cfg(all(feature = "alloc", feature = "std"))]
#[test]
fn test_raw_identifiers_struct() {
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
pub struct TestStruct {
pub r#type: u8,
}
let test_data: Vec<u8> = [0xff].to_vec();
let ret_read = TestStruct::try_from(test_data.as_slice()).unwrap();
assert_eq!(TestStruct { r#type: 0xff }, ret_read);
let ret_write: Vec<u8> = ret_read.try_into().unwrap();
assert_eq!(test_data, ret_write);
}
#[cfg(feature = "alloc")]
#[test]
fn test_big_endian() {
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
pub struct A {
#[deku(bytes = "3", endian = "big")]
address: u32,
}
let bytes = [0x11, 0x22, 0x33];
let a = A::from_bytes((&bytes, 0)).unwrap().1;
let new_bytes = a.to_bytes().unwrap();
assert_eq!(bytes, &*new_bytes);
let bytes = &[0x11, 0x22, 0x33];
let a = A::from_bytes((bytes, 0)).unwrap().1;
let new_bytes = a.to_bytes().unwrap();
assert_eq!(bytes, &*new_bytes);
#[derive(PartialEq, Debug, DekuRead, DekuWrite)]
pub struct B {
#[deku(bytes = "2", endian = "big")]
address: u32,
}
let bytes = [0x00, 0xff, 0xab, 0xaa];
let a = B::from_bytes((&bytes, 0)).unwrap().1;
let new_bytes = a.to_bytes().unwrap();
assert_eq!(&bytes[..2], &*new_bytes);
}
#[cfg(feature = "alloc")]
#[test]
fn test_units() {
#[derive(DekuRead, DekuWrite)]
#[deku(magic = b"\xf0")]
struct Unit;
let bytes = [0xf0];
let a = Unit::from_bytes((&bytes, 0)).unwrap().1;
let new_bytes = a.to_bytes().unwrap();
assert_eq!(bytes, &*new_bytes);
let a = Unit;
let new_bytes = a.to_bytes().unwrap();
assert_eq!(bytes, &*new_bytes);
}
#[cfg(feature = "alloc")]
#[test]
fn test_zst_vec_1() {
#[derive(Debug, PartialEq, DekuRead)]
struct EmptyThing {}
#[derive(Debug, PartialEq, DekuRead)]
struct ListOfThings {
#[deku(read_all)]
things: Vec<EmptyThing>,
}
let bytes = vec![];
let (_y, x) = ListOfThings::from_bytes((&bytes, 0)).unwrap();
assert_eq!(x.things.len(), 0);
}
#[cfg(feature = "alloc")]
#[test]
fn test_zst_vec_2() {
#[derive(Debug, PartialEq, DekuRead)]
struct EmptyThing {}
#[derive(Debug, PartialEq, DekuRead)]
struct ListOfThings {
#[deku(bytes_read = "1")]
things: Vec<EmptyThing>,
}
let bytes = vec![];
let (_y, x) = ListOfThings::from_bytes((&bytes, 0)).unwrap();
assert_eq!(x.things.len(), 0);
}