1use core::{
15 convert::TryFrom,
16 fmt::{self, Debug},
17};
18
19use zenoh_buffers::ZBuf;
20
21pub mod iext {
58 use core::fmt;
59
60 pub const ID_BITS: u8 = 4;
61 pub const ID_MASK: u8 = !(u8::MAX << ID_BITS);
62
63 pub const FLAG_M: u8 = 1 << 4;
64 pub const ENC_UNIT: u8 = 0b00 << 5;
65 pub const ENC_Z64: u8 = 0b01 << 5;
66 pub const ENC_ZBUF: u8 = 0b10 << 5;
67 pub const ENC_MASK: u8 = 0b11 << 5;
68 pub const FLAG_Z: u8 = 1 << 7;
69
70 pub const fn eid(header: u8) -> u8 {
71 header & !FLAG_Z
72 }
73
74 pub const fn mid(header: u8) -> u8 {
75 header & ID_MASK
76 }
77
78 pub(super) const fn id(id: u8, mandatory: bool, encoding: u8) -> u8 {
79 let mut id = id & ID_MASK;
80 if mandatory {
81 id |= FLAG_M;
82 } else {
83 id &= !FLAG_M;
84 }
85 id |= encoding;
86 id
87 }
88
89 pub(super) const fn is_mandatory(id: u8) -> bool {
90 crate::common::imsg::has_flag(id, FLAG_M)
91 }
92
93 pub(super) fn fmt(f: &mut fmt::DebugStruct, id: u8) {
94 f.field("Id", &(id & ID_MASK))
95 .field("Mandatory", &is_mandatory(id))
96 .field(
97 "Encoding",
98 match id & ENC_MASK {
99 ENC_UNIT => &"Unit",
100 ENC_Z64 => &"Z64",
101 ENC_ZBUF => &"ZBuf",
102 _ => &"Unknown",
103 },
104 );
105 }
106}
107
108pub struct DidntConvert;
109
110#[repr(transparent)]
111#[derive(Clone, Copy, PartialEq, Eq)]
112pub struct ZExtUnit<const ID: u8>;
113
114impl<const ID: u8> Default for ZExtUnit<{ ID }> {
115 fn default() -> Self {
116 Self::new()
117 }
118}
119
120impl<const ID: u8> ZExtUnit<{ ID }> {
121 pub const ID: u8 = ID;
122
123 pub const fn new() -> Self {
124 Self
125 }
126
127 pub const fn id(mandatory: bool) -> u8 {
128 iext::id(ID, mandatory, iext::ENC_UNIT)
129 }
130
131 pub const fn is_mandatory(&self) -> bool {
132 iext::is_mandatory(ID)
133 }
134
135 pub const fn transmute<const DI: u8>(self) -> ZExtUnit<{ DI }> {
136 ZExtUnit::new()
137 }
138
139 #[cfg(feature = "test")]
140 pub fn rand() -> Self {
141 Self::new()
142 }
143}
144
145impl<const ID: u8> Debug for ZExtUnit<{ ID }> {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 let mut s = f.debug_struct("ZExtUnit");
148 iext::fmt(&mut s, ID);
149 s.finish()
150 }
151}
152
153impl<const ID: u8> TryFrom<ZExtUnknown> for ZExtUnit<{ ID }> {
154 type Error = DidntConvert;
155
156 fn try_from(v: ZExtUnknown) -> Result<Self, Self::Error> {
157 if v.id != ID {
158 return Err(DidntConvert);
159 }
160 match v.body {
161 ZExtBody::Unit => Ok(Self::new()),
162 _ => Err(DidntConvert),
163 }
164 }
165}
166
167#[repr(transparent)]
168#[derive(Clone, Copy, PartialEq, Eq)]
169pub struct ZExtZ64<const ID: u8> {
170 pub value: u64,
171}
172
173impl<const ID: u8> ZExtZ64<{ ID }> {
174 pub const ID: u8 = ID;
175
176 pub const fn new(value: u64) -> Self {
177 Self { value }
178 }
179
180 pub const fn id(mandatory: bool) -> u8 {
181 iext::id(ID, mandatory, iext::ENC_Z64)
182 }
183
184 pub const fn is_mandatory(&self) -> bool {
185 iext::is_mandatory(ID)
186 }
187
188 pub const fn transmute<const DI: u8>(self) -> ZExtZ64<{ DI }> {
189 ZExtZ64::new(self.value)
190 }
191
192 #[cfg(feature = "test")]
193 pub fn rand() -> Self {
194 use rand::Rng;
195
196 let mut rng = rand::thread_rng();
197 let value: u64 = rng.gen();
198 Self { value }
199 }
200}
201
202impl<const ID: u8> Debug for ZExtZ64<{ ID }> {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 let mut s = f.debug_struct("ZExtZ64");
205 iext::fmt(&mut s, ID);
206 s.field("Value", &self.value).finish()
207 }
208}
209
210impl<const ID: u8> TryFrom<ZExtUnknown> for ZExtZ64<{ ID }> {
211 type Error = DidntConvert;
212
213 fn try_from(v: ZExtUnknown) -> Result<Self, Self::Error> {
214 if v.id != ID {
215 return Err(DidntConvert);
216 }
217 match v.body {
218 ZExtBody::Z64(v) => Ok(Self::new(v)),
219 _ => Err(DidntConvert),
220 }
221 }
222}
223
224#[repr(transparent)]
225#[derive(Clone, PartialEq, Eq)]
226pub struct ZExtZBuf<const ID: u8> {
227 pub value: ZBuf,
228}
229
230impl<const ID: u8> ZExtZBuf<{ ID }> {
231 pub const ID: u8 = ID;
232
233 pub const fn new(value: ZBuf) -> Self {
234 Self { value }
235 }
236
237 pub const fn id(mandatory: bool) -> u8 {
238 iext::id(ID, mandatory, iext::ENC_ZBUF)
239 }
240
241 pub const fn is_mandatory(&self) -> bool {
242 iext::is_mandatory(ID)
243 }
244
245 pub fn transmute<const DI: u8>(self) -> ZExtZBuf<{ DI }> {
246 ZExtZBuf::new(self.value)
247 }
248
249 #[cfg(feature = "test")]
250 pub fn rand() -> Self {
251 use rand::Rng;
252
253 let mut rng = rand::thread_rng();
254 let value = ZBuf::rand(rng.gen_range(8..=64));
255 Self { value }
256 }
257}
258
259impl<const ID: u8> Debug for ZExtZBuf<{ ID }> {
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 let mut s = f.debug_struct("ZExtZBuf");
262 iext::fmt(&mut s, ID);
263 s.field("Value", &self.value).finish()
264 }
265}
266
267impl<const ID: u8> TryFrom<ZExtUnknown> for ZExtZBuf<{ ID }> {
268 type Error = DidntConvert;
269
270 fn try_from(v: ZExtUnknown) -> Result<Self, Self::Error> {
271 if v.id != ID {
272 return Err(DidntConvert);
273 }
274 match v.body {
275 ZExtBody::ZBuf(v) => Ok(Self::new(v)),
276 _ => Err(DidntConvert),
277 }
278 }
279}
280
281#[derive(Clone, PartialEq, Eq)]
282pub struct ZExtZBufHeader<const ID: u8> {
283 pub len: usize,
284}
285
286impl<const ID: u8> ZExtZBufHeader<{ ID }> {
287 pub const ID: u8 = ID;
288
289 pub const fn new(len: usize) -> Self {
290 Self { len }
291 }
292
293 pub const fn id(mandatory: bool) -> u8 {
294 iext::id(ID, mandatory, iext::ENC_ZBUF)
295 }
296
297 pub const fn is_mandatory(&self) -> bool {
298 iext::is_mandatory(ID)
299 }
300}
301
302impl<const ID: u8> Debug for ZExtZBufHeader<{ ID }> {
303 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 let mut s = f.debug_struct("ZExtZBufHeader");
305 iext::fmt(&mut s, ID);
306 s.field("Len", &self.len).finish()
307 }
308}
309
310#[derive(Debug, Clone, PartialEq, Eq)]
311pub enum ZExtBody {
312 Unit,
313 Z64(u64),
314 ZBuf(ZBuf),
315}
316
317impl ZExtBody {
318 #[cfg(feature = "test")]
319 pub fn rand() -> Self {
320 use rand::{seq::SliceRandom, Rng};
321 let mut rng = rand::thread_rng();
322 [
323 ZExtBody::Unit,
324 ZExtBody::Z64(rng.gen()),
325 ZExtBody::ZBuf(ZBuf::rand(rng.gen_range(8..=64))),
326 ]
327 .choose(&mut rng)
328 .unwrap()
329 .clone()
330 }
331}
332
333#[derive(Clone, PartialEq, Eq)]
334pub struct ZExtUnknown {
335 pub id: u8,
336 pub body: ZExtBody,
337}
338
339impl ZExtUnknown {
340 pub const fn new(id: u8, mandatory: bool, body: ZExtBody) -> Self {
341 let enc = match &body {
342 ZExtBody::Unit => iext::ENC_UNIT,
343 ZExtBody::Z64(_) => iext::ENC_Z64,
344 ZExtBody::ZBuf(_) => iext::ENC_ZBUF,
345 };
346 let id = iext::id(id, mandatory, enc);
347 Self { id, body }
348 }
349
350 pub const fn is_mandatory(&self) -> bool {
351 iext::is_mandatory(self.id)
352 }
353
354 #[cfg(feature = "test")]
355 pub fn rand() -> Self {
356 use rand::Rng;
357 let mut rng = rand::thread_rng();
358
359 let id: u8 = rng.gen_range(0x00..=iext::ID_MASK);
360 let mandatory = rng.gen_bool(0.5);
361 let body = ZExtBody::rand();
362 Self::new(id, mandatory, body)
363 }
364
365 #[cfg(feature = "test")]
366 pub fn rand2(start: u8, mandatory: bool) -> Self {
367 use rand::Rng;
368 let mut rng = rand::thread_rng();
369
370 let id: u8 = rng.gen_range(start..=iext::ID_MASK);
371 let body = ZExtBody::rand();
372 Self::new(id, mandatory, body)
373 }
374}
375
376impl Debug for ZExtUnknown {
377 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378 let mut s = f.debug_struct("ZExtUnknown");
379 iext::fmt(&mut s, self.id);
380 match &self.body {
381 ZExtBody::Unit => {}
382 ZExtBody::Z64(v) => {
383 s.field("Value", v);
384 }
385 ZExtBody::ZBuf(v) => {
386 s.field("Value", v);
387 }
388 };
389 s.finish()
390 }
391}
392
393impl<const ID: u8> From<ZExtUnit<{ ID }>> for ZExtUnknown {
394 fn from(_: ZExtUnit<{ ID }>) -> Self {
395 ZExtUnknown {
396 id: ID,
397 body: ZExtBody::Unit,
398 }
399 }
400}
401
402impl<const ID: u8> From<ZExtZ64<{ ID }>> for ZExtUnknown {
403 fn from(e: ZExtZ64<{ ID }>) -> Self {
404 ZExtUnknown {
405 id: ID,
406 body: ZExtBody::Z64(e.value),
407 }
408 }
409}
410
411impl<const ID: u8> From<ZExtZBuf<{ ID }>> for ZExtUnknown {
412 fn from(e: ZExtZBuf<{ ID }>) -> Self {
413 ZExtUnknown {
414 id: ID,
415 body: ZExtBody::ZBuf(e.value),
416 }
417 }
418}
419
420#[macro_export]
422macro_rules! zextunit {
423 ($id:expr, $m:expr) => {
424 ZExtUnit<{ ZExtUnit::<$id>::id($m) }>
425 }
426}
427
428#[macro_export]
429macro_rules! zextz64 {
430 ($id:expr, $m:expr) => {
431 ZExtZ64<{ ZExtZ64::<$id>::id($m) }>
432 }
433}
434
435#[macro_export]
436macro_rules! zextzbuf {
437 ($id:expr, $m:expr) => {
438 ZExtZBuf<{ ZExtZBuf::<$id>::id($m) }>
439 }
440}