1use crate::{
5 conflict::{ConflictError, ConflictReason},
6 flags::Flags,
7};
8
9use bee_common::packable::{OptionError, Packable, Read, Write};
10use bee_message::{milestone::MilestoneIndex, MessageId};
11
12use serde::Serialize;
13
14use std::{
15 cmp::Ordering,
16 time::{SystemTime, UNIX_EPOCH},
17};
18
19#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Serialize)]
21pub struct MessageMetadata {
22 flags: Flags,
23 milestone_index: Option<MilestoneIndex>,
24 arrival_timestamp: u64,
25 solidification_timestamp: u64,
26 reference_timestamp: u64,
27 omrsi: Option<IndexId>,
28 ymrsi: Option<IndexId>,
29 conflict: ConflictReason,
30}
31
32impl MessageMetadata {
33 #[allow(clippy::too_many_arguments)]
35 pub fn new(
36 flags: Flags,
37 milestone_index: Option<MilestoneIndex>,
38 arrival_timestamp: u64,
39 solidification_timestamp: u64,
40 reference_timestamp: u64,
41 omrsi: Option<IndexId>,
42 ymrsi: Option<IndexId>,
43 conflict: ConflictReason,
44 ) -> Self {
45 Self {
46 flags,
47 milestone_index,
48 arrival_timestamp,
49 solidification_timestamp,
50 reference_timestamp,
51 omrsi,
52 ymrsi,
53 conflict,
54 }
55 }
56
57 pub fn arrived() -> Self {
59 Self {
60 arrival_timestamp: SystemTime::now()
61 .duration_since(UNIX_EPOCH)
62 .expect("Clock may have gone backwards")
63 .as_millis() as u64,
64 ..Self::default()
65 }
66 }
67
68 pub fn flags(&self) -> &Flags {
70 &self.flags
71 }
72
73 pub fn flags_mut(&mut self) -> &mut Flags {
75 &mut self.flags
76 }
77
78 pub fn milestone_index(&self) -> Option<MilestoneIndex> {
80 self.milestone_index
81 }
82
83 pub fn set_milestone_index(&mut self, index: MilestoneIndex) {
85 self.milestone_index = Some(index);
86 }
87
88 pub fn arrival_timestamp(&self) -> u64 {
90 self.arrival_timestamp
91 }
92
93 pub fn solidification_timestamp(&self) -> u64 {
95 self.solidification_timestamp
96 }
97
98 pub fn omrsi(&self) -> Option<IndexId> {
100 self.omrsi
101 }
102
103 pub fn set_omrsi(&mut self, omrsi: IndexId) {
105 self.omrsi = Some(omrsi);
106 }
107
108 pub fn ymrsi(&self) -> Option<IndexId> {
110 self.ymrsi
111 }
112
113 pub fn set_ymrsi(&mut self, ymrsi: IndexId) {
115 self.ymrsi = Some(ymrsi);
116 }
117
118 pub fn reference_timestamp(&self) -> u64 {
120 self.reference_timestamp
121 }
122
123 pub fn mark_solid(&mut self) {
125 self.flags.set_solid(true);
126 self.solidification_timestamp = SystemTime::now()
127 .duration_since(UNIX_EPOCH)
128 .expect("Clock may have gone backwards")
129 .as_millis() as u64;
130 }
131
132 pub fn reference(&mut self, timestamp: u64) {
134 self.flags.set_referenced(true);
135 self.reference_timestamp = timestamp;
136 }
137
138 pub fn conflict(&self) -> ConflictReason {
140 self.conflict
141 }
142
143 pub fn set_conflict(&mut self, conflict: ConflictReason) {
145 self.conflict = conflict;
146 }
147}
148
149#[derive(Debug)]
151pub enum MessageMetadataError {
152 Io(std::io::Error),
154 OptionIndex(<Option<MilestoneIndex> as Packable>::Error),
156 OptionIndexId(<Option<IndexId> as Packable>::Error),
158 Conflict(ConflictError),
160}
161
162impl From<std::io::Error> for MessageMetadataError {
163 fn from(error: std::io::Error) -> Self {
164 MessageMetadataError::Io(error)
165 }
166}
167
168impl From<OptionError<std::io::Error>> for MessageMetadataError {
169 fn from(error: OptionError<std::io::Error>) -> Self {
170 MessageMetadataError::OptionIndex(error)
171 }
172}
173
174impl From<OptionError<IndexIdError>> for MessageMetadataError {
175 fn from(error: OptionError<IndexIdError>) -> Self {
176 MessageMetadataError::OptionIndexId(error)
177 }
178}
179
180impl Packable for MessageMetadata {
181 type Error = MessageMetadataError;
182
183 fn packed_len(&self) -> usize {
184 self.flags.packed_len()
185 + self.milestone_index.packed_len()
186 + self.arrival_timestamp.packed_len()
187 + self.solidification_timestamp.packed_len()
188 + self.reference_timestamp.packed_len()
189 + self.omrsi.packed_len()
190 + self.ymrsi.packed_len()
191 + self.conflict.packed_len()
192 }
193
194 fn pack<W: Write>(&self, writer: &mut W) -> Result<(), Self::Error> {
195 self.flags.pack(writer)?;
196 self.milestone_index.pack(writer)?;
197 self.arrival_timestamp.pack(writer)?;
198 self.solidification_timestamp.pack(writer)?;
199 self.reference_timestamp.pack(writer)?;
200 self.omrsi.pack(writer)?;
201 self.ymrsi.pack(writer)?;
202 self.conflict.pack(writer).map_err(MessageMetadataError::Conflict)?;
203
204 Ok(())
205 }
206
207 fn unpack_inner<R: Read + ?Sized, const CHECK: bool>(reader: &mut R) -> Result<Self, Self::Error> {
208 Ok(Self {
209 flags: Flags::unpack_inner::<R, CHECK>(reader)?,
210 milestone_index: Option::<MilestoneIndex>::unpack_inner::<R, CHECK>(reader)?,
211 arrival_timestamp: u64::unpack_inner::<R, CHECK>(reader)?,
212 solidification_timestamp: u64::unpack_inner::<R, CHECK>(reader)?,
213 reference_timestamp: u64::unpack_inner::<R, CHECK>(reader)?,
214 omrsi: Option::<IndexId>::unpack_inner::<R, CHECK>(reader)?,
215 ymrsi: Option::<IndexId>::unpack_inner::<R, CHECK>(reader)?,
216 conflict: ConflictReason::unpack_inner::<R, CHECK>(reader).map_err(MessageMetadataError::Conflict)?,
217 })
218 }
219}
220
221#[derive(Clone, Copy, Debug, Serialize)]
224pub struct IndexId(MilestoneIndex, MessageId);
225
226impl IndexId {
227 pub fn new(index: MilestoneIndex, id: MessageId) -> Self {
229 Self(index, id)
230 }
231
232 pub fn index(&self) -> MilestoneIndex {
234 self.0
235 }
236
237 pub fn id(&self) -> MessageId {
239 self.1
240 }
241
242 pub fn set_index(&mut self, index: MilestoneIndex) {
244 self.0 = index;
245 }
246}
247
248impl Ord for IndexId {
249 fn cmp(&self, other: &Self) -> Ordering {
250 self.0.cmp(&other.0)
251 }
252}
253
254impl PartialOrd for IndexId {
255 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
256 self.0.partial_cmp(&other.0)
257 }
258}
259
260impl Eq for IndexId {}
261
262impl PartialEq for IndexId {
263 fn eq(&self, other: &Self) -> bool {
264 self.0 == other.0
265 }
266}
267
268impl Packable for IndexId {
269 type Error = IndexIdError;
270
271 fn packed_len(&self) -> usize {
272 self.0.packed_len() + self.1.packed_len()
273 }
274
275 fn pack<W: Write>(&self, writer: &mut W) -> Result<(), Self::Error> {
276 self.0.pack(writer)?;
277 self.1.pack(writer)?;
278
279 Ok(())
280 }
281
282 fn unpack_inner<R: Read + ?Sized, const CHECK: bool>(reader: &mut R) -> Result<Self, Self::Error> {
283 let index = MilestoneIndex::unpack_inner::<R, CHECK>(reader)?;
284 let id = MessageId::unpack_inner::<R, CHECK>(reader)?;
285
286 Ok(Self(index, id))
287 }
288}
289
290#[derive(Debug)]
292pub enum IndexIdError {
293 Io(std::io::Error),
295 MessageId(bee_message::Error),
297}
298
299impl From<std::io::Error> for IndexIdError {
300 fn from(error: std::io::Error) -> Self {
301 IndexIdError::Io(error)
302 }
303}
304
305impl From<bee_message::Error> for IndexIdError {
306 fn from(error: bee_message::Error) -> Self {
307 IndexIdError::MessageId(error)
308 }
309}