1use core::fmt::{self, Display, Formatter, LowerHex, UpperHex};
11
12use zb_core::IeeeAddress;
13
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
21pub struct Envelope<T> {
22 source: Source,
23 metadata: Metadata,
24 payload: T,
25}
26
27impl<T> Envelope<T> {
28 #[must_use]
30 pub const fn new(source: Source, metadata: Metadata, payload: T) -> Self {
31 Self {
32 source,
33 metadata,
34 payload,
35 }
36 }
37
38 #[must_use]
40 pub const fn source(&self) -> Source {
41 self.source
42 }
43
44 #[must_use]
46 pub const fn metadata(&self) -> Metadata {
47 self.metadata
48 }
49
50 #[must_use]
52 pub const fn payload(&self) -> &T {
53 &self.payload
54 }
55
56 #[must_use]
58 pub fn into_parts(self) -> (Source, Metadata, T) {
59 (self.source, self.metadata, self.payload)
60 }
61}
62
63#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
68#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
69pub struct Source {
70 node_id: u16,
71 ieee_address: Option<IeeeAddress>,
72}
73
74impl Source {
75 #[must_use]
77 pub const fn new(node_id: u16, ieee_address: Option<IeeeAddress>) -> Self {
78 Self {
79 node_id,
80 ieee_address,
81 }
82 }
83
84 #[must_use]
86 pub const fn node_id(&self) -> u16 {
87 self.node_id
88 }
89
90 #[must_use]
92 pub const fn ieee_address(&self) -> Option<IeeeAddress> {
93 self.ieee_address
94 }
95
96 #[must_use]
98 pub const fn into_parts(self) -> (u16, Option<IeeeAddress>) {
99 (self.node_id, self.ieee_address)
100 }
101}
102
103#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
108#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
109pub struct Metadata {
110 last_hop_lqi: Option<u8>,
111 last_hop_rssi: Option<i16>,
112 binding_index: Option<usize>,
113 source_route_overhead: Option<u8>,
114}
115
116impl Metadata {
117 #[must_use]
119 pub const fn new(
120 last_hop_lqi: Option<u8>,
121 last_hop_rssi: Option<i16>,
122 binding_index: Option<usize>,
123 source_route_overhead: Option<u8>,
124 ) -> Self {
125 Self {
126 last_hop_lqi,
127 last_hop_rssi,
128 binding_index,
129 source_route_overhead,
130 }
131 }
132
133 #[must_use]
135 pub const fn last_hop_lqi(&self) -> Option<u8> {
136 self.last_hop_lqi
137 }
138
139 #[must_use]
141 pub const fn last_hop_rssi(&self) -> Option<i16> {
142 self.last_hop_rssi
143 }
144
145 #[must_use]
147 pub const fn binding_index(&self) -> Option<usize> {
148 self.binding_index
149 }
150
151 #[must_use]
153 pub const fn source_route_overhead(&self) -> Option<u8> {
154 self.source_route_overhead
155 }
156}
157
158macro_rules! impl_fmt_for_source {
159 ($($tr:path),+ $(,)?) => {
160 $(
161 impl $tr for Source {
162 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
163 <u16 as $tr>::fmt(&self.node_id, f)?;
164 f.write_str(" (")?;
165
166 if let Some(ieee_address) = self.ieee_address {
167 <IeeeAddress as $tr>::fmt(&ieee_address, f)?;
168 } else {
169 f.write_str("N/A")?;
170 }
171
172 f.write_str(")")
173 }
174 }
175 )+
176 }
177}
178
179impl_fmt_for_source! { Display, UpperHex, LowerHex }