Krys4lide/crates/fsv/src/fsv_parsing/blocks.rs

238 lines
7.9 KiB
Rust
Raw Normal View History

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");
}
}