Skip to main content

zenoh_keyexpr/key_expr/
owned.rs

1//
2// Copyright (c) 2023 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//
14extern crate alloc;
15
16// use crate::core::WireExpr;
17use alloc::{borrow::ToOwned, boxed::Box, string::String, sync::Arc};
18use core::{
19    convert::TryFrom,
20    fmt,
21    ops::{Deref, Div},
22    str::FromStr,
23};
24
25use super::{canon::Canonize, keyexpr, nonwild_keyexpr};
26
27/// A [`Arc<str>`] newtype that is statically known to be a valid key expression.
28///
29/// See [`keyexpr`](super::borrowed::keyexpr).
30#[derive(Clone, PartialEq, Eq, Hash, serde::Deserialize)]
31#[cfg_attr(feature = "std", derive(schemars::JsonSchema))]
32#[serde(try_from = "String")]
33pub struct OwnedKeyExpr(pub(crate) Arc<str>);
34impl serde::Serialize for OwnedKeyExpr {
35    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36    where
37        S: serde::Serializer,
38    {
39        self.0.serialize(serializer)
40    }
41}
42
43impl OwnedKeyExpr {
44    /// Equivalent to `<OwnedKeyExpr as TryFrom>::try_from(t)`.
45    ///
46    /// Will return an Err if `t` isn't a valid key expression.
47    /// Note that to be considered a valid key expression, a string MUST be canon.
48    ///
49    /// [`OwnedKeyExpr::autocanonize`] is an alternative constructor that will canonize the passed expression before constructing it.
50    pub fn new<T, E>(t: T) -> Result<Self, E>
51    where
52        Self: TryFrom<T, Error = E>,
53    {
54        Self::try_from(t)
55    }
56
57    /// Canonizes the passed value before returning it as an `OwnedKeyExpr`.
58    ///
59    /// Will return Err if the passed value isn't a valid key expression despite canonization.
60    pub fn autocanonize<T, E>(mut t: T) -> Result<Self, E>
61    where
62        Self: TryFrom<T, Error = E>,
63        T: Canonize,
64    {
65        t.canonize();
66        Self::new(t)
67    }
68
69    /// Constructs an OwnedKeyExpr without checking [`keyexpr`]'s invariants
70    /// # Safety
71    /// Key Expressions must follow some rules to be accepted by a Zenoh network.
72    /// Messages addressed with invalid key expressions will be dropped.
73    pub unsafe fn from_string_unchecked(s: String) -> Self {
74        // SAFETY: caller upholds key expression invariants for `s`.
75        unsafe { Self::from_boxed_str_unchecked(s.into_boxed_str()) }
76    }
77
78    /// Constructs an OwnedKeyExpr without checking [`keyexpr`]'s invariants
79    /// # Safety
80    /// Key Expressions must follow some rules to be accepted by a Zenoh network.
81    /// Messages addressed with invalid key expressions will be dropped.
82    pub unsafe fn from_boxed_str_unchecked(s: Box<str>) -> Self {
83        OwnedKeyExpr(s.into())
84    }
85}
86
87#[allow(clippy::suspicious_arithmetic_impl)]
88impl Div<&keyexpr> for OwnedKeyExpr {
89    type Output = Self;
90    fn div(self, rhs: &keyexpr) -> Self::Output {
91        &self / rhs
92    }
93}
94
95#[allow(clippy::suspicious_arithmetic_impl)]
96impl Div<&keyexpr> for &OwnedKeyExpr {
97    type Output = OwnedKeyExpr;
98    fn div(self, rhs: &keyexpr) -> Self::Output {
99        let s: String = [self.as_str(), "/", rhs.as_str()].concat();
100        OwnedKeyExpr::autocanonize(s).unwrap() // Joining 2 key expressions should always result in a canonizable string.
101    }
102}
103
104#[test]
105fn div() {
106    let a = OwnedKeyExpr::new("a").unwrap();
107    let b = OwnedKeyExpr::new("b").unwrap();
108    let k = a / &b;
109    assert_eq!(k.as_str(), "a/b")
110}
111
112impl fmt::Debug for OwnedKeyExpr {
113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114        self.as_ref().fmt(f)
115    }
116}
117
118impl fmt::Display for OwnedKeyExpr {
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120        self.as_ref().fmt(f)
121    }
122}
123
124impl Deref for OwnedKeyExpr {
125    type Target = keyexpr;
126    fn deref(&self) -> &Self::Target {
127        // SAFETY: upheld by the surrounding invariants and prior validation.
128        unsafe { keyexpr::from_str_unchecked(&self.0) }
129    }
130}
131
132impl AsRef<str> for OwnedKeyExpr {
133    fn as_ref(&self) -> &str {
134        &self.0
135    }
136}
137impl FromStr for OwnedKeyExpr {
138    type Err = zenoh_result::Error;
139    fn from_str(s: &str) -> Result<Self, Self::Err> {
140        Self::try_from(s.to_owned())
141    }
142}
143impl TryFrom<&str> for OwnedKeyExpr {
144    type Error = zenoh_result::Error;
145    fn try_from(s: &str) -> Result<Self, Self::Error> {
146        Self::try_from(s.to_owned())
147    }
148}
149impl TryFrom<String> for OwnedKeyExpr {
150    type Error = zenoh_result::Error;
151    fn try_from(value: String) -> Result<Self, Self::Error> {
152        <&keyexpr as TryFrom<&str>>::try_from(value.as_str())?;
153        Ok(Self(value.into()))
154    }
155}
156impl<'a> From<&'a keyexpr> for OwnedKeyExpr {
157    fn from(val: &'a keyexpr) -> Self {
158        OwnedKeyExpr(Arc::from(val.as_str()))
159    }
160}
161impl From<OwnedKeyExpr> for Arc<str> {
162    fn from(ke: OwnedKeyExpr) -> Self {
163        ke.0
164    }
165}
166impl From<OwnedKeyExpr> for String {
167    fn from(ke: OwnedKeyExpr) -> Self {
168        ke.as_str().to_owned()
169    }
170}
171
172/// A [`Arc<str>`] newtype that is statically known to be a valid nonwild key expression.
173///
174/// See [`nonwild_keyexpr`](super::borrowed::nonwild_keyexpr).
175#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Deserialize)]
176#[cfg_attr(feature = "std", derive(schemars::JsonSchema))]
177#[serde(try_from = "String")]
178pub struct OwnedNonWildKeyExpr(pub(crate) Arc<str>);
179impl serde::Serialize for OwnedNonWildKeyExpr {
180    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
181    where
182        S: serde::Serializer,
183    {
184        self.0.serialize(serializer)
185    }
186}
187
188impl TryFrom<String> for OwnedNonWildKeyExpr {
189    type Error = zenoh_result::Error;
190    fn try_from(value: String) -> Result<Self, Self::Error> {
191        let ke = <&keyexpr as TryFrom<&str>>::try_from(value.as_str())?;
192        <&nonwild_keyexpr as TryFrom<&keyexpr>>::try_from(ke)?;
193        Ok(Self(value.into()))
194    }
195}
196impl<'a> From<&'a nonwild_keyexpr> for OwnedNonWildKeyExpr {
197    fn from(val: &'a nonwild_keyexpr) -> Self {
198        OwnedNonWildKeyExpr(Arc::from(val.as_str()))
199    }
200}
201
202impl Deref for OwnedNonWildKeyExpr {
203    type Target = nonwild_keyexpr;
204    fn deref(&self) -> &Self::Target {
205        // SAFETY: upheld by the surrounding invariants and prior validation.
206        unsafe { nonwild_keyexpr::from_str_unchecked(&self.0) }
207    }
208}
209
210#[allow(clippy::suspicious_arithmetic_impl)]
211impl Div<&keyexpr> for &OwnedNonWildKeyExpr {
212    type Output = OwnedKeyExpr;
213    fn div(self, rhs: &keyexpr) -> Self::Output {
214        let s: String = [self.as_str(), "/", rhs.as_str()].concat();
215        OwnedKeyExpr::autocanonize(s).unwrap() // Joining 2 key expressions should always result in a canonizable string.
216    }
217}
218
219#[allow(clippy::suspicious_arithmetic_impl)]
220impl Div<&nonwild_keyexpr> for &OwnedNonWildKeyExpr {
221    type Output = OwnedKeyExpr;
222    fn div(self, rhs: &nonwild_keyexpr) -> Self::Output {
223        let s: String = [self.as_str(), "/", rhs.as_str()].concat();
224        s.try_into().unwrap() // Joining 2 non wild key expressions should always result in a non wild string.
225    }
226}