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