zenoh_codec/scouting/
scout.rs1use core::convert::TryFrom;
15
16use zenoh_buffers::{
17 reader::{DidntRead, Reader},
18 writer::{DidntWrite, Writer},
19};
20use zenoh_protocol::{
21 common::{imsg, ZExtUnknown},
22 core::{whatami::WhatAmIMatcher, ZenohIdProto},
23 scouting::{
24 id,
25 scout::{flag, Scout},
26 },
27};
28
29use crate::{RCodec, WCodec, Zenoh080, Zenoh080Header, Zenoh080Length};
30
31impl<W> WCodec<&Scout, &mut W> for Zenoh080
32where
33 W: Writer,
34{
35 type Output = Result<(), DidntWrite>;
36
37 fn write(self, writer: &mut W, x: &Scout) -> Self::Output {
38 let Scout { version, what, zid } = x;
39
40 let header = id::SCOUT;
42 self.write(&mut *writer, header)?;
43
44 self.write(&mut *writer, version)?;
46
47 let mut flags: u8 = 0;
48 let what: u8 = (*what).into();
49 flags |= what & 0b111;
50 if let Some(zid) = zid.as_ref() {
51 flags |= (((zid.size() - 1) as u8) << 4) | flag::I;
52 };
53 self.write(&mut *writer, flags)?;
54
55 if let Some(zid) = zid.as_ref() {
56 let lodec = Zenoh080Length::new(zid.size());
57 lodec.write(&mut *writer, zid)?;
58 }
59
60 Ok(())
61 }
62}
63
64impl<R> RCodec<Scout, &mut R> for Zenoh080
65where
66 R: Reader,
67{
68 type Error = DidntRead;
69
70 fn read(self, reader: &mut R) -> Result<Scout, Self::Error> {
71 let header: u8 = self.read(&mut *reader)?;
72 let codec = Zenoh080Header::new(header);
73
74 codec.read(reader)
75 }
76}
77
78impl<R> RCodec<Scout, &mut R> for Zenoh080Header
79where
80 R: Reader,
81{
82 type Error = DidntRead;
83
84 fn read(self, reader: &mut R) -> Result<Scout, Self::Error> {
85 if imsg::mid(self.header) != id::SCOUT {
86 return Err(DidntRead);
87 }
88
89 let version: u8 = self.codec.read(&mut *reader)?;
91 let flags: u8 = self.codec.read(&mut *reader)?;
92 let what = WhatAmIMatcher::try_from(flags & 0b111).map_err(|_| DidntRead)?;
93 let zid = if imsg::has_flag(flags, flag::I) {
94 let length = 1 + ((flags >> 4) as usize);
95 let lodec = Zenoh080Length::new(length);
96 let zid: ZenohIdProto = lodec.read(&mut *reader)?;
97 Some(zid)
98 } else {
99 None
100 };
101
102 let mut has_extensions = imsg::has_flag(self.header, flag::Z);
104 while has_extensions {
105 let (_, more): (ZExtUnknown, bool) = self.codec.read(&mut *reader)?;
106 has_extensions = more;
107 }
108
109 Ok(Scout { version, what, zid })
110 }
111}