medea_jason/utils/
mod.rs

1//! Miscellaneous utility structs and functions.
2
3#[macro_use]
4mod errors;
5
6pub mod component;
7mod resettable_delay;
8
9use derive_more::with_trait::From;
10use futures::future::{self, AbortHandle};
11use medea_reactive::Guarded;
12
13#[doc(inline)]
14pub use self::{
15    component::{AsProtoState, Component, SynchronizableState, Updatable},
16    errors::{Caused, JsonParseError},
17    resettable_delay::{ResettableDelayHandle, resettable_delay_for},
18};
19
20/// Wrapper around [`AbortHandle`] which aborts [`Future`] on [`Drop`].
21#[derive(Debug, From)]
22pub struct TaskHandle(AbortHandle);
23
24impl Drop for TaskHandle {
25    fn drop(&mut self) {
26        self.0.abort();
27    }
28}
29
30/// Tries to upgrade [`Weak`] reference breaks cycle if upgrade fails.
31macro_rules! upgrade_or_break {
32    ($weak:tt) => {
33        if let Some(this) = $weak.upgrade() {
34            this
35        } else {
36            break;
37        }
38    };
39}
40
41/// Returns [`Future`] which will return the provided value being
42/// [`Guarded::transpose()`]d.
43///
44/// Intended for use in [`StreamExt::filter_map()`].
45///
46/// [`StreamExt::filter_map()`]: futures::StreamExt::filter_map
47pub fn transpose_guarded<T>(
48    val: Guarded<Option<T>>,
49) -> impl Future<Output = Option<Guarded<T>>> {
50    future::ready(val.transpose())
51}
52
53#[cfg(not(target_family = "wasm"))]
54/// Compares strings in `const` context.
55///
56/// As there is no `const impl Trait` and `l == r` calls [`Eq`], we have to
57/// write custom comparison function.
58///
59/// [`Eq`]: trait@Eq
60// TODO: Remove once `Eq` trait is allowed in `const` context.
61#[must_use]
62pub const fn str_eq(l: &str, r: &str) -> bool {
63    if l.len() != r.len() {
64        return false;
65    }
66
67    let (l, r) = (l.as_bytes(), r.as_bytes());
68    let mut i = 0;
69    while i < l.len() {
70        if l[i] != r[i] {
71            return false;
72        }
73        i += 1;
74    }
75
76    true
77}