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 #[doc(hidden)]
141 pub fn rand() -> Self {
142 Self::new()
143 }
144}
145
146impl<const ID: u8> Debug for ZExtUnit<{ ID }> {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 let mut s = f.debug_struct("ZExtUnit");
149 iext::fmt(&mut s, ID);
150 s.finish()
151 }
152}
153
154impl<const ID: u8> TryFrom<ZExtUnknown> for ZExtUnit<{ ID }> {
155 type Error = DidntConvert;
156
157 fn try_from(v: ZExtUnknown) -> Result<Self, Self::Error> {
158 if v.id != ID {
159 return Err(DidntConvert);
160 }
161 match v.body {
162 ZExtBody::Unit => Ok(Self::new()),
163 _ => Err(DidntConvert),
164 }
165 }
166}
167
168#[repr(transparent)]
169#[derive(Clone, Copy, PartialEq, Eq)]
170pub struct ZExtZ64<const ID: u8> {
171 pub value: u64,
172}
173
174impl<const ID: u8> ZExtZ64<{ ID }> {
175 pub const ID: u8 = ID;
176
177 pub const fn new(value: u64) -> Self {
178 Self { value }
179 }
180
181 pub const fn id(mandatory: bool) -> u8 {
182 iext::id(ID, mandatory, iext::ENC_Z64)
183 }
184
185 pub const fn is_mandatory(&self) -> bool {
186 iext::is_mandatory(ID)
187 }
188
189 pub const fn transmute<const DI: u8>(self) -> ZExtZ64<{ DI }> {
190 ZExtZ64::new(self.value)
191 }
192
193 #[cfg(feature = "test")]
194 #[doc(hidden)]
195 pub fn rand() -> Self {
196 use rand::Rng;
197
198 let mut rng = rand::thread_rng();
199 let value: u64 = rng.gen();
200 Self { value }
201 }
202}
203
204impl<const ID: u8> Debug for ZExtZ64<{ ID }> {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 let mut s = f.debug_struct("ZExtZ64");
207 iext::fmt(&mut s, ID);
208 s.field("Value", &self.value).finish()
209 }
210}
211
212impl<const ID: u8> TryFrom<ZExtUnknown> for ZExtZ64<{ ID }> {
213 type Error = DidntConvert;
214
215 fn try_from(v: ZExtUnknown) -> Result<Self, Self::Error> {
216 if v.id != ID {
217 return Err(DidntConvert);
218 }
219 match v.body {
220 ZExtBody::Z64(v) => Ok(Self::new(v)),
221 _ => Err(DidntConvert),
222 }
223 }
224}
225
226#[repr(transparent)]
227#[derive(Clone, PartialEq, Eq)]
228pub struct ZExtZBuf<const ID: u8> {
229 pub value: ZBuf,
230}
231
232impl<const ID: u8> ZExtZBuf<{ ID }> {
233 pub const ID: u8 = ID;
234
235 pub const fn new(value: ZBuf) -> Self {
236 Self { value }
237 }
238
239 pub const fn id(mandatory: bool) -> u8 {
240 iext::id(ID, mandatory, iext::ENC_ZBUF)
241 }
242
243 pub const fn is_mandatory(&self) -> bool {
244 iext::is_mandatory(ID)
245 }
246
247 pub fn transmute<const DI: u8>(self) -> ZExtZBuf<{ DI }> {
248 ZExtZBuf::new(self.value)
249 }
250
251 #[cfg(feature = "test")]
252 #[doc(hidden)]
253 pub fn rand() -> Self {
254 use rand::Rng;
255
256 let mut rng = rand::thread_rng();
257 let value = ZBuf::rand(rng.gen_range(8..=64));
258 Self { value }
259 }
260}
261
262impl<const ID: u8> Debug for ZExtZBuf<{ ID }> {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 let mut s = f.debug_struct("ZExtZBuf");
265 iext::fmt(&mut s, ID);
266 s.field("Value", &self.value).finish()
267 }
268}
269
270impl<const ID: u8> TryFrom<ZExtUnknown> for ZExtZBuf<{ ID }> {
271 type Error = DidntConvert;
272
273 fn try_from(v: ZExtUnknown) -> Result<Self, Self::Error> {
274 if v.id != ID {
275 return Err(DidntConvert);
276 }
277 match v.body {
278 ZExtBody::ZBuf(v) => Ok(Self::new(v)),
279 _ => Err(DidntConvert),
280 }
281 }
282}
283
284#[derive(Clone, PartialEq, Eq)]
285pub struct ZExtZBufHeader<const ID: u8> {
286 pub len: usize,
287}
288
289impl<const ID: u8> ZExtZBufHeader<{ ID }> {
290 pub const ID: u8 = ID;
291
292 pub const fn new(len: usize) -> Self {
293 Self { len }
294 }
295
296 pub const fn id(mandatory: bool) -> u8 {
297 iext::id(ID, mandatory, iext::ENC_ZBUF)
298 }
299
300 pub const fn is_mandatory(&self) -> bool {
301 iext::is_mandatory(ID)
302 }
303}
304
305impl<const ID: u8> Debug for ZExtZBufHeader<{ ID }> {
306 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
307 let mut s = f.debug_struct("ZExtZBufHeader");
308 iext::fmt(&mut s, ID);
309 s.field("Len", &self.len).finish()
310 }
311}
312
313#[derive(Debug, Default, Clone, PartialEq, Eq)]
314pub enum ZExtBody {
315 #[default]
316 Unit,
317 Z64(u64),
318 ZBuf(ZBuf),
319}
320
321impl ZExtBody {
322 #[cfg(feature = "test")]
323 #[doc(hidden)]
324 pub fn rand() -> Self {
325 use rand::{seq::SliceRandom, Rng};
326 let mut rng = rand::thread_rng();
327 [
328 ZExtBody::Unit,
329 ZExtBody::Z64(rng.gen()),
330 ZExtBody::ZBuf(ZBuf::rand(rng.gen_range(8..=64))),
331 ]
332 .choose(&mut rng)
333 .unwrap()
334 .clone()
335 }
336}
337
338#[derive(Clone, PartialEq, Eq)]
339pub struct ZExtUnknown {
340 pub id: u8,
341 pub body: ZExtBody,
342}
343
344impl ZExtUnknown {
345 pub const fn new(id: u8, mandatory: bool, body: ZExtBody) -> Self {
346 let enc = match &body {
347 ZExtBody::Unit => iext::ENC_UNIT,
348 ZExtBody::Z64(_) => iext::ENC_Z64,
349 ZExtBody::ZBuf(_) => iext::ENC_ZBUF,
350 };
351 let id = iext::id(id, mandatory, enc);
352 Self { id, body }
353 }
354
355 pub const fn is_mandatory(&self) -> bool {
356 iext::is_mandatory(self.id)
357 }
358
359 #[cfg(feature = "test")]
360 #[doc(hidden)]
361 pub fn rand() -> Self {
362 use rand::Rng;
363 let mut rng = rand::thread_rng();
364
365 let id: u8 = rng.gen_range(0x00..=iext::ID_MASK);
366 let mandatory = rng.gen_bool(0.5);
367 let body = ZExtBody::rand();
368 Self::new(id, mandatory, body)
369 }
370
371 #[cfg(feature = "test")]
372 #[doc(hidden)]
373 pub fn rand2(start: u8, mandatory: bool) -> Self {
374 use rand::Rng;
375 let mut rng = rand::thread_rng();
376
377 let id: u8 = rng.gen_range(start..=iext::ID_MASK);
378 let body = ZExtBody::rand();
379 Self::new(id, mandatory, body)
380 }
381}
382
383impl Debug for ZExtUnknown {
384 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385 let mut s = f.debug_struct("ZExtUnknown");
386 iext::fmt(&mut s, self.id);
387 match &self.body {
388 ZExtBody::Unit => {}
389 ZExtBody::Z64(v) => {
390 s.field("Value", v);
391 }
392 ZExtBody::ZBuf(v) => {
393 s.field("Value", v);
394 }
395 };
396 s.finish()
397 }
398}
399
400impl<const ID: u8> From<ZExtUnit<{ ID }>> for ZExtUnknown {
401 fn from(_: ZExtUnit<{ ID }>) -> Self {
402 ZExtUnknown {
403 id: ID,
404 body: ZExtBody::Unit,
405 }
406 }
407}
408
409impl<const ID: u8> From<ZExtZ64<{ ID }>> for ZExtUnknown {
410 fn from(e: ZExtZ64<{ ID }>) -> Self {
411 ZExtUnknown {
412 id: ID,
413 body: ZExtBody::Z64(e.value),
414 }
415 }
416}
417
418impl<const ID: u8> From<ZExtZBuf<{ ID }>> for ZExtUnknown {
419 fn from(e: ZExtZBuf<{ ID }>) -> Self {
420 ZExtUnknown {
421 id: ID,
422 body: ZExtBody::ZBuf(e.value),
423 }
424 }
425}
426
427#[macro_export]
429macro_rules! zextunit {
430 ($id:expr, $m:expr) => {
431 ZExtUnit<{ ZExtUnit::<$id>::id($m) }>
432 }
433}
434
435#[macro_export]
436macro_rules! zextz64 {
437 ($id:expr, $m:expr) => {
438 ZExtZ64<{ ZExtZ64::<$id>::id($m) }>
439 }
440}
441
442#[macro_export]
443macro_rules! zextzbuf {
444 ($id:expr, $m:expr) => {
445 ZExtZBuf<{ ZExtZBuf::<$id>::id($m) }>
446 }
447}