Skip to main content

zenoh_codec/network/
request.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//
14use zenoh_buffers::{
15    reader::{DidntRead, Reader},
16    writer::{DidntWrite, Writer},
17};
18use zenoh_protocol::{
19    common::{iext, imsg},
20    core::WireExpr,
21    network::{
22        id,
23        request::{ext, flag},
24        Mapping, Request, RequestId,
25    },
26    zenoh::RequestBody,
27};
28
29use crate::{
30    common::extension, RCodec, WCodec, Zenoh080, Zenoh080Bounded, Zenoh080Condition, Zenoh080Header,
31};
32
33// Target
34impl<W> WCodec<(&ext::QueryTarget, bool), &mut W> for Zenoh080
35where
36    W: Writer,
37{
38    type Output = Result<(), DidntWrite>;
39
40    fn write(self, writer: &mut W, x: (&ext::QueryTarget, bool)) -> Self::Output {
41        let (x, more) = x;
42
43        let v = match x {
44            ext::QueryTarget::BestMatching => 0,
45            ext::QueryTarget::All => 1,
46            ext::QueryTarget::AllComplete => 2,
47        };
48        let ext = ext::Target::new(v);
49        self.write(&mut *writer, (&ext, more))
50    }
51}
52
53impl<R> RCodec<(ext::QueryTarget, bool), &mut R> for Zenoh080Header
54where
55    R: Reader,
56{
57    type Error = DidntRead;
58
59    fn read(self, reader: &mut R) -> Result<(ext::QueryTarget, bool), Self::Error> {
60        let (ext, more): (ext::Target, bool) = self.read(&mut *reader)?;
61        let rt = match ext.value {
62            0 => ext::QueryTarget::BestMatching,
63            1 => ext::QueryTarget::All,
64            2 => ext::QueryTarget::AllComplete,
65            _ => return Err(DidntRead),
66        };
67        Ok((rt, more))
68    }
69}
70
71impl<W> WCodec<&Request, &mut W> for Zenoh080
72where
73    W: Writer,
74{
75    type Output = Result<(), DidntWrite>;
76
77    fn write(self, writer: &mut W, x: &Request) -> Self::Output {
78        let Request {
79            id,
80            wire_expr,
81            ext_qos,
82            ext_tstamp,
83            ext_nodeid,
84            ext_target,
85            ext_budget,
86            ext_timeout,
87            ext_ts_stack,
88            payload,
89        } = x;
90
91        // Header
92        let mut header = id::REQUEST;
93        let mut n_exts = ((ext_qos != &ext::QoSType::DEFAULT) as u8)
94            + (ext_tstamp.is_some() as u8)
95            + ((ext_target != &ext::QueryTarget::DEFAULT) as u8)
96            + (ext_budget.is_some() as u8)
97            + (ext_timeout.is_some() as u8)
98            + ((ext_nodeid != &ext::NodeIdType::DEFAULT) as u8)
99            + (ext_ts_stack.is_some() as u8);
100        if n_exts != 0 {
101            header |= flag::Z;
102        }
103        if wire_expr.mapping != Mapping::DEFAULT {
104            header |= flag::M;
105        }
106        if wire_expr.has_suffix() {
107            header |= flag::N;
108        }
109        self.write(&mut *writer, header)?;
110
111        // Body
112        self.write(&mut *writer, id)?;
113        self.write(&mut *writer, wire_expr)?;
114
115        // Extensions
116        if ext_qos != &ext::QoSType::DEFAULT {
117            n_exts -= 1;
118            self.write(&mut *writer, (*ext_qos, n_exts != 0))?;
119        }
120        if let Some(ts) = ext_tstamp.as_ref() {
121            n_exts -= 1;
122            self.write(&mut *writer, (ts, n_exts != 0))?;
123        }
124        if ext_target != &ext::QueryTarget::DEFAULT {
125            n_exts -= 1;
126            self.write(&mut *writer, (ext_target, n_exts != 0))?;
127        }
128        if let Some(l) = ext_budget.as_ref() {
129            n_exts -= 1;
130            let e = ext::Budget::new(l.get() as u64);
131            self.write(&mut *writer, (&e, n_exts != 0))?;
132        }
133        if let Some(to) = ext_timeout.as_ref() {
134            n_exts -= 1;
135            let e = ext::Timeout::new(to.as_millis() as u64);
136            self.write(&mut *writer, (&e, n_exts != 0))?;
137        }
138        if ext_nodeid != &ext::NodeIdType::DEFAULT {
139            n_exts -= 1;
140            self.write(&mut *writer, (*ext_nodeid, n_exts != 0))?;
141        }
142        if let Some(ts_stack) = ext_ts_stack.as_ref() {
143            n_exts -= 1;
144            self.write(&mut *writer, (ts_stack, n_exts != 0))?;
145        }
146
147        // Payload
148        self.write(&mut *writer, payload)?;
149
150        Ok(())
151    }
152}
153
154impl<R> RCodec<Request, &mut R> for Zenoh080
155where
156    R: Reader,
157{
158    type Error = DidntRead;
159
160    fn read(self, reader: &mut R) -> Result<Request, Self::Error> {
161        let header: u8 = self.read(&mut *reader)?;
162        let codec = Zenoh080Header::new(header);
163        codec.read(reader)
164    }
165}
166
167impl<R> RCodec<Request, &mut R> for Zenoh080Header
168where
169    R: Reader,
170{
171    type Error = DidntRead;
172
173    fn read(self, reader: &mut R) -> Result<Request, Self::Error> {
174        if imsg::mid(self.header) != id::REQUEST {
175            return Err(DidntRead);
176        }
177
178        // Body
179        let bodec = Zenoh080Bounded::<RequestId>::new();
180        let id: RequestId = bodec.read(&mut *reader)?;
181        let ccond = Zenoh080Condition::new(imsg::has_flag(self.header, flag::N));
182        let mut wire_expr: WireExpr<'static> = ccond.read(&mut *reader)?;
183        wire_expr.mapping = if imsg::has_flag(self.header, flag::M) {
184            Mapping::Sender
185        } else {
186            Mapping::Receiver
187        };
188
189        // Extensions
190        let mut ext_qos = ext::QoSType::DEFAULT;
191        let mut ext_tstamp = None;
192        let mut ext_nodeid = ext::NodeIdType::DEFAULT;
193        let mut ext_target = ext::QueryTarget::DEFAULT;
194        let mut ext_limit = None;
195        let mut ext_timeout = None;
196        let mut ext_ts_stack = None;
197
198        let mut has_ext = imsg::has_flag(self.header, flag::Z);
199        while has_ext {
200            let ext: u8 = self.codec.read(&mut *reader)?;
201            let eodec = Zenoh080Header::new(ext);
202            match iext::eid(ext) {
203                ext::QoS::ID => {
204                    let (q, ext): (ext::QoSType, bool) = eodec.read(&mut *reader)?;
205                    ext_qos = q;
206                    has_ext = ext;
207                }
208                ext::Timestamp::ID => {
209                    let (t, ext): (ext::TimestampType, bool) = eodec.read(&mut *reader)?;
210                    ext_tstamp = Some(t);
211                    has_ext = ext;
212                }
213                ext::NodeId::ID => {
214                    let (nid, ext): (ext::NodeIdType, bool) = eodec.read(&mut *reader)?;
215                    ext_nodeid = nid;
216                    has_ext = ext;
217                }
218                ext::Target::ID => {
219                    let (rt, ext): (ext::QueryTarget, bool) = eodec.read(&mut *reader)?;
220                    ext_target = rt;
221                    has_ext = ext;
222                }
223                ext::Budget::ID => {
224                    let (l, ext): (ext::Budget, bool) = eodec.read(&mut *reader)?;
225                    ext_limit = ext::BudgetType::new(l.value as u32);
226                    has_ext = ext;
227                }
228                ext::Timeout::ID => {
229                    let (to, ext): (ext::Timeout, bool) = eodec.read(&mut *reader)?;
230                    ext_timeout = Some(ext::TimeoutType::from_millis(to.value));
231                    has_ext = ext;
232                }
233                ext::TsStack::ID => {
234                    let (ts, ext): (ext::TsStackType, bool) = eodec.read(&mut *reader)?;
235                    ext_ts_stack = Some(ts);
236                    has_ext = ext;
237                }
238                _ => {
239                    has_ext = extension::skip(reader, "Request", ext)?;
240                }
241            }
242        }
243
244        // Payload
245        let payload: RequestBody = self.codec.read(&mut *reader)?;
246
247        Ok(Request {
248            id,
249            wire_expr,
250            payload,
251            ext_qos,
252            ext_tstamp,
253            ext_nodeid,
254            ext_target,
255            ext_budget: ext_limit,
256            ext_timeout,
257            ext_ts_stack,
258        })
259    }
260}