datex_core/global/protocol_structures/
block_header.rs1use super::serializable::Serializable;
2use crate::values::core_values::endpoint::Endpoint;
3use binrw::{BinRead, BinWrite};
4use core::prelude::rust_2024::*;
5use modular_bitfield::{Specifier, bitfield, prelude::B43};
6use strum_macros::Display;
7
8#[derive(Debug, Display, PartialEq, Clone, Copy, Default, Specifier)]
10#[cfg_attr(feature = "debug", derive(serde::Serialize, serde::Deserialize))]
11#[bits = 4]
12pub enum BlockType {
13 #[default]
14 Request = 0,
15 Response = 1,
16 Hello = 2,
17 Trace = 3,
18 TraceBack = 4,
19}
20
21impl BlockType {
22 pub fn is_response(&self) -> bool {
23 core::matches!(self, BlockType::Response | BlockType::TraceBack)
24 }
25}
26
27#[bitfield]
31#[derive(BinWrite, BinRead, Clone, Copy, Debug, PartialEq)]
32#[bw(map = |&x| Self::into_bytes(x))]
33#[br(map = Self::from_bytes)]
34#[brw(little)]
35pub struct FlagsAndTimestamp {
36 pub block_type: BlockType,
37 pub has_side_effects: bool,
38 pub has_only_data: bool,
39 pub is_end_of_section: bool,
40 pub is_end_of_context: bool,
41 pub has_lifetime: bool,
42 pub has_represented_by: bool,
43 pub has_iv: bool,
44 pub is_compressed: bool,
45 pub is_signature_in_last_subblock: bool,
46
47 #[allow(unused)]
48 unused_0: bool,
49 #[allow(unused)]
50 unused_1: bool,
51 #[allow(unused)]
52 unused_2: bool,
53 #[allow(unused)]
54 unused_3: bool,
55 #[allow(unused)]
56 unused_4: bool,
57 #[allow(unused)]
58 unused_5: bool,
59 #[allow(unused)]
60 unused_6: bool,
61 #[allow(unused)]
62 unused_7: bool,
63
64 pub creation_timestamp: B43,
65}
66
67#[cfg(feature = "debug")]
68mod flags_and_timestamp_serde {
69 use super::*;
70 use serde::{Deserialize, Deserializer, Serialize, Serializer};
71
72 #[derive(Serialize, Deserialize)]
73 struct FlagsHelper {
74 block_type: BlockType,
75 has_side_effects: bool,
76 has_only_data: bool,
77 is_end_of_section: bool,
78 is_end_of_context: bool,
79 has_lifetime: bool,
80 has_represented_by: bool,
81 has_iv: bool,
82 is_compressed: bool,
83 is_signature_in_last_subblock: bool,
84 creation_timestamp: u64,
85 }
86
87 impl Serialize for FlagsAndTimestamp {
88 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89 where
90 S: Serializer,
91 {
92 let helper = FlagsHelper {
93 block_type: self.block_type(),
94 has_side_effects: self.has_side_effects(),
95 has_only_data: self.has_only_data(),
96 is_end_of_section: self.is_end_of_section(),
97 is_end_of_context: self.is_end_of_context(),
98 has_lifetime: self.has_lifetime(),
99 has_represented_by: self.has_represented_by(),
100 has_iv: self.has_iv(),
101 is_compressed: self.is_compressed(),
102 is_signature_in_last_subblock: self
103 .is_signature_in_last_subblock(),
104 creation_timestamp: self.creation_timestamp(),
105 };
106 helper.serialize(serializer)
107 }
108 }
109
110 impl<'de> Deserialize<'de> for FlagsAndTimestamp {
111 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
112 where
113 D: Deserializer<'de>,
114 {
115 let helper = FlagsHelper::deserialize(deserializer)?;
116 Ok(FlagsAndTimestamp::new()
117 .with_block_type(helper.block_type)
118 .with_has_side_effects(helper.has_side_effects)
119 .with_has_only_data(helper.has_only_data)
120 .with_is_end_of_section(helper.is_end_of_section)
121 .with_is_end_of_context(helper.is_end_of_context)
122 .with_has_lifetime(helper.has_lifetime)
123 .with_has_represented_by(helper.has_represented_by)
124 .with_has_iv(helper.has_iv)
125 .with_is_compressed(helper.is_compressed)
126 .with_is_signature_in_last_subblock(
127 helper.is_signature_in_last_subblock,
128 )
129 .with_creation_timestamp(helper.creation_timestamp))
130 }
131 }
132}
133
134impl Default for FlagsAndTimestamp {
135 fn default() -> Self {
136 FlagsAndTimestamp::new()
137 .with_block_type(BlockType::Request)
138 .with_has_side_effects(true)
139 .with_has_only_data(false)
140 .with_is_end_of_section(true)
141 .with_is_end_of_context(true)
142 .with_has_lifetime(false)
143 .with_has_represented_by(false)
144 .with_has_iv(false)
145 .with_is_compressed(false)
146 .with_is_signature_in_last_subblock(false)
147 }
148}
149
150#[cfg_attr(feature = "debug", derive(serde::Serialize, serde::Deserialize))]
153#[derive(Debug, Clone, Default, BinWrite, BinRead, PartialEq)]
154#[brw(little)]
155pub struct BlockHeader {
156 pub context_id: u32,
159 pub section_index: u16,
163 pub block_number: u16,
169
170 pub flags_and_timestamp: FlagsAndTimestamp,
171
172 #[brw(if(flags_and_timestamp.has_lifetime()))]
173 pub lifetime: Option<u32>,
174
175 #[brw(if(flags_and_timestamp.has_represented_by()))]
176 pub represented_by: Option<Endpoint>,
177
178 #[brw(if(flags_and_timestamp.has_iv()))]
179 pub iv: Option<[u8; 16]>,
180}
181
182impl Serializable for BlockHeader {}