1use 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
85impl<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
132impl<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
182impl<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
233impl<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
288impl<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#[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}