datex_core/global/protocol_structures/
block_header.rs

1use super::serializable::Serializable;
2use crate::values::core_values::endpoint::Endpoint;
3use binrw::{BinRead, BinWrite};
4use modular_bitfield::{Specifier, bitfield, prelude::B43};
5use strum_macros::Display;
6
7// 4 bit
8#[derive(Debug, Display, PartialEq, Clone, Copy, Default, Specifier)]
9pub enum BlockType {
10    #[default]
11    Request = 0,
12    Response = 1,
13    Hello = 2,
14    Trace = 3,
15    TraceBack = 4,
16    #[allow(unused)]
17    Unused3,
18    #[allow(unused)]
19    Unused4,
20    #[allow(unused)]
21    Unused5,
22    #[allow(unused)]
23    Unused6,
24    #[allow(unused)]
25    Unused7,
26    #[allow(unused)]
27    Unused8,
28    #[allow(unused)]
29    Unused9,
30    #[allow(unused)]
31    Unused10,
32    #[allow(unused)]
33    Unused11,
34    #[allow(unused)]
35    Unused12,
36    #[allow(unused)]
37    Unused13,
38}
39
40impl BlockType {
41    pub fn is_response(&self) -> bool {
42        match self {
43            BlockType::Response | BlockType::TraceBack => true,
44            _ => false,
45        }
46    }
47}
48
49// 21 bit + 43 bit = 64 bit
50#[bitfield]
51#[derive(BinWrite, BinRead, Clone, Copy, Debug, PartialEq)]
52#[bw(map = |&x| Self::into_bytes(x))]
53#[br(map = Self::from_bytes)]
54pub struct FlagsAndTimestamp {
55    pub block_type: BlockType,
56    pub allow_execution: bool,
57    pub is_end_of_section: bool,
58    pub is_end_of_context: bool,
59    pub has_lifetime: bool,
60    pub has_represented_by: bool,
61    pub has_iv: bool,
62    pub is_compressed: bool,
63    pub is_signature_in_last_subblock: bool,
64
65    #[allow(unused)]
66    unused_0: bool,
67    #[allow(unused)]
68    unused_1: bool,
69    #[allow(unused)]
70    unused_2: bool,
71    #[allow(unused)]
72    unused_3: bool,
73    #[allow(unused)]
74    unused_4: bool,
75    #[allow(unused)]
76    unused_5: bool,
77    #[allow(unused)]
78    unused_6: bool,
79    #[allow(unused)]
80    unused_7: bool,
81    #[allow(unused)]
82    unused_8: bool,
83
84    pub creation_timestamp: B43,
85}
86
87impl Default for FlagsAndTimestamp {
88    fn default() -> Self {
89        FlagsAndTimestamp::new()
90            .with_block_type(BlockType::Request)
91            .with_allow_execution(false)
92            .with_is_end_of_section(true)
93            .with_is_end_of_context(true)
94            .with_has_lifetime(false)
95            .with_has_represented_by(false)
96            .with_has_iv(false)
97            .with_is_compressed(false)
98            .with_is_signature_in_last_subblock(false)
99    }
100}
101
102// min: 16 byte
103// max 8 + 8 byte + 4 byte + 21 byte + 16 byte = 57 byte
104#[derive(Debug, Clone, Default, BinWrite, BinRead, PartialEq)]
105#[brw(little)]
106pub struct BlockHeader {
107    /// A unique id that defines the context in which this block lives
108    /// A context has a persistent state that can e.g. contain DATEX variables
109    pub context_id: u32,
110    /// A section is a collection of multiple sequential blocks inside the same context
111    /// (each with an incrementing block number)
112    /// When a new section starts, the block number is not reset but continues to increment
113    pub section_index: u16,
114    /// A unique number that identifies a block inside a block context
115    /// The context_id combined with the block_number define a unique block from a specific endpoint
116    /// the block id (endpoint, context_id, block_number) defines a globally unique block
117    /// Note: blocks ids are not completely unique, when the block_number or section_index overflows,
118    /// it starts from 0 again, leading to duplicate block ids after a while
119    pub block_number: u16,
120
121    pub flags_and_timestamp: FlagsAndTimestamp,
122
123    #[brw(if(flags_and_timestamp.has_lifetime()))]
124    pub lifetime: Option<u32>,
125
126    #[brw(if(flags_and_timestamp.has_represented_by()))]
127    pub represented_by: Option<Endpoint>,
128
129    #[brw(if(flags_and_timestamp.has_iv()))]
130    pub iv: [u8; 16],
131}
132
133impl Serializable for BlockHeader {}