zenoh_codec/common/
extension.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 alloc::vec::Vec;
15
16use zenoh_buffers::{
17    reader::{DidntRead, Reader},
18    writer::{DidntWrite, Writer},
19    ZBuf,
20};
21use zenoh_protocol::common::{
22    iext, imsg::has_flag, ZExtBody, ZExtUnit, ZExtUnknown, ZExtZ64, ZExtZBuf, ZExtZBufHeader,
23};
24
25use crate::{RCodec, WCodec, Zenoh080, Zenoh080Bounded, Zenoh080Header};
26
27fn read_inner<R>(reader: &mut R, _s: &str, header: u8) -> Result<(ZExtUnknown, bool), DidntRead>
28where
29    R: Reader,
30{
31    let codec = Zenoh080Header::new(header);
32    let (u, has_ext): (ZExtUnknown, bool) = codec.read(&mut *reader)?;
33    if u.is_mandatory() {
34        #[cfg(feature = "std")]
35        tracing::error!("Unknown {_s} ext: {u:?}");
36        return Err(DidntRead);
37    } else {
38        #[cfg(feature = "std")]
39        tracing::debug!("Unknown {_s} ext: {u:?}");
40    }
41    Ok((u, has_ext))
42}
43
44#[cold]
45#[inline(never)]
46pub fn read<R>(reader: &mut R, s: &str, header: u8) -> Result<(ZExtUnknown, bool), DidntRead>
47where
48    R: Reader,
49{
50    read_inner(&mut *reader, s, header)
51}
52
53fn skip_inner<R>(reader: &mut R, s: &str, header: u8) -> Result<bool, DidntRead>
54where
55    R: Reader,
56{
57    let (_, has_ext): (ZExtUnknown, bool) = read_inner(&mut *reader, s, header)?;
58    Ok(has_ext)
59}
60
61#[cold]
62#[inline(never)]
63pub fn skip<R>(reader: &mut R, s: &str, header: u8) -> Result<bool, DidntRead>
64where
65    R: Reader,
66{
67    skip_inner(reader, s, header)
68}
69
70#[cold]
71#[inline(never)]
72pub fn skip_all<R>(reader: &mut R, s: &str) -> Result<(), DidntRead>
73where
74    R: Reader,
75{
76    let codec = Zenoh080::new();
77    let mut has_ext = true;
78    while has_ext {
79        let header: u8 = codec.read(&mut *reader)?;
80        has_ext = skip_inner(reader, s, header)?;
81    }
82    Ok(())
83}
84
85// ZExtUnit
86impl<const ID: u8, W> WCodec<(&ZExtUnit<{ ID }>, bool), &mut W> for Zenoh080
87where
88    W: Writer,
89{
90    type Output = Result<(), DidntWrite>;
91
92    fn write(self, writer: &mut W, x: (&ZExtUnit<{ ID }>, bool)) -> Self::Output {
93        let (x, more) = x;
94        let ZExtUnit = x;
95
96        let mut header: u8 = ID;
97        if more {
98            header |= iext::FLAG_Z;
99        }
100        self.write(&mut *writer, header)?;
101        Ok(())
102    }
103}
104
105impl<const ID: u8, R> RCodec<(ZExtUnit<{ ID }>, bool), &mut R> for Zenoh080
106where
107    R: Reader,
108{
109    type Error = DidntRead;
110
111    fn read(self, reader: &mut R) -> Result<(ZExtUnit<{ ID }>, bool), Self::Error> {
112        let header: u8 = self.read(&mut *reader)?;
113        let codec = Zenoh080Header::new(header);
114        codec.read(&mut *reader)
115    }
116}
117
118impl<const ID: u8, R> RCodec<(ZExtUnit<{ ID }>, bool), &mut R> for Zenoh080Header
119where
120    R: Reader,
121{
122    type Error = DidntRead;
123
124    fn read(self, _reader: &mut R) -> Result<(ZExtUnit<{ ID }>, bool), Self::Error> {
125        if iext::eid(self.header) != ID {
126            return Err(DidntRead);
127        }
128        Ok((ZExtUnit::new(), has_flag(self.header, iext::FLAG_Z)))
129    }
130}
131
132// ZExtZ64
133impl<const ID: u8, W> WCodec<(&ZExtZ64<{ ID }>, bool), &mut W> for Zenoh080
134where
135    W: Writer,
136{
137    type Output = Result<(), DidntWrite>;
138
139    fn write(self, writer: &mut W, x: (&ZExtZ64<{ ID }>, bool)) -> Self::Output {
140        let (x, more) = x;
141        let ZExtZ64 { value } = x;
142
143        let mut header: u8 = ID;
144        if more {
145            header |= iext::FLAG_Z;
146        }
147        self.write(&mut *writer, header)?;
148        self.write(&mut *writer, value)?;
149        Ok(())
150    }
151}
152
153impl<const ID: u8, R> RCodec<(ZExtZ64<{ ID }>, bool), &mut R> for Zenoh080
154where
155    R: Reader,
156{
157    type Error = DidntRead;
158
159    fn read(self, reader: &mut R) -> Result<(ZExtZ64<{ ID }>, bool), Self::Error> {
160        let header: u8 = self.read(&mut *reader)?;
161        let codec = Zenoh080Header::new(header);
162        codec.read(&mut *reader)
163    }
164}
165
166impl<const ID: u8, R> RCodec<(ZExtZ64<{ ID }>, bool), &mut R> for Zenoh080Header
167where
168    R: Reader,
169{
170    type Error = DidntRead;
171
172    fn read(self, reader: &mut R) -> Result<(ZExtZ64<{ ID }>, bool), Self::Error> {
173        if iext::eid(self.header) != ID {
174            return Err(DidntRead);
175        }
176
177        let value: u64 = self.codec.read(&mut *reader)?;
178        Ok((ZExtZ64::new(value), has_flag(self.header, iext::FLAG_Z)))
179    }
180}
181
182// ZExtZBuf
183impl<const ID: u8, W> WCodec<(&ZExtZBuf<{ ID }>, bool), &mut W> for Zenoh080
184where
185    W: Writer,
186{
187    type Output = Result<(), DidntWrite>;
188
189    fn write(self, writer: &mut W, x: (&ZExtZBuf<{ ID }>, bool)) -> Self::Output {
190        let (x, more) = x;
191        let ZExtZBuf { value } = x;
192
193        let mut header: u8 = ID;
194        if more {
195            header |= iext::FLAG_Z;
196        }
197        self.write(&mut *writer, header)?;
198        let bodec = Zenoh080Bounded::<u32>::new();
199        bodec.write(&mut *writer, value)?;
200        Ok(())
201    }
202}
203
204impl<const ID: u8, R> RCodec<(ZExtZBuf<{ ID }>, bool), &mut R> for Zenoh080
205where
206    R: Reader,
207{
208    type Error = DidntRead;
209
210    fn read(self, reader: &mut R) -> Result<(ZExtZBuf<{ ID }>, bool), Self::Error> {
211        let header: u8 = self.read(&mut *reader)?;
212        let codec = Zenoh080Header::new(header);
213        codec.read(&mut *reader)
214    }
215}
216
217impl<const ID: u8, R> RCodec<(ZExtZBuf<{ ID }>, bool), &mut R> for Zenoh080Header
218where
219    R: Reader,
220{
221    type Error = DidntRead;
222
223    fn read(self, reader: &mut R) -> Result<(ZExtZBuf<{ ID }>, bool), Self::Error> {
224        if iext::eid(self.header) != ID {
225            return Err(DidntRead);
226        }
227        let bodec = Zenoh080Bounded::<u32>::new();
228        let value: ZBuf = bodec.read(&mut *reader)?;
229        Ok((ZExtZBuf::new(value), has_flag(self.header, iext::FLAG_Z)))
230    }
231}
232
233// ZExtZBufHeader
234impl<const ID: u8, W> WCodec<(&ZExtZBufHeader<{ ID }>, bool), &mut W> for Zenoh080
235where
236    W: Writer,
237{
238    type Output = Result<(), DidntWrite>;
239
240    fn write(self, writer: &mut W, x: (&ZExtZBufHeader<{ ID }>, bool)) -> Self::Output {
241        let (x, more) = x;
242        let ZExtZBufHeader { len } = x;
243
244        let mut header: u8 = ID;
245        if more {
246            header |= iext::FLAG_Z;
247        }
248        self.write(&mut *writer, header)?;
249        let bodec = Zenoh080Bounded::<u32>::new();
250        bodec.write(&mut *writer, *len)?;
251        Ok(())
252    }
253}
254
255impl<const ID: u8, R> RCodec<(ZExtZBufHeader<{ ID }>, bool), &mut R> for Zenoh080
256where
257    R: Reader,
258{
259    type Error = DidntRead;
260
261    fn read(self, reader: &mut R) -> Result<(ZExtZBufHeader<{ ID }>, bool), Self::Error> {
262        let header: u8 = self.read(&mut *reader)?;
263        let codec = Zenoh080Header::new(header);
264        codec.read(&mut *reader)
265    }
266}
267
268impl<const ID: u8, R> RCodec<(ZExtZBufHeader<{ ID }>, bool), &mut R> for Zenoh080Header
269where
270    R: Reader,
271{
272    type Error = DidntRead;
273
274    fn read(self, reader: &mut R) -> Result<(ZExtZBufHeader<{ ID }>, bool), Self::Error> {
275        if iext::eid(self.header) != ID {
276            return Err(DidntRead);
277        }
278
279        let bodec = Zenoh080Bounded::<u32>::new();
280        let len: usize = bodec.read(&mut *reader)?;
281        Ok((
282            ZExtZBufHeader::new(len),
283            has_flag(self.header, iext::FLAG_Z),
284        ))
285    }
286}
287
288// ZExtUnknown
289impl<W> WCodec<(&ZExtUnknown, bool), &mut W> for Zenoh080
290where
291    W: Writer,
292{
293    type Output = Result<(), DidntWrite>;
294
295    fn write(self, writer: &mut W, x: (&ZExtUnknown, bool)) -> Self::Output {
296        let (x, more) = x;
297        let ZExtUnknown { id, body } = x;
298
299        let mut header: u8 = *id;
300        if more {
301            header |= iext::FLAG_Z;
302        }
303        match body {
304            ZExtBody::Unit => self.write(&mut *writer, header)?,
305            ZExtBody::Z64(u64) => {
306                self.write(&mut *writer, header)?;
307                self.write(&mut *writer, *u64)?
308            }
309            ZExtBody::ZBuf(zbuf) => {
310                self.write(&mut *writer, header)?;
311                let bodec = Zenoh080Bounded::<u32>::new();
312                bodec.write(&mut *writer, zbuf)?
313            }
314        }
315        Ok(())
316    }
317}
318
319impl<R> RCodec<(ZExtUnknown, bool), &mut R> for Zenoh080
320where
321    R: Reader,
322{
323    type Error = DidntRead;
324
325    fn read(self, reader: &mut R) -> Result<(ZExtUnknown, bool), Self::Error> {
326        let header: u8 = self.read(&mut *reader)?;
327        let codec = Zenoh080Header::new(header);
328        codec.read(&mut *reader)
329    }
330}
331
332impl<R> RCodec<(ZExtUnknown, bool), &mut R> for Zenoh080Header
333where
334    R: Reader,
335{
336    type Error = DidntRead;
337
338    fn read(self, reader: &mut R) -> Result<(ZExtUnknown, bool), Self::Error> {
339        let body = match self.header & iext::ENC_MASK {
340            iext::ENC_UNIT => ZExtBody::Unit,
341            iext::ENC_Z64 => {
342                let u64: u64 = self.codec.read(&mut *reader)?;
343                ZExtBody::Z64(u64)
344            }
345            iext::ENC_ZBUF => {
346                let bodec = Zenoh080Bounded::<u32>::new();
347                let zbuf: ZBuf = bodec.read(&mut *reader)?;
348                ZExtBody::ZBuf(zbuf)
349            }
350            _ => {
351                return Err(DidntRead);
352            }
353        };
354
355        Ok((
356            ZExtUnknown {
357                id: self.header & !iext::FLAG_Z,
358                body,
359            },
360            has_flag(self.header, iext::FLAG_Z),
361        ))
362    }
363}
364
365impl<W> WCodec<&[ZExtUnknown], &mut W> for Zenoh080
366where
367    W: Writer,
368{
369    type Output = Result<(), DidntWrite>;
370
371    fn write(self, writer: &mut W, x: &[ZExtUnknown]) -> Self::Output {
372        let len = x.len();
373        for (i, e) in x.iter().enumerate() {
374            self.write(&mut *writer, (e, i < len - 1))?;
375        }
376        Ok(())
377    }
378}
379
380impl<R> RCodec<Vec<ZExtUnknown>, &mut R> for Zenoh080
381where
382    R: Reader,
383{
384    type Error = DidntRead;
385
386    fn read(self, reader: &mut R) -> Result<Vec<ZExtUnknown>, Self::Error> {
387        let mut exts = Vec::new();
388        let mut has_ext = reader.can_read();
389        while has_ext {
390            let (e, more): (ZExtUnknown, bool) = self.read(&mut *reader)?;
391            exts.push(e);
392            has_ext = more;
393        }
394        Ok(exts)
395    }
396}
397
398// Macros
399#[macro_export]
400macro_rules! impl_zextz64 {
401    ($ext:ty, $id:expr) => {
402        impl<W> WCodec<($ext, bool), &mut W> for Zenoh080
403        where
404            W: Writer,
405        {
406            type Output = Result<(), DidntWrite>;
407
408            fn write(self, writer: &mut W, x: ($ext, bool)) -> Self::Output {
409                let (x, more) = x;
410                let ext: ZExtZ64<{ $id }> = x.into();
411                self.write(&mut *writer, (&ext, more))
412            }
413        }
414
415        impl<R> RCodec<($ext, bool), &mut R> for Zenoh080
416        where
417            R: Reader,
418        {
419            type Error = DidntRead;
420
421            fn read(self, reader: &mut R) -> Result<($ext, bool), Self::Error> {
422                let header: u8 = self.read(&mut *reader)?;
423                let codec = Zenoh080Header::new(header);
424                codec.read(reader)
425            }
426        }
427
428        impl<R> RCodec<($ext, bool), &mut R> for Zenoh080Header
429        where
430            R: Reader,
431        {
432            type Error = DidntRead;
433
434            fn read(self, reader: &mut R) -> Result<($ext, bool), Self::Error> {
435                let (ext, more): (ZExtZ64<{ $id }>, bool) = self.read(&mut *reader)?;
436                Ok((ext.into(), more))
437            }
438        }
439    };
440}