Skip to main content

zenoh_protocol/network/
push.rs

1use zenoh_buffers::buffer::Buffer;
2
3//
4// Copyright (c) 2022 ZettaScale Technology
5//
6// This program and the accompanying materials are made available under the
7// terms of the Eclipse Public License 2.0 which is available at
8// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
9// which is available at https://www.apache.org/licenses/LICENSE-2.0.
10//
11// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
12//
13// Contributors:
14//   ZettaScale Zenoh Team, <zenoh@zettascale.tech>
15//
16#[cfg(feature = "test")]
17use crate::zenoh::Put;
18use crate::{core::WireExpr, zenoh::PushBody};
19
20pub mod flag {
21    pub const N: u8 = 1 << 5; // 0x20 Named         if N==1 then the key expr has name/suffix
22    pub const M: u8 = 1 << 6; // 0x40 Mapping       if M==1 then key expr mapping is the one declared by the sender, else it is the one declared by the receiver
23    pub const Z: u8 = 1 << 7; // 0x80 Extensions    if Z==1 then an extension will follow
24}
25
26/// ```text
27/// Flags:
28/// - N: Named          If N==1 then the key expr has name/suffix
29/// - M: Mapping        if M==1 then key expr mapping is the one declared by the sender, else it is the one declared by the receiver
30/// - Z: Extension      If Z==1 then at least one extension is present
31///
32///  7 6 5 4 3 2 1 0
33/// +-+-+-+-+-+-+-+-+
34/// |Z|M|N|  PUSH   |
35/// +-+-+-+---------+
36/// ~ key_scope:z16 ~
37/// +---------------+
38/// ~  key_suffix   ~  if N==1 -- <u8;z16>
39/// +---------------+
40/// ~  [push_exts]  ~  if Z==1
41/// +---------------+
42/// ~   PushBody    ~
43/// +---------------+
44/// ```
45#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct Push {
47    pub wire_expr: WireExpr<'static>,
48    pub ext_qos: ext::QoSType,
49    pub ext_tstamp: Option<ext::TimestampType>,
50    pub ext_nodeid: ext::NodeIdType,
51    pub ext_ts_stack: Option<ext::TsStackType>,
52    pub payload: PushBody,
53}
54
55pub mod ext {
56    use crate::{zextz64, zextzbuf};
57
58    pub type QoS = zextz64!(0x1, false);
59    pub type QoSType = crate::network::ext::QoSType<{ QoS::ID }>;
60
61    pub type Timestamp = zextzbuf!(0x2, false);
62    pub type TimestampType = crate::network::ext::TimestampType<{ Timestamp::ID }>;
63
64    pub type NodeId = zextz64!(0x3, true);
65    pub type NodeIdType = crate::network::ext::NodeIdType<{ NodeId::ID }>;
66
67    pub type TsStack = zextzbuf!(0x7, false);
68    pub type TsStackType = crate::network::timestamp_stack::TsStackType<{ TsStack::ID }>;
69}
70
71impl Push {
72    pub fn payload_size(&self) -> usize {
73        match &self.payload {
74            PushBody::Put(p) => {
75                p.payload.len() + p.ext_attachment.as_ref().map_or(0, |a| a.buffer.len())
76            }
77            PushBody::Del(d) => d.ext_attachment.as_ref().map_or(0, |a| a.buffer.len()),
78        }
79    }
80
81    #[cfg(feature = "test")]
82    #[doc(hidden)]
83    pub fn rand() -> Self {
84        use rand::Rng;
85
86        let mut rng = rand::thread_rng();
87        let wire_expr = WireExpr::rand();
88        let payload = PushBody::rand();
89        let ext_qos = ext::QoSType::rand();
90        let ext_tstamp = rng.gen_bool(0.5).then(ext::TimestampType::rand);
91        let ext_nodeid = ext::NodeIdType::rand();
92        let ext_ts_stack = rng.gen_bool(0.5).then(ext::TsStackType::rand);
93
94        Self {
95            wire_expr,
96            payload,
97            ext_tstamp,
98            ext_qos,
99            ext_nodeid,
100            ext_ts_stack,
101        }
102    }
103}
104
105impl From<PushBody> for Push {
106    fn from(value: PushBody) -> Self {
107        Self {
108            wire_expr: WireExpr::empty(),
109            ext_qos: ext::QoSType::DEFAULT,
110            ext_tstamp: None,
111            ext_nodeid: ext::NodeIdType::DEFAULT,
112            ext_ts_stack: None,
113            payload: value,
114        }
115    }
116}
117
118#[cfg(feature = "test")]
119impl From<Put> for Push {
120    fn from(value: Put) -> Self {
121        PushBody::from(value).into()
122    }
123}
124
125#[cfg(feature = "test")]
126impl From<Vec<u8>> for Push {
127    fn from(value: Vec<u8>) -> Self {
128        Self::from(Put {
129            payload: value.into(),
130            ..Put::default()
131        })
132    }
133}