1use bytes::Bytes;
9use std::pin::Pin;
10
11use futures::Stream;
12
13#[cfg(all(
16 target_arch = "wasm32",
17 target_os = "unknown",
18 target_feature = "atomics"
19))]
20compile_error!(
21 "rig-http does not support threaded wasm (`+atomics`): its wasm-compat markers assume a \
22 single-threaded target"
23);
24
25#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
26#[diagnostic::on_unimplemented(
36 message = "`{Self}` is not `Send`, and Rig needs `Send` natively",
37 label = "not `Send`",
38 note = "handlers and transports run inside a driver's task: hold shared state behind an `Arc` (never an `Rc`), or use a `!Send` value only on browser wasm, where this marker is a no-op"
39)]
40pub trait WasmCompatSend: Send {}
41#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
42pub trait WasmCompatSend {}
44
45#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
46impl<T> WasmCompatSend for T where T: Send {}
47#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
48impl<T> WasmCompatSend for T {}
49
50#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
51pub trait WasmCompatSendStream:
53 Stream<Item = Result<Bytes, crate::http_client::Error>> + Send
54{
55 type InnerItem: Send;
56}
57
58#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
59pub trait WasmCompatSendStream: Stream<Item = Result<Bytes, crate::http_client::Error>> {
61 type InnerItem;
62}
63
64#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
65impl<T> WasmCompatSendStream for T
66where
67 T: Stream<Item = Result<Bytes, crate::http_client::Error>> + Send,
68{
69 type InnerItem = Result<Bytes, crate::http_client::Error>;
70}
71
72#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
73impl<T> WasmCompatSendStream for T
74where
75 T: Stream<Item = Result<Bytes, crate::http_client::Error>>,
76{
77 type InnerItem = Result<Bytes, crate::http_client::Error>;
78}
79
80#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
81#[diagnostic::on_unimplemented(
91 message = "`{Self}` is not `Sync`, and Rig needs `Sync` natively",
92 label = "not `Sync`",
93 note = "handlers and transports are shared between a driver and its in-flight tasks: use `Mutex`/atomics instead of `Cell`/`RefCell`, or use a `!Sync` value only on browser wasm, where this marker is a no-op"
94)]
95pub trait WasmCompatSync: Sync {}
96#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
97pub trait WasmCompatSync {}
99
100#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
101impl<T> WasmCompatSync for T where T: Sync {}
102#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
103impl<T> WasmCompatSync for T {}
104
105#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
106pub type WasmBoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
108
109#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
110pub type WasmBoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
112
113#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
114pub type WasmBoxedStream<'a, T> = Pin<Box<dyn Stream<Item = T> + Send + 'a>>;
116
117#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
118pub type WasmBoxedStream<'a, T> = Pin<Box<dyn Stream<Item = T> + 'a>>;
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123pub struct Elapsed;
124
125impl std::fmt::Display for Elapsed {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 f.write_str("future timed out")
128 }
129}
130
131impl std::error::Error for Elapsed {}
132
133pub async fn timeout<F>(duration: std::time::Duration, future: F) -> Result<F::Output, Elapsed>
141where
142 F: Future,
143{
144 use futures::future::{Either, select};
145
146 let delay = futures_timer::Delay::new(duration);
147 futures::pin_mut!(future);
148 futures::pin_mut!(delay);
149 match select(future, delay).await {
150 Either::Left((output, _)) => Ok(output),
151 Either::Right(((), _)) => Err(Elapsed),
152 }
153}
154
155pub async fn sleep(duration: std::time::Duration) {
160 futures_timer::Delay::new(duration).await;
161}
162
163#[cfg(test)]
164mod tests;