238 lines
7.9 KiB
Rust
238 lines
7.9 KiB
Rust
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<DataBlock>,
|
|
}
|
|
|
|
#[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");
|
|
}
|
|
} |