Skip to main content

zenoh_core/
lib.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//
14
15//! ⚠️ WARNING ⚠️
16//!
17//! This crate is intended for Zenoh's internal use.
18//!
19//! [Click here for Zenoh's documentation](https://docs.rs/zenoh/latest/zenoh)
20pub use lazy_static::lazy_static;
21pub mod macros;
22
23use std::future::{Future, IntoFuture, Ready};
24
25// Re-exports after moving ZError/ZResult to zenoh-result
26pub use zenoh_result::{bail, to_zerror, zerror};
27pub mod zresult {
28    pub use zenoh_result::*;
29}
30pub use zresult::{Error, ZResult as Result};
31
32/// A resolvable execution, either sync or async
33pub trait Resolvable {
34    type To: Sized;
35}
36
37/// Trick used to mark `<Resolve as IntoFuture>::IntoFuture` bound as Send
38#[doc(hidden)]
39pub trait IntoSendFuture: Resolvable {
40    type IntoFuture: Future<Output = Self::To> + Send;
41}
42
43impl<T> IntoSendFuture for T
44where
45    T: Resolvable + IntoFuture<Output = Self::To>,
46    T::IntoFuture: Send,
47{
48    type IntoFuture = T::IntoFuture;
49}
50
51/// Synchronous execution of a resolvable
52pub trait Wait: Resolvable {
53    /// Synchronously execute and wait
54    fn wait(self) -> Self::To;
55}
56
57/// Zenoh's trait for resolving builder patterns.
58///
59/// Builder patterns in Zenoh can be resolved by awaiting them, in async context,
60/// and [`Wait::wait`] in sync context.
61/// We advise to prefer the usage of asynchronous execution, and to use synchronous one with caution
62#[must_use = "Resolvables do nothing unless you resolve them using `.await` or `zenoh::Wait::wait`"]
63pub trait Resolve<Output>:
64    Resolvable<To = Output>
65    + Wait
66    + IntoSendFuture
67    + IntoFuture<IntoFuture = <Self as IntoSendFuture>::IntoFuture, Output = Output>
68    + Send
69{
70}
71
72impl<T, Output> Resolve<Output> for T where
73    T: Resolvable<To = Output>
74        + Wait
75        + IntoSendFuture
76        + IntoFuture<IntoFuture = <Self as IntoSendFuture>::IntoFuture, Output = Output>
77        + Send
78{
79}
80
81// Closure to wait
82#[must_use = "Resolvables do nothing unless you resolve them using `.await` or `zenoh::Wait::wait`"]
83pub struct ResolveClosure<C, To>(C)
84where
85    To: Sized + Send,
86    C: FnOnce() -> To + Send;
87
88impl<C, To> std::fmt::Debug for ResolveClosure<C, To>
89where
90    To: Sized + Send,
91    C: FnOnce() -> To + Send,
92{
93    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94        f.debug_tuple("ResolveClosure").field(&"..").finish()
95    }
96}
97
98impl<C, To> ResolveClosure<C, To>
99where
100    To: Sized + Send,
101    C: FnOnce() -> To + Send,
102{
103    pub fn new(c: C) -> Self {
104        Self(c)
105    }
106}
107
108impl<C, To> Resolvable for ResolveClosure<C, To>
109where
110    To: Sized + Send,
111    C: FnOnce() -> To + Send,
112{
113    type To = To;
114}
115
116impl<C, To> IntoFuture for ResolveClosure<C, To>
117where
118    To: Sized + Send,
119    C: FnOnce() -> To + Send,
120{
121    type Output = <Self as Resolvable>::To;
122    type IntoFuture = Ready<<Self as Resolvable>::To>;
123
124    fn into_future(self) -> Self::IntoFuture {
125        std::future::ready(self.wait())
126    }
127}
128
129impl<C, To> Wait for ResolveClosure<C, To>
130where
131    To: Sized + Send,
132    C: FnOnce() -> To + Send,
133{
134    fn wait(self) -> <Self as Resolvable>::To {
135        self.0()
136    }
137}
138
139// Future to wait
140#[must_use = "Resolvables do nothing unless you resolve them using `.await` or `zenoh::Wait::wait`"]
141pub struct ResolveFuture<F, To>(F)
142where
143    To: Sized + Send,
144    F: Future<Output = To> + Send;
145
146impl<F, To> std::fmt::Debug for ResolveFuture<F, To>
147where
148    To: Sized + Send,
149    F: Future<Output = To> + Send,
150{
151    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152        f.debug_tuple("ResolveFuture").field(&"..").finish()
153    }
154}
155
156impl<F, To> ResolveFuture<F, To>
157where
158    To: Sized + Send,
159    F: Future<Output = To> + Send,
160{
161    pub fn new(f: F) -> Self {
162        Self(f)
163    }
164}
165
166impl<F, To> Resolvable for ResolveFuture<F, To>
167where
168    To: Sized + Send,
169    F: Future<Output = To> + Send,
170{
171    type To = To;
172}
173
174impl<F, To> IntoFuture for ResolveFuture<F, To>
175where
176    To: Sized + Send,
177    F: Future<Output = To> + Send,
178{
179    type Output = To;
180    type IntoFuture = F;
181
182    fn into_future(self) -> Self::IntoFuture {
183        self.0
184    }
185}
186
187impl<F, To> Wait for ResolveFuture<F, To>
188where
189    To: Sized + Send,
190    F: Future<Output = To> + Send,
191{
192    fn wait(self) -> <Self as Resolvable>::To {
193        zenoh_runtime::ZRuntime::Application.block_in_place(self.0)
194    }
195}
196
197pub use zenoh_result::{likely, unlikely};
198
199/// Re-definitions of inaccessible [`std`] items for MSRV compatibility.
200///
201/// These definitions are likely to cause `incompatible_msrv` warnings from clippy,
202/// see <https://github.com/rust-lang/rust-clippy/issues/12280>.
203pub mod polyfill {
204    // TODO: use rustversion?
205
206    // NOTE: `Option::is_none_or` was stabilized in 1.82.0 > 1.75.0
207    #[allow(clippy::wrong_self_convention)]
208    pub trait OptionExt<T>: Sized {
209        fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool;
210    }
211
212    impl<T> OptionExt<T> for Option<T> {
213        fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
214            match self {
215                None => true,
216                Some(x) => f(x),
217            }
218        }
219    }
220}
221
222/// Asserts that the LHS expression implies the RHS expression.
223///
224/// Note that in logic, `p ⟹ q` is equivalent to `¬p ∨ q` (i.e. `!p || q`).
225#[macro_export]
226macro_rules! debug_assert_implies {
227    ($lhs:expr, $rhs:expr) => {
228        debug_assert!(!$lhs || $rhs)
229    };
230}
231
232/// Panics with the given message in debug mode or logs an error otherwise.
233#[macro_export]
234macro_rules! bug {
235    ($msg:literal) => {
236        if cfg!(debug_assertions) {
237            assert!(false, $msg);
238        } else {
239            tracing::error!(target: "zenoh::bug", $msg);
240        }
241    };
242}