1use alloc::string::String;
15use core::{convert::TryFrom, fmt, num::NonZeroU8, ops::BitOr, str::FromStr};
16
17use const_format::formatcp;
18use serde::ser::SerializeSeq;
19use zenoh_result::{bail, ZError};
20
21#[repr(u8)]
39#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
40pub enum WhatAmI {
41 Router = 0b001,
42 #[default]
43 Peer = 0b010,
44 Client = 0b100,
45}
46
47impl WhatAmI {
48 const STR_R: &'static str = "router";
49 const STR_P: &'static str = "peer";
50 const STR_C: &'static str = "client";
51
52 const U8_R: u8 = Self::Router as u8;
53 const U8_P: u8 = Self::Peer as u8;
54 const U8_C: u8 = Self::Client as u8;
55
56 pub const fn to_str(self) -> &'static str {
57 match self {
58 Self::Router => Self::STR_R,
59 Self::Peer => Self::STR_P,
60 Self::Client => Self::STR_C,
61 }
62 }
63
64 #[cfg(feature = "test")]
65 #[doc(hidden)]
66 pub fn rand() -> Self {
67 use rand::prelude::SliceRandom;
68 let mut rng = rand::thread_rng();
69
70 *[Self::Router, Self::Peer, Self::Client]
71 .choose(&mut rng)
72 .unwrap()
73 }
74}
75
76impl TryFrom<u8> for WhatAmI {
77 type Error = ();
78
79 fn try_from(v: u8) -> Result<Self, Self::Error> {
80 match v {
81 Self::U8_R => Ok(Self::Router),
82 Self::U8_P => Ok(Self::Peer),
83 Self::U8_C => Ok(Self::Client),
84 _ => Err(()),
85 }
86 }
87}
88
89impl FromStr for WhatAmI {
90 type Err = ZError;
91
92 fn from_str(s: &str) -> Result<Self, Self::Err> {
93 match s {
94 Self::STR_R => Ok(Self::Router),
95 Self::STR_P => Ok(Self::Peer),
96 Self::STR_C => Ok(Self::Client),
97 _ => bail!(
98 "{s} is not a valid WhatAmI value. Valid values are: {}, {}, {}.",
99 Self::STR_R,
100 Self::STR_P,
101 Self::STR_C
102 ),
103 }
104 }
105}
106
107impl fmt::Display for WhatAmI {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 f.write_str(self.to_str())
110 }
111}
112
113impl From<WhatAmI> for u8 {
114 fn from(w: WhatAmI) -> Self {
115 w as u8
116 }
117}
118
119#[repr(transparent)]
125#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
126pub struct WhatAmIMatcher(NonZeroU8);
127
128impl WhatAmIMatcher {
129 const U8_0: u8 = 1 << 7;
131 const U8_R: u8 = Self::U8_0 | WhatAmI::U8_R;
132 const U8_P: u8 = Self::U8_0 | WhatAmI::U8_P;
133 const U8_C: u8 = Self::U8_0 | WhatAmI::U8_C;
134 const U8_R_P: u8 = Self::U8_0 | WhatAmI::U8_R | WhatAmI::U8_P;
135 const U8_P_C: u8 = Self::U8_0 | WhatAmI::U8_P | WhatAmI::U8_C;
136 const U8_R_C: u8 = Self::U8_0 | WhatAmI::U8_R | WhatAmI::U8_C;
137 const U8_R_P_C: u8 = Self::U8_0 | WhatAmI::U8_R | WhatAmI::U8_P | WhatAmI::U8_C;
138
139 pub const fn empty() -> Self {
141 Self(unsafe { NonZeroU8::new_unchecked(Self::U8_0) })
142 }
143
144 pub const fn router(self) -> Self {
146 Self(unsafe { NonZeroU8::new_unchecked(self.0.get() | Self::U8_R) })
147 }
148
149 pub const fn peer(self) -> Self {
151 Self(unsafe { NonZeroU8::new_unchecked(self.0.get() | Self::U8_P) })
152 }
153
154 pub const fn client(self) -> Self {
156 Self(unsafe { NonZeroU8::new_unchecked(self.0.get() | Self::U8_C) })
157 }
158
159 pub const fn is_empty(&self) -> bool {
161 self.0.get() == Self::U8_0
162 }
163
164 pub const fn matches(&self, w: WhatAmI) -> bool {
166 (self.0.get() & w as u8) != 0
167 }
168
169 pub const fn to_str(self) -> &'static str {
172 match self.0.get() {
173 Self::U8_0 => "",
174 Self::U8_R => WhatAmI::STR_R,
175 Self::U8_P => WhatAmI::STR_P,
176 Self::U8_C => WhatAmI::STR_C,
177 Self::U8_R_P => formatcp!("{}|{}", WhatAmI::STR_R, WhatAmI::STR_P),
178 Self::U8_R_C => formatcp!("{}|{}", WhatAmI::STR_R, WhatAmI::STR_C),
179 Self::U8_P_C => formatcp!("{}|{}", WhatAmI::STR_P, WhatAmI::STR_C),
180 Self::U8_R_P_C => formatcp!("{}|{}|{}", WhatAmI::STR_R, WhatAmI::STR_P, WhatAmI::STR_C),
181
182 _ => unreachable!(),
183 }
184 }
185
186 #[cfg(feature = "test")]
187 #[doc(hidden)]
188 pub fn rand() -> Self {
189 use rand::Rng;
190
191 let mut rng = rand::thread_rng();
192 let mut waim = WhatAmIMatcher::empty();
193 if rng.gen_bool(0.5) {
194 waim = waim.router();
195 }
196 if rng.gen_bool(0.5) {
197 waim = waim.peer();
198 }
199 if rng.gen_bool(0.5) {
200 waim = waim.client();
201 }
202 waim
203 }
204}
205
206impl TryFrom<u8> for WhatAmIMatcher {
207 type Error = ();
208
209 fn try_from(v: u8) -> Result<Self, Self::Error> {
210 const MIN: u8 = 0;
211 const MAX: u8 = WhatAmI::U8_R | WhatAmI::U8_P | WhatAmI::U8_C;
212
213 if (MIN..=MAX).contains(&v) {
214 Ok(WhatAmIMatcher(unsafe {
215 NonZeroU8::new_unchecked(Self::U8_0 | v)
216 }))
217 } else {
218 Err(())
219 }
220 }
221}
222
223impl FromStr for WhatAmIMatcher {
224 type Err = ();
225
226 fn from_str(s: &str) -> Result<Self, Self::Err> {
227 let mut inner = 0;
228 for s in s.split('|') {
229 match s.trim() {
230 "" => {}
231 WhatAmI::STR_R => inner |= WhatAmI::U8_R,
232 WhatAmI::STR_P => inner |= WhatAmI::U8_P,
233 WhatAmI::STR_C => inner |= WhatAmI::U8_C,
234 _ => return Err(()),
235 }
236 }
237 Self::try_from(inner)
238 }
239}
240
241impl fmt::Display for WhatAmIMatcher {
242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 f.write_str(self.to_str())
244 }
245}
246
247impl From<WhatAmIMatcher> for u8 {
248 fn from(w: WhatAmIMatcher) -> u8 {
249 w.0.get()
250 }
251}
252
253impl<T> BitOr<T> for WhatAmIMatcher
254where
255 NonZeroU8: BitOr<T, Output = NonZeroU8>,
256{
257 type Output = Self;
258
259 fn bitor(self, rhs: T) -> Self::Output {
260 WhatAmIMatcher(self.0 | rhs)
261 }
262}
263
264impl BitOr<WhatAmI> for WhatAmIMatcher {
265 type Output = Self;
266
267 fn bitor(self, rhs: WhatAmI) -> Self::Output {
268 self | rhs as u8
269 }
270}
271
272impl BitOr for WhatAmIMatcher {
273 type Output = Self;
274
275 fn bitor(self, rhs: Self) -> Self::Output {
276 self | rhs.0
277 }
278}
279
280impl BitOr for WhatAmI {
281 type Output = WhatAmIMatcher;
282
283 fn bitor(self, rhs: Self) -> Self::Output {
284 WhatAmIMatcher(unsafe {
285 NonZeroU8::new_unchecked(self as u8 | rhs as u8 | WhatAmIMatcher::U8_0)
286 })
287 }
288}
289
290impl From<WhatAmI> for WhatAmIMatcher {
291 fn from(w: WhatAmI) -> Self {
292 WhatAmIMatcher(unsafe { NonZeroU8::new_unchecked(w as u8 | WhatAmIMatcher::U8_0) })
293 }
294}
295
296impl serde::Serialize for WhatAmI {
298 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
299 where
300 S: serde::Serializer,
301 {
302 serializer.serialize_str(self.to_str())
303 }
304}
305
306pub struct WhatAmIVisitor;
307
308impl<'de> serde::de::Visitor<'de> for WhatAmIVisitor {
309 type Value = WhatAmI;
310
311 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
312 write!(
313 formatter,
314 "either '{}', '{}' or '{}'",
315 WhatAmI::STR_R,
316 WhatAmI::STR_P,
317 WhatAmI::STR_C
318 )
319 }
320 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
321 where
322 E: serde::de::Error,
323 {
324 v.parse().map_err(|_| {
325 serde::de::Error::unknown_variant(v, &[WhatAmI::STR_R, WhatAmI::STR_P, WhatAmI::STR_C])
326 })
327 }
328 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
329 where
330 E: serde::de::Error,
331 {
332 self.visit_str(v)
333 }
334 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
335 where
336 E: serde::de::Error,
337 {
338 self.visit_str(&v)
339 }
340}
341
342impl<'de> serde::Deserialize<'de> for WhatAmI {
343 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
344 where
345 D: serde::Deserializer<'de>,
346 {
347 deserializer.deserialize_str(WhatAmIVisitor)
348 }
349}
350
351impl serde::Serialize for WhatAmIMatcher {
352 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
353 where
354 S: serde::Serializer,
355 {
356 let values = [WhatAmI::Router, WhatAmI::Peer, WhatAmI::Client]
357 .iter()
358 .filter(|v| self.matches(**v));
359 let mut seq = serializer.serialize_seq(Some(values.clone().count()))?;
360 for v in values {
361 seq.serialize_element(v)?;
362 }
363 seq.end()
364 }
365}
366
367pub struct WhatAmIMatcherVisitor;
368impl<'de> serde::de::Visitor<'de> for WhatAmIMatcherVisitor {
369 type Value = WhatAmIMatcher;
370 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
371 write!(
372 formatter,
373 "a list of whatami variants ('{}', '{}', '{}')",
374 WhatAmI::STR_R,
375 WhatAmI::STR_P,
376 WhatAmI::STR_C
377 )
378 }
379
380 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
381 where
382 A: serde::de::SeqAccess<'de>,
383 {
384 let mut inner = 0;
385
386 while let Some(s) = seq.next_element::<String>()? {
387 match s.as_str() {
388 WhatAmI::STR_R => inner |= WhatAmI::U8_R,
389 WhatAmI::STR_P => inner |= WhatAmI::U8_P,
390 WhatAmI::STR_C => inner |= WhatAmI::U8_C,
391 _ => {
392 return Err(serde::de::Error::invalid_value(
393 serde::de::Unexpected::Str(&s),
394 &formatcp!(
395 "one of ('{}', '{}', '{}')",
396 WhatAmI::STR_R,
397 WhatAmI::STR_P,
398 WhatAmI::STR_C
399 ),
400 ))
401 }
402 }
403 }
404
405 Ok(WhatAmIMatcher::try_from(inner)
406 .expect("`WhatAmIMatcher` should be valid by construction"))
407 }
408}
409
410impl<'de> serde::Deserialize<'de> for WhatAmIMatcher {
411 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
412 where
413 D: serde::Deserializer<'de>,
414 {
415 deserializer.deserialize_seq(WhatAmIMatcherVisitor)
416 }
417}