zenoh_protocol_core/
whatami.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 super::ZInt;
15use zenoh_core::{bail, zresult::ZError};
16
17#[repr(u8)]
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19pub enum WhatAmI {
20    Router = 1,
21    Peer = 1 << 1,
22    Client = 1 << 2,
23}
24
25impl std::str::FromStr for WhatAmI {
26    type Err = ZError;
27
28    fn from_str(s: &str) -> Result<Self, Self::Err> {
29        match s {
30            "router" => Ok(WhatAmI::Router),
31            "peer" => Ok(WhatAmI::Peer),
32            "client" => Ok(WhatAmI::Client),
33            _ => bail!("{} is not a valid WhatAmI value. Valid values are: [\"router\", \"peer\", \"client\"].", s),
34        }
35    }
36}
37
38impl WhatAmI {
39    pub fn to_str(self) -> &'static str {
40        match self {
41            WhatAmI::Router => "router",
42            WhatAmI::Peer => "peer",
43            WhatAmI::Client => "client",
44        }
45    }
46
47    pub fn try_from(value: ZInt) -> Option<Self> {
48        const CLIENT: ZInt = WhatAmI::Client as ZInt;
49        const ROUTER: ZInt = WhatAmI::Router as ZInt;
50        const PEER: ZInt = WhatAmI::Peer as ZInt;
51        match value {
52            CLIENT => Some(WhatAmI::Client),
53            ROUTER => Some(WhatAmI::Router),
54            PEER => Some(WhatAmI::Peer),
55            _ => None,
56        }
57    }
58}
59
60impl std::fmt::Display for WhatAmI {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        f.write_str(self.to_str())
63    }
64}
65
66impl serde::Serialize for WhatAmI {
67    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68    where
69        S: serde::Serializer,
70    {
71        serializer.serialize_str(self.to_str())
72    }
73}
74
75pub struct WhatAmIVisitor;
76
77impl<'de> serde::de::Visitor<'de> for WhatAmIVisitor {
78    type Value = WhatAmI;
79
80    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
81        formatter.write_str("either 'router', 'client' or 'peer'")
82    }
83    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
84    where
85        E: serde::de::Error,
86    {
87        v.parse()
88            .map_err(|_| serde::de::Error::unknown_variant(v, &["router", "client", "peer"]))
89    }
90    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
91    where
92        E: serde::de::Error,
93    {
94        self.visit_str(v)
95    }
96    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
97    where
98        E: serde::de::Error,
99    {
100        self.visit_str(&v)
101    }
102}
103
104impl<'de> serde::Deserialize<'de> for WhatAmI {
105    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
106    where
107        D: serde::Deserializer<'de>,
108    {
109        deserializer.deserialize_str(WhatAmIVisitor)
110    }
111}
112
113impl From<WhatAmI> for ZInt {
114    fn from(w: WhatAmI) -> Self {
115        w as ZInt
116    }
117}
118
119use std::{num::NonZeroU8, ops::BitOr};
120#[repr(transparent)]
121#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
122pub struct WhatAmIMatcher(pub NonZeroU8);
123
124impl WhatAmIMatcher {
125    pub fn try_from<T: std::convert::TryInto<u8>>(i: T) -> Option<Self> {
126        let i = i.try_into().ok()?;
127        if 127 < i && i < 136 {
128            Some(WhatAmIMatcher(unsafe { NonZeroU8::new_unchecked(i) }))
129        } else {
130            None
131        }
132    }
133
134    pub fn is_empty(self) -> bool {
135        self.0.get() == 128
136    }
137
138    pub fn empty() -> Self {
139        WhatAmIMatcher(unsafe { NonZeroU8::new_unchecked(128) })
140    }
141
142    pub fn matches(self, w: WhatAmI) -> bool {
143        (self.0.get() & w as u8) != 0
144    }
145
146    pub fn to_str(self) -> &'static str {
147        match self.0.get() {
148            128 => "",
149            129 => "router",
150            130 => "peer",
151            132 => "client",
152            131 => "router|peer",
153            134 => "client|peer",
154            133 => "client|router",
155            135 => "client|router|peer",
156            _ => "invalid_matcher",
157        }
158    }
159}
160
161impl std::str::FromStr for WhatAmIMatcher {
162    type Err = ();
163
164    fn from_str(s: &str) -> Result<Self, Self::Err> {
165        let mut inner = 128;
166        for s in s.split('|') {
167            match s.trim() {
168                "" => {}
169                "router" => inner |= WhatAmI::Router as u8,
170                "client" => inner |= WhatAmI::Client as u8,
171                "peer" => inner |= WhatAmI::Peer as u8,
172                _ => return Err(()),
173            }
174        }
175        Self::try_from(inner).ok_or(())
176    }
177}
178
179impl serde::Serialize for WhatAmIMatcher {
180    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
181    where
182        S: serde::Serializer,
183    {
184        serializer.serialize_str(self.to_str())
185    }
186}
187pub struct WhatAmIMatcherVisitor;
188impl<'de> serde::de::Visitor<'de> for WhatAmIMatcherVisitor {
189    type Value = WhatAmIMatcher;
190    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
191        formatter.write_str("a | separated list of whatami variants ('peer', 'client' or 'router')")
192    }
193    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
194    where
195        E: serde::de::Error,
196    {
197        v.parse().map_err(|_| {
198            serde::de::Error::invalid_value(
199                serde::de::Unexpected::Str(v),
200                &"a | separated list of whatami variants ('peer', 'client' or 'router')",
201            )
202        })
203    }
204    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
205    where
206        E: serde::de::Error,
207    {
208        self.visit_str(v)
209    }
210    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
211    where
212        E: serde::de::Error,
213    {
214        self.visit_str(&v)
215    }
216}
217
218impl<'de> serde::Deserialize<'de> for WhatAmIMatcher {
219    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
220    where
221        D: serde::Deserializer<'de>,
222    {
223        deserializer.deserialize_str(WhatAmIMatcherVisitor)
224    }
225}
226
227impl std::fmt::Display for WhatAmIMatcher {
228    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229        f.write_str(self.to_str())
230    }
231}
232
233impl From<WhatAmIMatcher> for ZInt {
234    fn from(w: WhatAmIMatcher) -> ZInt {
235        w.0.get() as ZInt
236    }
237}
238
239impl<T> BitOr<T> for WhatAmIMatcher
240where
241    NonZeroU8: BitOr<T, Output = NonZeroU8>,
242{
243    type Output = Self;
244    fn bitor(self, rhs: T) -> Self::Output {
245        WhatAmIMatcher(self.0 | rhs)
246    }
247}
248
249impl BitOr<WhatAmI> for WhatAmIMatcher {
250    type Output = Self;
251    fn bitor(self, rhs: WhatAmI) -> Self::Output {
252        self | rhs as u8
253    }
254}
255
256impl BitOr for WhatAmIMatcher {
257    type Output = Self;
258    fn bitor(self, rhs: Self) -> Self::Output {
259        self | rhs.0
260    }
261}
262
263impl BitOr for WhatAmI {
264    type Output = WhatAmIMatcher;
265    fn bitor(self, rhs: Self) -> Self::Output {
266        WhatAmIMatcher(unsafe { NonZeroU8::new_unchecked(self as u8 | rhs as u8 | 128) })
267    }
268}
269
270impl From<WhatAmI> for WhatAmIMatcher {
271    fn from(w: WhatAmI) -> Self {
272        WhatAmIMatcher(unsafe { NonZeroU8::new_unchecked(w as u8 | 128) })
273    }
274}