1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! Target-conditional `Send`/`Sync` bounds: real on native, vacuous on wasm32.
//!
//! The pipeline runs as *one logical task* on every target. On native that task
//! should still be `Send` so a work-stealing executor (e.g. multi-threaded
//! tokio) can spawn and migrate it like any other task. On `wasm32` there is
//! only one thread and JS handles (`JsValue`) are `!Send`, so the same bounds
//! must vanish. These aliases express "Send where it exists" once, so the rest
//! of the codebase is written a single time.
/// `Send` on native targets; no requirement on `wasm32`.
/// `Send` on native targets; no requirement on `wasm32`.
/// `Send + Sync` on native targets; no requirement on `wasm32`.
/// `Send + Sync` on native targets; no requirement on `wasm32`.
/// Apply [`async_trait`](https://docs.rs/async-trait) with the target-correct
/// `Send`-ness, in one line instead of the two-attribute `cfg_attr` dance.
///
/// Every async trait definition and impl in pipecrab needs the same pair —
/// plain `#[async_trait]` on native (its boxed futures are `Send`, matching the
/// [`MaybeSend`]/[`MaybeSendSync`] bounds), and `#[async_trait(?Send)]` on
/// `wasm32` (where they can't be). Writing both by hand is easy to get subtly
/// wrong (swap the two `cfg`s and native silently loses `Send`). Wrap the item
/// instead — the trait definition *or* the impl block:
///
/// ```
/// use pipecrab_runtime::{maybe_async_trait, MaybeSend};
///
/// maybe_async_trait! {
/// pub trait Widget: MaybeSend {
/// async fn poll(&mut self) -> u32;
/// }
/// }
///
/// struct Zero;
/// maybe_async_trait! {
/// impl Widget for Zero {
/// async fn poll(&mut self) -> u32 { 0 }
/// }
/// }
/// ```
///
/// The macro pulls in `async_trait` through this crate, so a stage or interface crate
/// that uses it needs only a `pipecrab-runtime` dependency, not a direct one on
/// `async-trait`.