zenoh_protocol/network/
mod.rs

1//
2// Copyright (c) 2022 ZettaScale Technology
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8//
9// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10//
11// Contributors:
12//   ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13//
14pub mod declare;
15pub mod interest;
16pub mod oam;
17pub mod push;
18pub mod request;
19pub mod response;
20
21use core::fmt;
22
23pub use declare::{
24    Declare, DeclareBody, DeclareFinal, DeclareKeyExpr, DeclareQueryable, DeclareSubscriber,
25    DeclareToken, UndeclareKeyExpr, UndeclareQueryable, UndeclareSubscriber, UndeclareToken,
26};
27pub use interest::Interest;
28pub use oam::Oam;
29pub use push::Push;
30pub use request::{AtomicRequestId, Request, RequestId};
31pub use response::{Response, ResponseFinal};
32
33use crate::core::{CongestionControl, Priority, Reliability, WireExpr};
34#[cfg(feature = "shared-memory")]
35use crate::zenoh::{PushBody, RequestBody, ResponseBody};
36
37pub mod id {
38    // WARNING: it's crucial that these IDs do NOT collide with the IDs
39    //          defined in `crate::transport::id`.
40    pub const OAM: u8 = 0x1f;
41    pub const DECLARE: u8 = 0x1e;
42    pub const PUSH: u8 = 0x1d;
43    pub const REQUEST: u8 = 0x1c;
44    pub const RESPONSE: u8 = 0x1b;
45    pub const RESPONSE_FINAL: u8 = 0x1a;
46    pub const INTEREST: u8 = 0x19;
47}
48
49#[repr(u8)]
50#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)]
51pub enum Mapping {
52    #[default]
53    Receiver = 0,
54    Sender = 1,
55}
56
57impl Mapping {
58    pub const DEFAULT: Self = Self::Receiver;
59
60    #[cfg(feature = "test")]
61    #[doc(hidden)]
62    pub fn rand() -> Self {
63        use rand::Rng;
64
65        let mut rng = rand::thread_rng();
66        if rng.gen_bool(0.5) {
67            Mapping::Sender
68        } else {
69            Mapping::Receiver
70        }
71    }
72}
73
74// Zenoh messages at zenoh-network level
75#[derive(Debug, Clone, PartialEq, Eq)]
76pub enum NetworkBody {
77    Push(Push),
78    Request(Request),
79    Response(Response),
80    ResponseFinal(ResponseFinal),
81    Interest(Interest),
82    Declare(Declare),
83    OAM(Oam),
84}
85
86#[derive(Debug, Copy, Clone, PartialEq, Eq)]
87pub enum NetworkBodyRef<'a> {
88    Push(&'a Push),
89    Request(&'a Request),
90    Response(&'a Response),
91    ResponseFinal(&'a ResponseFinal),
92    Interest(&'a Interest),
93    Declare(&'a Declare),
94    OAM(&'a Oam),
95}
96
97#[derive(Debug, PartialEq, Eq)]
98pub enum NetworkBodyMut<'a> {
99    Push(&'a mut Push),
100    Request(&'a mut Request),
101    Response(&'a mut Response),
102    ResponseFinal(&'a mut ResponseFinal),
103    Interest(&'a mut Interest),
104    Declare(&'a mut Declare),
105    OAM(&'a mut Oam),
106}
107
108#[derive(Debug, Clone, PartialEq, Eq)]
109pub struct NetworkMessage {
110    pub body: NetworkBody,
111    pub reliability: Reliability,
112}
113
114#[derive(Debug, Copy, Clone, PartialEq, Eq)]
115pub struct NetworkMessageRef<'a> {
116    pub body: NetworkBodyRef<'a>,
117    pub reliability: Reliability,
118}
119
120#[derive(Debug, PartialEq, Eq)]
121pub struct NetworkMessageMut<'a> {
122    pub body: NetworkBodyMut<'a>,
123    pub reliability: Reliability,
124}
125
126pub trait NetworkMessageExt {
127    #[doc(hidden)]
128    fn body(&self) -> NetworkBodyRef<'_>;
129
130    #[doc(hidden)]
131    fn reliability(&self) -> Reliability;
132
133    #[inline]
134    fn is_reliable(&self) -> bool {
135        self.reliability() == Reliability::Reliable
136    }
137
138    #[inline]
139    fn is_express(&self) -> bool {
140        match self.body() {
141            NetworkBodyRef::Push(msg) => msg.ext_qos.is_express(),
142            NetworkBodyRef::Request(msg) => msg.ext_qos.is_express(),
143            NetworkBodyRef::Response(msg) => msg.ext_qos.is_express(),
144            NetworkBodyRef::ResponseFinal(msg) => msg.ext_qos.is_express(),
145            NetworkBodyRef::Interest(msg) => msg.ext_qos.is_express(),
146            NetworkBodyRef::Declare(msg) => msg.ext_qos.is_express(),
147            NetworkBodyRef::OAM(msg) => msg.ext_qos.is_express(),
148        }
149    }
150
151    #[inline]
152    fn congestion_control(&self) -> CongestionControl {
153        match self.body() {
154            NetworkBodyRef::Push(msg) => msg.ext_qos.get_congestion_control(),
155            NetworkBodyRef::Request(msg) => msg.ext_qos.get_congestion_control(),
156            NetworkBodyRef::Response(msg) => msg.ext_qos.get_congestion_control(),
157            NetworkBodyRef::ResponseFinal(msg) => msg.ext_qos.get_congestion_control(),
158            NetworkBodyRef::Interest(msg) => msg.ext_qos.get_congestion_control(),
159            NetworkBodyRef::Declare(msg) => msg.ext_qos.get_congestion_control(),
160            NetworkBodyRef::OAM(msg) => msg.ext_qos.get_congestion_control(),
161        }
162    }
163
164    #[inline]
165    #[cfg(feature = "shared-memory")]
166    fn is_shm(&self) -> bool {
167        match self.body() {
168            NetworkBodyRef::Push(Push { payload, .. }) => match payload {
169                PushBody::Put(p) => p.ext_shm.is_some(),
170                PushBody::Del(_) => false,
171            },
172            NetworkBodyRef::Request(Request { payload, .. }) => match payload {
173                RequestBody::Query(b) => b.ext_body.as_ref().is_some_and(|b| b.ext_shm.is_some()),
174            },
175            NetworkBodyRef::Response(Response { payload, .. }) => match payload {
176                ResponseBody::Reply(b) => match &b.payload {
177                    PushBody::Put(p) => p.ext_shm.is_some(),
178                    PushBody::Del(_) => false,
179                },
180                ResponseBody::Err(e) => e.ext_shm.is_some(),
181            },
182            NetworkBodyRef::ResponseFinal(_)
183            | NetworkBodyRef::Interest(_)
184            | NetworkBodyRef::Declare(_)
185            | NetworkBodyRef::OAM(_) => false,
186        }
187    }
188
189    #[inline]
190    fn is_droppable(&self) -> bool {
191        !self.is_reliable() || self.congestion_control() == CongestionControl::Drop
192    }
193
194    #[inline]
195    fn priority(&self) -> Priority {
196        match self.body() {
197            NetworkBodyRef::Push(msg) => msg.ext_qos.get_priority(),
198            NetworkBodyRef::Request(msg) => msg.ext_qos.get_priority(),
199            NetworkBodyRef::Response(msg) => msg.ext_qos.get_priority(),
200            NetworkBodyRef::ResponseFinal(msg) => msg.ext_qos.get_priority(),
201            NetworkBodyRef::Interest(msg) => msg.ext_qos.get_priority(),
202            NetworkBodyRef::Declare(msg) => msg.ext_qos.get_priority(),
203            NetworkBodyRef::OAM(msg) => msg.ext_qos.get_priority(),
204        }
205    }
206
207    #[inline]
208    fn wire_expr(&self) -> Option<&WireExpr<'_>> {
209        match &self.body() {
210            NetworkBodyRef::Push(m) => Some(&m.wire_expr),
211            NetworkBodyRef::Request(m) => Some(&m.wire_expr),
212            NetworkBodyRef::Response(m) => Some(&m.wire_expr),
213            NetworkBodyRef::ResponseFinal(_) => None,
214            NetworkBodyRef::Interest(m) => m.wire_expr.as_ref(),
215            NetworkBodyRef::Declare(m) => match &m.body {
216                DeclareBody::DeclareKeyExpr(m) => Some(&m.wire_expr),
217                DeclareBody::UndeclareKeyExpr(_) => None,
218                DeclareBody::DeclareSubscriber(m) => Some(&m.wire_expr),
219                DeclareBody::UndeclareSubscriber(m) => Some(&m.ext_wire_expr.wire_expr),
220                DeclareBody::DeclareQueryable(m) => Some(&m.wire_expr),
221                DeclareBody::UndeclareQueryable(m) => Some(&m.ext_wire_expr.wire_expr),
222                DeclareBody::DeclareToken(m) => Some(&m.wire_expr),
223                DeclareBody::UndeclareToken(m) => Some(&m.ext_wire_expr.wire_expr),
224                DeclareBody::DeclareFinal(_) => None,
225            },
226            NetworkBodyRef::OAM(_) => None,
227        }
228    }
229
230    #[inline]
231    fn payload_size(&self) -> Option<usize> {
232        match &self.body() {
233            NetworkBodyRef::Push(p) => Some(p.payload_size()),
234            NetworkBodyRef::Request(r) => Some(r.payload_size()),
235            NetworkBodyRef::Response(r) => Some(r.payload_size()),
236            NetworkBodyRef::ResponseFinal(_)
237            | NetworkBodyRef::Interest(_)
238            | NetworkBodyRef::Declare(_)
239            | NetworkBodyRef::OAM(_) => None,
240        }
241    }
242
243    #[inline]
244    fn as_ref(&self) -> NetworkMessageRef<'_> {
245        NetworkMessageRef {
246            body: self.body(),
247            reliability: self.reliability(),
248        }
249    }
250
251    #[inline]
252    fn to_owned(&self) -> NetworkMessage {
253        NetworkMessage {
254            body: match self.body() {
255                NetworkBodyRef::Push(msg) => NetworkBody::Push(msg.clone()),
256                NetworkBodyRef::Request(msg) => NetworkBody::Request(msg.clone()),
257                NetworkBodyRef::Response(msg) => NetworkBody::Response(msg.clone()),
258                NetworkBodyRef::ResponseFinal(msg) => NetworkBody::ResponseFinal(msg.clone()),
259                NetworkBodyRef::Interest(msg) => NetworkBody::Interest(msg.clone()),
260                NetworkBodyRef::Declare(msg) => NetworkBody::Declare(msg.clone()),
261                NetworkBodyRef::OAM(msg) => NetworkBody::OAM(msg.clone()),
262            },
263            reliability: self.reliability(),
264        }
265    }
266}
267
268impl<M: NetworkMessageExt> NetworkMessageExt for &M {
269    fn body(&self) -> NetworkBodyRef<'_> {
270        (**self).body()
271    }
272
273    fn reliability(&self) -> Reliability {
274        (**self).reliability()
275    }
276}
277
278impl<M: NetworkMessageExt> NetworkMessageExt for &mut M {
279    fn body(&self) -> NetworkBodyRef<'_> {
280        (**self).body()
281    }
282
283    fn reliability(&self) -> Reliability {
284        (**self).reliability()
285    }
286}
287
288impl NetworkMessageExt for NetworkMessage {
289    fn body(&self) -> NetworkBodyRef<'_> {
290        match &self.body {
291            NetworkBody::Push(body) => NetworkBodyRef::Push(body),
292            NetworkBody::Request(body) => NetworkBodyRef::Request(body),
293            NetworkBody::Response(body) => NetworkBodyRef::Response(body),
294            NetworkBody::ResponseFinal(body) => NetworkBodyRef::ResponseFinal(body),
295            NetworkBody::Interest(body) => NetworkBodyRef::Interest(body),
296            NetworkBody::Declare(body) => NetworkBodyRef::Declare(body),
297            NetworkBody::OAM(body) => NetworkBodyRef::OAM(body),
298        }
299    }
300
301    fn reliability(&self) -> Reliability {
302        self.reliability
303    }
304}
305
306impl NetworkMessageExt for NetworkMessageRef<'_> {
307    fn body(&self) -> NetworkBodyRef<'_> {
308        self.body
309    }
310
311    fn reliability(&self) -> Reliability {
312        self.reliability
313    }
314}
315
316impl NetworkMessageExt for NetworkMessageMut<'_> {
317    fn body(&self) -> NetworkBodyRef<'_> {
318        match &self.body {
319            NetworkBodyMut::Push(body) => NetworkBodyRef::Push(body),
320            NetworkBodyMut::Request(body) => NetworkBodyRef::Request(body),
321            NetworkBodyMut::Response(body) => NetworkBodyRef::Response(body),
322            NetworkBodyMut::ResponseFinal(body) => NetworkBodyRef::ResponseFinal(body),
323            NetworkBodyMut::Interest(body) => NetworkBodyRef::Interest(body),
324            NetworkBodyMut::Declare(body) => NetworkBodyRef::Declare(body),
325            NetworkBodyMut::OAM(body) => NetworkBodyRef::OAM(body),
326        }
327    }
328
329    fn reliability(&self) -> Reliability {
330        self.reliability
331    }
332}
333
334impl NetworkMessage {
335    #[cfg(feature = "test")]
336    #[doc(hidden)]
337    pub fn rand() -> Self {
338        use rand::Rng;
339
340        let mut rng = rand::thread_rng();
341
342        let body = match rng.gen_range(0..6) {
343            0 => NetworkBody::Push(Push::rand()),
344            1 => NetworkBody::Request(Request::rand()),
345            2 => NetworkBody::Response(Response::rand()),
346            3 => NetworkBody::ResponseFinal(ResponseFinal::rand()),
347            4 => NetworkBody::Declare(Declare::rand()),
348            5 => NetworkBody::OAM(Oam::rand()),
349            _ => unreachable!(),
350        };
351
352        body.into()
353    }
354
355    #[inline]
356    pub fn as_mut(&mut self) -> NetworkMessageMut<'_> {
357        let body = match &mut self.body {
358            NetworkBody::Push(body) => NetworkBodyMut::Push(body),
359            NetworkBody::Request(body) => NetworkBodyMut::Request(body),
360            NetworkBody::Response(body) => NetworkBodyMut::Response(body),
361            NetworkBody::ResponseFinal(body) => NetworkBodyMut::ResponseFinal(body),
362            NetworkBody::Interest(body) => NetworkBodyMut::Interest(body),
363            NetworkBody::Declare(body) => NetworkBodyMut::Declare(body),
364            NetworkBody::OAM(body) => NetworkBodyMut::OAM(body),
365        };
366        NetworkMessageMut {
367            body,
368            reliability: self.reliability,
369        }
370    }
371}
372
373impl NetworkMessageMut<'_> {
374    #[inline]
375    pub fn as_mut(&mut self) -> NetworkMessageMut<'_> {
376        let body = match &mut self.body {
377            NetworkBodyMut::Push(body) => NetworkBodyMut::Push(body),
378            NetworkBodyMut::Request(body) => NetworkBodyMut::Request(body),
379            NetworkBodyMut::Response(body) => NetworkBodyMut::Response(body),
380            NetworkBodyMut::ResponseFinal(body) => NetworkBodyMut::ResponseFinal(body),
381            NetworkBodyMut::Interest(body) => NetworkBodyMut::Interest(body),
382            NetworkBodyMut::Declare(body) => NetworkBodyMut::Declare(body),
383            NetworkBodyMut::OAM(body) => NetworkBodyMut::OAM(body),
384        };
385        NetworkMessageMut {
386            body,
387            reliability: self.reliability,
388        }
389    }
390}
391
392impl fmt::Display for NetworkMessageRef<'_> {
393    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
394        match &self.body {
395            NetworkBodyRef::OAM(_) => write!(f, "OAM"),
396            NetworkBodyRef::Push(_) => write!(f, "Push"),
397            NetworkBodyRef::Request(_) => write!(f, "Request"),
398            NetworkBodyRef::Response(_) => write!(f, "Response"),
399            NetworkBodyRef::ResponseFinal(_) => write!(f, "ResponseFinal"),
400            NetworkBodyRef::Interest(_) => write!(f, "Interest"),
401            NetworkBodyRef::Declare(_) => write!(f, "Declare"),
402        }
403    }
404}
405
406impl fmt::Display for NetworkMessage {
407    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
408        self.as_ref().fmt(f)
409    }
410}
411
412impl fmt::Display for NetworkMessageMut<'_> {
413    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
414        self.as_ref().fmt(f)
415    }
416}
417
418impl From<NetworkBody> for NetworkMessage {
419    #[inline]
420    fn from(body: NetworkBody) -> Self {
421        Self {
422            body,
423            reliability: Reliability::DEFAULT,
424        }
425    }
426}
427
428#[cfg(feature = "test")]
429impl From<Push> for NetworkMessage {
430    fn from(push: Push) -> Self {
431        NetworkBody::Push(push).into()
432    }
433}
434
435// Extensions
436pub mod ext {
437    use core::fmt;
438
439    use crate::{
440        common::{imsg, ZExtZ64},
441        core::{CongestionControl, EntityId, Priority, ZenohIdProto},
442    };
443
444    /// ```text
445    ///  7 6 5 4 3 2 1 0
446    /// +-+-+-+-+-+-+-+-+
447    /// |Z|0_1|    ID   |
448    /// +-+-+-+---------+
449    /// %0|r|F|E|D|prio %
450    /// +---------------+
451    ///
452    /// - prio: Priority class
453    /// - D:    Don't drop. Don't drop the message for congestion control.
454    /// - E:    Express. Don't batch this message.
455    /// - F:    Don't drop the first message for congestion control.
456    /// - r:  Reserved
457    /// ```
458    #[repr(transparent)]
459    #[derive(Clone, Copy, PartialEq, Eq)]
460    pub struct QoSType<const ID: u8> {
461        inner: u8,
462    }
463
464    impl<const ID: u8> QoSType<{ ID }> {
465        const P_MASK: u8 = 0b00000111;
466        const D_FLAG: u8 = 0b00001000;
467        const E_FLAG: u8 = 0b00010000;
468        const F_FLAG: u8 = 0b00100000;
469
470        pub const DEFAULT: Self = Self::new(Priority::DEFAULT, CongestionControl::DEFAULT, false);
471
472        pub const DECLARE: Self =
473            Self::new(Priority::Control, CongestionControl::DEFAULT_DECLARE, false);
474        pub const PUSH: Self = Self::new(Priority::DEFAULT, CongestionControl::DEFAULT_PUSH, false);
475        pub const REQUEST: Self =
476            Self::new(Priority::DEFAULT, CongestionControl::DEFAULT_REQUEST, false);
477        pub const RESPONSE: Self = Self::new(
478            Priority::DEFAULT,
479            CongestionControl::DEFAULT_RESPONSE,
480            false,
481        );
482        pub const RESPONSE_FINAL: Self = Self::new(
483            Priority::DEFAULT,
484            CongestionControl::DEFAULT_RESPONSE,
485            false,
486        );
487        pub const OAM: Self = Self::new(Priority::Control, CongestionControl::DEFAULT_OAM, false);
488
489        pub const fn new(
490            priority: Priority,
491            congestion_control: CongestionControl,
492            is_express: bool,
493        ) -> Self {
494            let mut inner = priority as u8;
495            match congestion_control {
496                CongestionControl::Block => inner |= Self::D_FLAG,
497                #[cfg(feature = "unstable")]
498                CongestionControl::BlockFirst => inner |= Self::F_FLAG,
499                _ => {}
500            }
501            if is_express {
502                inner |= Self::E_FLAG;
503            }
504            Self { inner }
505        }
506
507        pub fn set_priority(&mut self, priority: Priority) {
508            self.inner = imsg::set_bitfield(self.inner, priority as u8, Self::P_MASK);
509        }
510
511        pub const fn get_priority(&self) -> Priority {
512            unsafe { core::mem::transmute(self.inner & Self::P_MASK) }
513        }
514
515        pub fn set_congestion_control(&mut self, cctrl: CongestionControl) {
516            match cctrl {
517                CongestionControl::Block => {
518                    self.inner = imsg::set_flag(self.inner, Self::D_FLAG);
519                    self.inner = imsg::unset_flag(self.inner, Self::F_FLAG);
520                }
521                CongestionControl::Drop => {
522                    self.inner = imsg::unset_flag(self.inner, Self::D_FLAG);
523                    self.inner = imsg::unset_flag(self.inner, Self::F_FLAG);
524                }
525                #[cfg(feature = "unstable")]
526                CongestionControl::BlockFirst => {
527                    self.inner = imsg::unset_flag(self.inner, Self::D_FLAG);
528                    self.inner = imsg::set_flag(self.inner, Self::F_FLAG);
529                }
530            }
531        }
532
533        pub const fn get_congestion_control(&self) -> CongestionControl {
534            match (
535                imsg::has_flag(self.inner, Self::D_FLAG),
536                imsg::has_flag(self.inner, Self::F_FLAG),
537            ) {
538                (false, false) => CongestionControl::Drop,
539                #[cfg(feature = "unstable")]
540                (false, true) => CongestionControl::BlockFirst,
541                #[cfg(not(feature = "unstable"))]
542                (false, true) => CongestionControl::Drop,
543                (true, _) => CongestionControl::Block,
544            }
545        }
546
547        pub fn set_is_express(&mut self, is_express: bool) {
548            match is_express {
549                true => self.inner = imsg::set_flag(self.inner, Self::E_FLAG),
550                false => self.inner = imsg::unset_flag(self.inner, Self::E_FLAG),
551            }
552        }
553
554        pub const fn is_express(&self) -> bool {
555            imsg::has_flag(self.inner, Self::E_FLAG)
556        }
557
558        #[cfg(feature = "test")]
559        #[doc(hidden)]
560        pub fn rand() -> Self {
561            use rand::Rng;
562            let mut rng = rand::thread_rng();
563
564            let inner: u8 = rng.gen();
565            Self { inner }
566        }
567    }
568
569    impl<const ID: u8> Default for QoSType<{ ID }> {
570        fn default() -> Self {
571            Self::new(Priority::DEFAULT, CongestionControl::DEFAULT, false)
572        }
573    }
574
575    impl<const ID: u8> From<ZExtZ64<{ ID }>> for QoSType<{ ID }> {
576        fn from(ext: ZExtZ64<{ ID }>) -> Self {
577            Self {
578                inner: ext.value as u8,
579            }
580        }
581    }
582
583    impl<const ID: u8> From<QoSType<{ ID }>> for ZExtZ64<{ ID }> {
584        fn from(ext: QoSType<{ ID }>) -> Self {
585            ZExtZ64::new(ext.inner as u64)
586        }
587    }
588
589    impl<const ID: u8> fmt::Debug for QoSType<{ ID }> {
590        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
591            f.debug_struct("QoS")
592                .field("priority", &self.get_priority())
593                .field("congestion", &self.get_congestion_control())
594                .field("express", &self.is_express())
595                .finish()
596        }
597    }
598
599    /// ```text
600    ///  7 6 5 4 3 2 1 0
601    /// +-+-+-+-+-+-+-+-+
602    /// |Z|1_0|    ID   |
603    /// +-+-+-+---------+
604    /// ~ ts: <u8;z16>  ~
605    /// +---------------+
606    /// ```
607    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
608    pub struct TimestampType<const ID: u8> {
609        pub timestamp: uhlc::Timestamp,
610    }
611
612    impl<const ID: u8> TimestampType<{ ID }> {
613        #[cfg(feature = "test")]
614        #[doc(hidden)]
615        pub fn rand() -> Self {
616            use rand::Rng;
617            let mut rng = rand::thread_rng();
618
619            let time = uhlc::NTP64(rng.gen());
620            let id = uhlc::ID::try_from(ZenohIdProto::rand().to_le_bytes()).unwrap();
621            let timestamp = uhlc::Timestamp::new(time, id);
622            Self { timestamp }
623        }
624    }
625
626    /// ```text
627    ///  7 6 5 4 3 2 1 0
628    /// +-+-+-+-+-+-+-+-+
629    /// |Z|0_1|    ID   |
630    /// +-+-+-+---------+
631    /// %    node_id    %
632    /// +---------------+
633    /// ```
634    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
635    pub struct NodeIdType<const ID: u8> {
636        pub node_id: u16,
637    }
638
639    impl<const ID: u8> NodeIdType<{ ID }> {
640        // node_id == 0 means the message has been generated by the node itself
641        pub const DEFAULT: Self = Self { node_id: 0 };
642
643        #[cfg(feature = "test")]
644        #[doc(hidden)]
645        pub fn rand() -> Self {
646            use rand::Rng;
647            let mut rng = rand::thread_rng();
648            let node_id = rng.gen();
649            Self { node_id }
650        }
651    }
652
653    impl<const ID: u8> Default for NodeIdType<{ ID }> {
654        fn default() -> Self {
655            Self::DEFAULT
656        }
657    }
658
659    impl<const ID: u8> From<ZExtZ64<{ ID }>> for NodeIdType<{ ID }> {
660        fn from(ext: ZExtZ64<{ ID }>) -> Self {
661            Self {
662                node_id: ext.value as u16,
663            }
664        }
665    }
666
667    impl<const ID: u8> From<NodeIdType<{ ID }>> for ZExtZ64<{ ID }> {
668        fn from(ext: NodeIdType<{ ID }>) -> Self {
669            ZExtZ64::new(ext.node_id as u64)
670        }
671    }
672
673    /// ```text
674    ///  7 6 5 4 3 2 1 0
675    /// +-+-+-+-+-+-+-+-+
676    /// |zid_len|X|X|X|X|
677    /// +-------+-+-+---+
678    /// ~      zid      ~
679    /// +---------------+
680    /// %      eid      %
681    /// +---------------+
682    /// ```
683    #[derive(Debug, Clone, PartialEq, Eq)]
684    pub struct EntityGlobalIdType<const ID: u8> {
685        pub zid: ZenohIdProto,
686        pub eid: EntityId,
687    }
688
689    impl<const ID: u8> EntityGlobalIdType<{ ID }> {
690        #[cfg(feature = "test")]
691        #[doc(hidden)]
692        pub fn rand() -> Self {
693            use rand::Rng;
694            let mut rng = rand::thread_rng();
695
696            let zid = ZenohIdProto::rand();
697            let eid: EntityId = rng.gen();
698            Self { zid, eid }
699        }
700    }
701}