Skip to main content

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 OAM: Self = Self::new(Priority::Control, CongestionControl::DEFAULT_OAM, false);
478
479        pub const fn new(
480            priority: Priority,
481            congestion_control: CongestionControl,
482            is_express: bool,
483        ) -> Self {
484            let mut inner = priority as u8;
485            match congestion_control {
486                CongestionControl::Block => inner |= Self::D_FLAG,
487                #[cfg(feature = "unstable")]
488                CongestionControl::BlockFirst => inner |= Self::F_FLAG,
489                _ => {}
490            }
491            if is_express {
492                inner |= Self::E_FLAG;
493            }
494            Self { inner }
495        }
496
497        pub fn set_priority(&mut self, priority: Priority) {
498            self.inner = imsg::set_bitfield(self.inner, priority as u8, Self::P_MASK);
499        }
500
501        pub const fn get_priority(&self) -> Priority {
502            unsafe { core::mem::transmute(self.inner & Self::P_MASK) }
503        }
504
505        pub fn set_congestion_control(&mut self, cctrl: CongestionControl) {
506            match cctrl {
507                CongestionControl::Block => {
508                    self.inner = imsg::set_flag(self.inner, Self::D_FLAG);
509                    self.inner = imsg::unset_flag(self.inner, Self::F_FLAG);
510                }
511                CongestionControl::Drop => {
512                    self.inner = imsg::unset_flag(self.inner, Self::D_FLAG);
513                    self.inner = imsg::unset_flag(self.inner, Self::F_FLAG);
514                }
515                #[cfg(feature = "unstable")]
516                CongestionControl::BlockFirst => {
517                    self.inner = imsg::unset_flag(self.inner, Self::D_FLAG);
518                    self.inner = imsg::set_flag(self.inner, Self::F_FLAG);
519                }
520            }
521        }
522
523        pub const fn get_congestion_control(&self) -> CongestionControl {
524            match (
525                imsg::has_flag(self.inner, Self::D_FLAG),
526                imsg::has_flag(self.inner, Self::F_FLAG),
527            ) {
528                (false, false) => CongestionControl::Drop,
529                #[cfg(feature = "unstable")]
530                (false, true) => CongestionControl::BlockFirst,
531                #[cfg(not(feature = "unstable"))]
532                (false, true) => CongestionControl::Drop,
533                (true, _) => CongestionControl::Block,
534            }
535        }
536
537        pub fn set_is_express(&mut self, is_express: bool) {
538            match is_express {
539                true => self.inner = imsg::set_flag(self.inner, Self::E_FLAG),
540                false => self.inner = imsg::unset_flag(self.inner, Self::E_FLAG),
541            }
542        }
543
544        pub const fn is_express(&self) -> bool {
545            imsg::has_flag(self.inner, Self::E_FLAG)
546        }
547
548        #[cfg(feature = "test")]
549        #[doc(hidden)]
550        pub fn rand() -> Self {
551            use rand::Rng;
552            let mut rng = rand::thread_rng();
553
554            let inner: u8 = rng.gen();
555            Self { inner }
556        }
557    }
558
559    impl<const ID: u8> Default for QoSType<{ ID }> {
560        fn default() -> Self {
561            Self::new(Priority::DEFAULT, CongestionControl::DEFAULT, false)
562        }
563    }
564
565    impl<const ID: u8> From<ZExtZ64<{ ID }>> for QoSType<{ ID }> {
566        fn from(ext: ZExtZ64<{ ID }>) -> Self {
567            Self {
568                inner: ext.value as u8,
569            }
570        }
571    }
572
573    impl<const ID: u8> From<QoSType<{ ID }>> for ZExtZ64<{ ID }> {
574        fn from(ext: QoSType<{ ID }>) -> Self {
575            ZExtZ64::new(ext.inner as u64)
576        }
577    }
578
579    impl<const ID: u8> fmt::Debug for QoSType<{ ID }> {
580        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
581            f.debug_struct("QoS")
582                .field("priority", &self.get_priority())
583                .field("congestion", &self.get_congestion_control())
584                .field("express", &self.is_express())
585                .finish()
586        }
587    }
588
589    /// ```text
590    ///  7 6 5 4 3 2 1 0
591    /// +-+-+-+-+-+-+-+-+
592    /// |Z|1_0|    ID   |
593    /// +-+-+-+---------+
594    /// ~ ts: <u8;z16>  ~
595    /// +---------------+
596    /// ```
597    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
598    pub struct TimestampType<const ID: u8> {
599        pub timestamp: uhlc::Timestamp,
600    }
601
602    impl<const ID: u8> TimestampType<{ ID }> {
603        #[cfg(feature = "test")]
604        #[doc(hidden)]
605        pub fn rand() -> Self {
606            use rand::Rng;
607            let mut rng = rand::thread_rng();
608
609            let time = uhlc::NTP64(rng.gen());
610            let id = uhlc::ID::try_from(ZenohIdProto::rand().to_le_bytes()).unwrap();
611            let timestamp = uhlc::Timestamp::new(time, id);
612            Self { timestamp }
613        }
614    }
615
616    /// ```text
617    ///  7 6 5 4 3 2 1 0
618    /// +-+-+-+-+-+-+-+-+
619    /// |Z|0_1|    ID   |
620    /// +-+-+-+---------+
621    /// %    node_id    %
622    /// +---------------+
623    /// ```
624    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
625    pub struct NodeIdType<const ID: u8> {
626        pub node_id: u16,
627    }
628
629    impl<const ID: u8> NodeIdType<{ ID }> {
630        // node_id == 0 means the message has been generated by the node itself
631        pub const DEFAULT: Self = Self { node_id: 0 };
632
633        #[cfg(feature = "test")]
634        #[doc(hidden)]
635        pub fn rand() -> Self {
636            use rand::Rng;
637            let mut rng = rand::thread_rng();
638            let node_id = rng.gen();
639            Self { node_id }
640        }
641    }
642
643    impl<const ID: u8> Default for NodeIdType<{ ID }> {
644        fn default() -> Self {
645            Self::DEFAULT
646        }
647    }
648
649    impl<const ID: u8> From<ZExtZ64<{ ID }>> for NodeIdType<{ ID }> {
650        fn from(ext: ZExtZ64<{ ID }>) -> Self {
651            Self {
652                node_id: ext.value as u16,
653            }
654        }
655    }
656
657    impl<const ID: u8> From<NodeIdType<{ ID }>> for ZExtZ64<{ ID }> {
658        fn from(ext: NodeIdType<{ ID }>) -> Self {
659            ZExtZ64::new(ext.node_id as u64)
660        }
661    }
662
663    /// ```text
664    ///  7 6 5 4 3 2 1 0
665    /// +-+-+-+-+-+-+-+-+
666    /// |zid_len|X|X|X|X|
667    /// +-------+-+-+---+
668    /// ~      zid      ~
669    /// +---------------+
670    /// %      eid      %
671    /// +---------------+
672    /// ```
673    #[derive(Debug, Clone, PartialEq, Eq)]
674    pub struct EntityGlobalIdType<const ID: u8> {
675        pub zid: ZenohIdProto,
676        pub eid: EntityId,
677    }
678
679    impl<const ID: u8> EntityGlobalIdType<{ ID }> {
680        #[cfg(feature = "test")]
681        #[doc(hidden)]
682        pub fn rand() -> Self {
683            use rand::Rng;
684            let mut rng = rand::thread_rng();
685
686            let zid = ZenohIdProto::rand();
687            let eid: EntityId = rng.gen();
688            Self { zid, eid }
689        }
690    }
691}