1use std::{
15 convert::{TryFrom, TryInto},
16 future::{IntoFuture, Ready},
17 str::FromStr,
18 sync::Arc,
19};
20
21use zenoh_core::{Resolvable, Wait};
22use zenoh_keyexpr::{keyexpr, OwnedKeyExpr};
23use zenoh_protocol::{
24 core::{key_expr::canon::Canonize, ExprId, WireExpr},
25 network::Mapping,
26};
27use zenoh_result::ZResult;
28
29use crate::api::session::{Session, UndeclarableSealed, WeakSession};
30
31#[derive(Debug)]
32pub(crate) struct KeyExprWireDeclaration {
33 expr_id: ExprId,
34 prefix_len: u32,
35 session: WeakSession,
36 undeclared: bool,
37}
38
39impl KeyExprWireDeclaration {
40 pub(crate) fn new(prefix: &str, session: &Session, force: bool) -> ZResult<Option<Self>> {
41 let prefix_len = prefix.len() as u32;
42 Ok(session
43 .declare_prefix(prefix, force)
44 .wait()?
45 .map(|expr_id| Self {
46 expr_id,
47 prefix_len,
48 session: session.downgrade(),
49 undeclared: false,
50 }))
51 }
52
53 pub(crate) fn undeclare(&mut self) -> ZResult<()> {
54 if self.undeclared {
55 Ok(())
56 } else {
57 self.undeclared = true;
58 self.session.undeclare_prefix(self.expr_id)
59 }
60 }
61}
62
63impl Drop for KeyExprWireDeclaration {
64 fn drop(&mut self) {
65 let _ = self.undeclare();
66 }
67}
68
69#[derive(Clone, Debug)]
70pub(crate) enum KeyExprInner<'a> {
71 Borrowed {
72 key_expr: &'a keyexpr,
73 declaration: Option<Arc<KeyExprWireDeclaration>>,
74 },
75 Owned {
76 key_expr: OwnedKeyExpr,
77 declaration: Option<Arc<KeyExprWireDeclaration>>,
78 },
79}
80
81#[repr(transparent)]
85#[derive(Clone, serde::Deserialize, serde::Serialize)]
86#[serde(from = "OwnedKeyExpr")]
87#[serde(into = "OwnedKeyExpr")]
88pub struct KeyExpr<'a>(pub(crate) KeyExprInner<'a>);
89
90impl<'a> std::panic::RefUnwindSafe for KeyExpr<'a> {}
94impl<'a> std::panic::UnwindSafe for KeyExpr<'a> {}
95
96impl std::ops::Deref for KeyExpr<'_> {
97 type Target = keyexpr;
98 fn deref(&self) -> &Self::Target {
99 match &self.0 {
100 KeyExprInner::Borrowed { key_expr, .. } => key_expr,
101 KeyExprInner::Owned { key_expr, .. } => key_expr,
102 }
103 }
104}
105
106impl KeyExpr<'static> {
107 pub unsafe fn from_string_unchecked(s: String) -> Self {
112 Self(KeyExprInner::Owned {
113 key_expr: OwnedKeyExpr::from_string_unchecked(s),
114 declaration: None,
115 })
116 }
117
118 pub unsafe fn from_boxed_str_unchecked(s: Box<str>) -> Self {
123 Self(KeyExprInner::Owned {
124 key_expr: OwnedKeyExpr::from_boxed_str_unchecked(s),
125 declaration: None,
126 })
127 }
128}
129
130#[zenoh_macros::internal]
131static KEYEXPR_DUMMY: &keyexpr = unsafe { keyexpr::from_str_unchecked("dummy") };
132
133impl<'a> KeyExpr<'a> {
134 pub fn new<T, E>(t: T) -> Result<Self, E>
141 where
142 Self: TryFrom<T, Error = E>,
143 {
144 Self::try_from(t)
145 }
146
147 #[zenoh_macros::internal]
151 pub fn dummy() -> Self {
152 Self(KeyExprInner::Borrowed {
153 key_expr: KEYEXPR_DUMMY,
154 declaration: None,
155 })
156 }
157
158 #[zenoh_macros::internal]
162 pub fn is_dummy(&self) -> bool {
163 let Self(inner) = self;
164 let KeyExprInner::Borrowed { key_expr, .. } = inner else {
165 return false;
166 };
167 std::ptr::eq(*key_expr, KEYEXPR_DUMMY)
168 }
169
170 pub fn borrowing_clone(&'a self) -> Self {
174 let inner = match &self.0 {
175 KeyExprInner::Borrowed {
176 key_expr,
177 declaration,
178 } => KeyExprInner::Borrowed {
179 key_expr,
180 declaration: declaration.clone(),
181 },
182 KeyExprInner::Owned {
183 key_expr,
184 declaration,
185 } => KeyExprInner::Borrowed {
186 key_expr,
187 declaration: declaration.clone(),
188 },
189 };
190 Self(inner)
191 }
192
193 pub fn autocanonize<T, E>(mut t: T) -> Result<Self, E>
197 where
198 Self: TryFrom<T, Error = E>,
199 T: Canonize,
200 {
201 t.canonize();
202 Self::new(t)
203 }
204
205 pub unsafe fn from_str_unchecked(s: &'a str) -> Self {
210 keyexpr::from_str_unchecked(s).into()
211 }
212
213 pub fn as_keyexpr(&self) -> &keyexpr {
215 self
216 }
217
218 pub fn into_owned(self) -> KeyExpr<'static> {
220 let inner = match self.0 {
221 KeyExprInner::Borrowed {
222 key_expr,
223 declaration,
224 } => KeyExprInner::Owned {
225 key_expr: key_expr.into(),
226 declaration: declaration.clone(),
227 },
228 KeyExprInner::Owned {
229 key_expr,
230 declaration,
231 } => KeyExprInner::Owned {
232 key_expr,
233 declaration,
234 },
235 };
236 KeyExpr(inner)
237 }
238
239 pub fn join<S: AsRef<str> + ?Sized>(&self, s: &S) -> ZResult<KeyExpr<'static>> {
253 Ok(KeyExpr(KeyExprInner::Owned {
254 key_expr: self.as_keyexpr().join(s)?,
255 declaration: self.declaration().clone(),
256 }))
257 }
258
259 pub fn concat<S: AsRef<str> + ?Sized>(&self, s: &S) -> ZResult<KeyExpr<'static>> {
263 let s = s.as_ref();
264 if self.ends_with('*') && s.starts_with('*') {
265 bail!("Tried to concatenate {} (ends with *) and {} (starts with *), which would likely have caused bugs. If you're sure you want to do this, concatenate these into a string and then try to convert.", self, s)
266 }
267 Ok(KeyExpr(KeyExprInner::Owned {
268 key_expr: OwnedKeyExpr::try_from(format!("{self}{s}"))?,
269 declaration: self.declaration().clone(),
270 }))
271 }
272
273 #[inline]
275 pub(crate) fn keyexpr_include<'b, L, R>(left: L, right: R) -> bool
276 where
277 L: TryInto<KeyExpr<'a>>,
278 R: TryInto<KeyExpr<'b>>,
279 L::Error: std::fmt::Display,
280 R::Error: std::fmt::Display,
281 {
282 match left.try_into() {
283 Ok(l) => match right.try_into() {
284 Ok(r) => {
285 return l.includes(&r);
286 }
287 Err(e) => {
288 tracing::error!("{e}");
289 }
290 },
291 Err(e) => {
292 tracing::error!("{e}");
293 }
294 }
295 false
296 }
297}
298
299impl FromStr for KeyExpr<'static> {
300 type Err = zenoh_result::Error;
301 fn from_str(s: &str) -> Result<Self, Self::Err> {
302 Ok(Self(KeyExprInner::Owned {
303 key_expr: s.parse()?,
304 declaration: None,
305 }))
306 }
307}
308
309impl<'a> From<KeyExpr<'a>> for OwnedKeyExpr {
310 fn from(val: KeyExpr<'a>) -> Self {
311 match val.0 {
312 KeyExprInner::Borrowed { key_expr, .. } => key_expr.into(),
313 KeyExprInner::Owned { key_expr, .. } => key_expr,
314 }
315 }
316}
317impl AsRef<keyexpr> for KeyExpr<'_> {
318 fn as_ref(&self) -> &keyexpr {
319 self
320 }
321}
322impl AsRef<str> for KeyExpr<'_> {
323 fn as_ref(&self) -> &str {
324 self
325 }
326}
327impl<'a> From<&'a keyexpr> for KeyExpr<'a> {
328 fn from(key_expr: &'a keyexpr) -> Self {
329 Self(KeyExprInner::Borrowed {
330 key_expr,
331 declaration: None,
332 })
333 }
334}
335impl From<OwnedKeyExpr> for KeyExpr<'_> {
336 fn from(key_expr: OwnedKeyExpr) -> Self {
337 Self(KeyExprInner::Owned {
338 key_expr,
339 declaration: None,
340 })
341 }
342}
343impl<'a> From<&'a OwnedKeyExpr> for KeyExpr<'a> {
344 fn from(key_expr: &'a OwnedKeyExpr) -> Self {
345 Self(KeyExprInner::Borrowed {
346 key_expr,
347 declaration: None,
348 })
349 }
350}
351impl<'a> From<&'a KeyExpr<'a>> for KeyExpr<'a> {
352 fn from(val: &'a KeyExpr<'a>) -> Self {
353 Self(KeyExprInner::Borrowed {
354 key_expr: val.key_expr(),
355 declaration: val.declaration().clone(),
356 })
357 }
358}
359impl From<KeyExpr<'_>> for String {
360 fn from(ke: KeyExpr) -> Self {
361 match ke.0 {
362 KeyExprInner::Borrowed { key_expr, .. } => key_expr.as_str().to_owned(),
363 KeyExprInner::Owned { key_expr, .. } => key_expr.into(),
364 }
365 }
366}
367
368impl TryFrom<String> for KeyExpr<'_> {
369 type Error = zenoh_result::Error;
370 fn try_from(value: String) -> Result<Self, Self::Error> {
371 Ok(Self(KeyExprInner::Owned {
372 key_expr: value.try_into()?,
373 declaration: None,
374 }))
375 }
376}
377impl<'a> TryFrom<&'a String> for KeyExpr<'a> {
378 type Error = zenoh_result::Error;
379 fn try_from(value: &'a String) -> Result<Self, Self::Error> {
380 Self::try_from(value.as_str())
381 }
382}
383impl<'a> TryFrom<&'a mut String> for KeyExpr<'a> {
384 type Error = zenoh_result::Error;
385 fn try_from(value: &'a mut String) -> Result<Self, Self::Error> {
386 Ok(Self::from(keyexpr::new(value)?))
387 }
388}
389impl<'a> TryFrom<&'a str> for KeyExpr<'a> {
390 type Error = zenoh_result::Error;
391 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
392 Ok(Self(KeyExprInner::Borrowed {
393 key_expr: value.try_into()?,
394 declaration: None,
395 }))
396 }
397}
398impl<'a> TryFrom<&'a mut str> for KeyExpr<'a> {
399 type Error = zenoh_result::Error;
400 fn try_from(value: &'a mut str) -> Result<Self, Self::Error> {
401 Ok(Self(KeyExprInner::Borrowed {
402 key_expr: value.try_into()?,
403 declaration: None,
404 }))
405 }
406}
407impl std::fmt::Debug for KeyExpr<'_> {
408 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
409 std::fmt::Debug::fmt(self.as_keyexpr(), f)
410 }
411}
412impl std::fmt::Display for KeyExpr<'_> {
413 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
414 std::fmt::Display::fmt(self.as_keyexpr(), f)
415 }
416}
417impl PartialEq for KeyExpr<'_> {
418 fn eq(&self, other: &Self) -> bool {
419 self.as_keyexpr() == other.as_keyexpr()
420 }
421}
422impl<T: PartialEq<keyexpr>> PartialEq<T> for KeyExpr<'_> {
423 fn eq(&self, other: &T) -> bool {
424 other == self.as_keyexpr()
425 }
426}
427impl Eq for KeyExpr<'_> {}
428impl std::hash::Hash for KeyExpr<'_> {
429 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
430 self.as_keyexpr().hash(state);
431 }
432}
433
434impl std::ops::Div<&keyexpr> for KeyExpr<'_> {
435 type Output = KeyExpr<'static>;
436
437 fn div(self, rhs: &keyexpr) -> Self::Output {
438 KeyExpr(KeyExprInner::Owned {
439 key_expr: self.key_expr() / rhs,
440 declaration: self.into_declaration(),
441 })
442 }
443}
444impl std::ops::Div<&keyexpr> for &KeyExpr<'_> {
445 type Output = KeyExpr<'static>;
446
447 fn div(self, rhs: &keyexpr) -> Self::Output {
448 KeyExpr(KeyExprInner::Owned {
449 key_expr: self.key_expr() / rhs,
450 declaration: self.declaration().clone(),
451 })
452 }
453}
454
455impl<'a> KeyExpr<'a> {
456 fn declaration(&self) -> &Option<Arc<KeyExprWireDeclaration>> {
457 match &self.0 {
458 KeyExprInner::Borrowed { declaration, .. } => declaration,
459 KeyExprInner::Owned { declaration, .. } => declaration,
460 }
461 }
462
463 fn declaration_mut(&mut self) -> &mut Option<Arc<KeyExprWireDeclaration>> {
464 match &mut self.0 {
465 KeyExprInner::Borrowed { declaration, .. } => declaration,
466 KeyExprInner::Owned { declaration, .. } => declaration,
467 }
468 }
469
470 pub(crate) fn declare(mut self, session: &Session, force: bool) -> ZResult<Self> {
471 if !self.is_fully_optimized(session) {
472 *self.declaration_mut() =
473 KeyExprWireDeclaration::new(self.as_str(), session, force)?.map(Arc::new);
474 }
475 Ok(self)
476 }
477
478 pub(crate) fn declare_nonwild_prefix(
479 mut self,
480 session: &Session,
481 force: bool,
482 ) -> ZResult<Self> {
483 if !self.is_non_wild_prefix_optimized(session) {
484 let ke = self.as_keyexpr();
485 *self.declaration_mut() = match ke.get_nonwild_prefix() {
486 Some(prefix) => {
487 KeyExprWireDeclaration::new(prefix.as_str(), session, force)?.map(Arc::new)
488 }
489 None => None,
490 }
491 }
492 Ok(self)
493 }
494
495 fn into_declaration(self) -> Option<Arc<KeyExprWireDeclaration>> {
496 match self.0 {
497 KeyExprInner::Borrowed { declaration, .. } => declaration,
498 KeyExprInner::Owned { declaration, .. } => declaration,
499 }
500 }
501
502 pub(crate) fn key_expr(&self) -> &keyexpr {
503 match &self.0 {
504 KeyExprInner::Borrowed { key_expr, .. } => key_expr,
505 KeyExprInner::Owned { key_expr, .. } => key_expr,
506 }
507 }
508
509 pub(crate) fn is_fully_optimized(&self, session: &Session) -> bool {
510 self.declaration()
511 .as_ref()
512 .map(|d| d.session == *session && d.prefix_len as usize == self.key_expr().len())
513 .unwrap_or(false)
514 }
515
516 pub(crate) fn is_non_wild_prefix_optimized(&self, session: &Session) -> bool {
517 self.declaration()
518 .as_ref()
519 .map(|d| {
520 d.session == *session
521 && self
522 .key_expr()
523 .get_nonwild_prefix()
524 .map(|p| p.len() == d.prefix_len as usize)
525 .unwrap_or(d.prefix_len == 0)
526 })
527 .unwrap_or(false)
528 }
529
530 fn to_wire_inner(&'a self, session: &Session, mapping: Mapping) -> WireExpr<'a> {
531 match self.declaration() {
532 Some(d) if d.session == *session => WireExpr {
533 scope: d.expr_id,
534 suffix: std::borrow::Cow::Borrowed(
535 &self.key_expr().as_str()[(d.prefix_len as usize)..],
536 ),
537 mapping,
538 },
539 _ => WireExpr {
540 scope: 0,
541 suffix: std::borrow::Cow::Borrowed(self.key_expr().as_str()),
542 mapping,
543 },
544 }
545 }
546
547 pub(crate) fn to_wire(&'a self, session: &Session) -> WireExpr<'a> {
548 self.to_wire_inner(session, Mapping::Sender)
549 }
550
551 pub(crate) fn to_wire_local(&'a self, session: &Session) -> WireExpr<'a> {
552 self.to_wire_inner(session, Mapping::Receiver)
553 }
554
555 fn undeclare_with_session_check(&mut self, parent_session: Option<&Session>) -> ZResult<()> {
556 match self.declaration_mut().take() {
557 Some(mut d) if self.key_expr().len() == d.prefix_len as usize => {
558 if parent_session.is_some_and(|s| d.session == *s) {
559 Arc::get_mut(&mut d).map(|d| d.undeclare()).unwrap_or(Ok(()))
560 } else {
561 let expr_id = self.declaration_mut().insert(d).expr_id;
562 Err(zerror!(
563 "Failed to undeclare expr with id {}, as it was declared by another Session",
564 expr_id
565 )
566 .into())
567 }
568 },
569 _ => Err(zerror!("Failed to undeclare {}, make sure you use the result of `Session::declare_keyexpr` to call `Session::undeclare`, and that key_expression was not undeclared previously", self).into()),
570 }
571 }
572}
573
574impl<'a> UndeclarableSealed<&'a Session> for KeyExpr<'a> {
575 type Undeclaration = KeyExprUndeclaration<'a>;
576
577 fn undeclare_inner(self, session: &'a Session) -> Self::Undeclaration {
578 KeyExprUndeclaration {
579 session,
580 expr: self,
581 }
582 }
583}
584
585#[must_use = "Resolvables do nothing unless you resolve them using `.await` or `zenoh::Wait::wait`"]
598pub struct KeyExprUndeclaration<'a> {
599 session: &'a Session,
600 expr: KeyExpr<'a>,
601}
602
603impl Resolvable for KeyExprUndeclaration<'_> {
604 type To = ZResult<()>;
605}
606
607impl Wait for KeyExprUndeclaration<'_> {
608 fn wait(self) -> <Self as Resolvable>::To {
609 let KeyExprUndeclaration { session, mut expr } = self;
610 expr.undeclare_with_session_check(Some(session))
611 }
612}
613
614impl IntoFuture for KeyExprUndeclaration<'_> {
615 type Output = <Self as Resolvable>::To;
616 type IntoFuture = Ready<<Self as Resolvable>::To>;
617
618 fn into_future(self) -> Self::IntoFuture {
619 std::future::ready(self.wait())
620 }
621}
622
623#[cfg(target_pointer_width = "64")]
624#[allow(non_snake_case)]
625#[test]
626fn size_of_KeyExpr() {
627 assert_eq!(
628 std::mem::size_of::<KeyExpr>(),
629 4 * std::mem::size_of::<usize>()
630 );
631 assert_eq!(
632 std::mem::size_of::<Option<KeyExpr>>(),
633 4 * std::mem::size_of::<usize>()
634 );
635}