use deku::deku_derive; use super::{ groups, size_read, read_with_size }; #[derive(Debug, PartialEq)] #[deku_derive(DekuRead)] /// # Data: FSV data structure /// This structure is the core structure to read FSV raw data /// It handles directly the raw data returned by the FSV library /// A `Data` structure is composed of multiple `DataBlock` structures pub struct Data { #[deku(read_all)] pub blocks: Vec, } #[derive(Debug, PartialEq)] #[deku_derive(DekuRead)] /// # Data block structure /// The `DataBlock` are the main structures inside a `Data` struct pub struct DataBlock { pub header: BlockHeader, #[deku(ctx = "header.group_id.0, header.data_size")] pub content: DataGroup, } #[derive(Debug, PartialEq)] #[deku_derive(DekuRead)] /// # Block header structure /// The `BlockHeader` structure is the header of a `DataBlock` /// It contains the group ID and the size of the `DataBlock` contained data (`inner` field) pub struct BlockHeader { pub group_id: GroupId, #[deku(reader = "size_read(deku::reader)")] pub data_size: u64, } #[derive(Debug, PartialEq)] #[deku_derive(DekuRead)] /// # Group ID /// Allow to identify the type of data contained in a `DataBlock` /// It is use as matching ID in the `DataGroup` enum. All the /// IDs are documented on the SSV documentation, pages 23-28 pub struct GroupId( #[deku(endian="big", bytes= 2)] pub u16, ); /// # Data group enum /// This enum is used to match a `DataBlock` content with the /// correct data structure, able to parse the data contained in #[derive(Debug, PartialEq)] #[deku_derive(DekuRead)] #[deku(ctx = "group_id: u16, data_size: u64", id = "group_id")] #[allow(non_camel_case_types)] pub enum DataGroup { #[deku(id = 1)] LireCartePS_Group1_Holder( #[deku(reader = "read_with_size(deku::reader, data_size as usize)")] groups::ssv_lire_carte_ps::group_1_holder::Holder), #[deku(id = 2)] LireCartePS_Group2_Situation( #[deku(reader = "read_with_size(deku::reader, data_size as usize)")] groups::ssv_lire_carte_ps::group_2_situation::Situation), #[deku(id = 60)] LireConfig_Group60_ConfigHeader( #[deku(reader = "read_with_size(deku::reader, data_size as usize)")] groups::ssv_lire_config::group_60_header_config::ConfigHeader), #[deku(id = 61)] LireConfig_Group61_ReaderConfig( #[deku(reader = "read_with_size(deku::reader, data_size as usize)")] groups::ssv_lire_config::group_61_reader_config::ReaderConfig), #[deku(id = 64)] LireConfig_Group64_SVComponentsConfig( #[deku(reader = "read_with_size(deku::reader, data_size as usize)")] groups::ssv_lire_config::group_64_sv_config::SVComponentsConfig), #[deku(id = 67)] LireConfig_Group67_PCSCReaderConfig( #[deku(reader = "read_with_size(deku::reader, data_size as usize)")] groups::ssv_lire_config::group_67_pcsc_config::PCSCReaderConfig), } #[cfg(test)] mod tests { use deku::DekuContainerRead as _; use super::*; mod deku_testing { use super::*; #[derive(Debug, PartialEq)] #[deku_derive(DekuRead)] #[deku(endian = "big")] pub struct DekuTest { #[deku(bits = 4)] pub a: u8, #[deku(bits = 4)] pub b: u8, pub c: u16, } #[derive(Debug, PartialEq)] #[deku_derive(DekuRead)] #[deku(endian = "big")] pub struct DekuTestWithSizeReader { #[deku(bytes = 2)] pub id: u16, #[deku(reader = "size_read(deku::reader)")] pub size: u64, } #[derive(Debug, PartialEq)] #[deku_derive(DekuRead)] pub struct DekuTestWithGroupId { pub group_id: GroupId, } } #[test] fn test_deserialize_deku_test() { let buffer: &[u8] = &[0b0110_1001, 0xBE, 0xEF]; let offset: usize = 0; let ((rest, offset), val) = deku_testing::DekuTest::from_bytes((buffer, offset)).unwrap(); assert_eq!(val.a, 0b0110); assert_eq!(val.b, 0b1001); assert_eq!(val.c, 0xBEEF); assert_eq!(offset, 0); assert_eq!(rest, &[]); } #[test] fn test_deserialize_deku_test_with_offset() { let buffer: &[u8] = &[0b0000_1111, 0b0110_1001, 0xBE, 0xEF]; let offset: usize = 8; let ((rest, offset), val) = deku_testing::DekuTest::from_bytes((buffer, offset)).unwrap(); assert_eq!(val.a, 0b0110); assert_eq!(val.b, 0b1001); assert_eq!(val.c, 0xBEEF); assert_eq!(offset, 0); assert_eq!(rest, &[]); } #[test] fn test_serialize_deku_test_with_rest() { let buffer: &[u8] = &[0b0110_1001, 0xBE, 0xEF, 0x1F, 0x2F]; let offset: usize = 0; let ((rest, offset), val) = deku_testing::DekuTest::from_bytes((buffer, offset)).unwrap(); assert_eq!(val.a, 0b0110); assert_eq!(val.b, 0b1001); assert_eq!(val.c, 0xBEEF); assert_eq!(offset, 0); assert_eq!(rest, &[0x1F, 0x2F]); } #[test] fn test_size_read() { let buffer: &[u8] = &[ 0, 60, // ID (60) 0b0100_0000, // Size type bit (0) + Size (64) 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 // Extra data (10 bytes ; should be 64) ]; let ((rest, _offset), val) = deku_testing::DekuTestWithSizeReader::from_bytes((buffer, 0)).unwrap(); assert_eq!(val.id, 60, "EX1: ID"); assert_eq!(val.size, 64, "EX1: Size"); assert_eq!(rest.len(), 10, "EX1: Rest"); let buffer: &[u8] = &[ 0, 60, // ID (60) 0b1000_0010, // Size type bit (1) + Size block length (2) 0b0000_0001, 0b0100_0000, // Size (320) 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 // Extra data (10 bytes ; should be 320) ]; let ((rest, _offset), val) = deku_testing::DekuTestWithSizeReader::from_bytes((buffer, 0)).unwrap(); assert_eq!(val.id, 60, "EX2: ID"); assert_eq!(val.size, 320, "EX2: Size"); println!("{:?}", rest); // assert_eq!(val.size, 320, "EX2: Size"); } #[test] fn test_endianness() { #[derive(Debug, PartialEq)] #[deku_derive(DekuRead)] struct DekuTest { #[deku(endian = "big")] field_be: u16, #[deku(endian = "little")] field_le: u16, field_default: u16, } let buffer: &[u8] = &[ 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, ]; let (_rest, result) = DekuTest::from_bytes((buffer, 0)).unwrap(); assert_eq!(result.field_be, 0xABCD, "0xAB,0xCD - Big Endian"); assert_eq!(result.field_le, 0xCDAB, "0xAB,0xCD - Little Endian"); assert_eq!(deku::ctx::Endian::default(), deku::ctx::Endian::Little, "Default Endian"); assert_eq!(result.field_default, 0xCDAB, "0xAB,0xCD - Default Endian"); let buffer: &[u8] = &[ 0, 64, 0, 64, 0, 64, ]; let (_rest, result) = DekuTest::from_bytes((buffer, 0)).unwrap(); assert_eq!(result.field_be, 64, "0,64 - Big Endian"); assert_eq!(result.field_le, 16384, "0,64 - Little Endian"); assert_eq!(deku::ctx::Endian::default(), deku::ctx::Endian::Little); assert_eq!(result.field_default, 16384, "0,64 - Default Endian"); } #[test] fn test_group_id() { // env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging let buffer: &[u8] = &[ 0, 60, // ID (60) ]; let (_rest, val) = deku_testing::DekuTestWithGroupId::from_bytes((buffer, 0)).unwrap(); assert_eq!(val.group_id.0, 60, "EX1: ID"); let buffer: &[u8] = &[ 7, 118, // ID (1910) ]; let (_rest, val) = deku_testing::DekuTestWithGroupId::from_bytes((buffer, 0)).unwrap(); assert_eq!(val.group_id.0, 1910, "EX2: ID"); } }