rocket/util/
mod.rs
1mod chain;
2mod reader_stream;
3mod join;
4
5#[cfg(unix)]
6pub mod unix;
7
8pub use chain::Chain;
9pub use reader_stream::ReaderStream;
10pub use join::join;
11
12#[track_caller]
13pub fn spawn_inspect<E, F, Fut>(or: F, future: Fut)
14 where F: FnOnce(&E) + Send + Sync + 'static,
15 E: Send + Sync + 'static,
16 Fut: std::future::Future<Output = Result<(), E>> + Send + 'static,
17{
18 use futures::TryFutureExt;
19 tokio::spawn(future.inspect_err(or));
20}
21
22use std::{fmt, io};
23use std::pin::pin;
24use std::future::Future;
25use either::Either;
26use futures::future;
27
28pub trait FutureExt: Future + Sized {
29 async fn race<B: Future>(self, other: B) -> Either<Self::Output, B::Output> {
31 match future::select(pin!(self), pin!(other)).await {
32 future::Either::Left((v, _)) => Either::Left(v),
33 future::Either::Right((v, _)) => Either::Right(v),
34 }
35 }
36
37 async fn race_io<T, K: Future>(self, trigger: K) -> io::Result<T>
38 where Self: Future<Output = io::Result<T>>
39 {
40 match future::select(pin!(self), pin!(trigger)).await {
41 future::Either::Left((v, _)) => v,
42 future::Either::Right((_, _)) => Err(io::Error::other("i/o terminated")),
43 }
44 }
45}
46
47impl<F: Future + Sized> FutureExt for F { }
48
49pub struct Formatter<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result>(pub F);
50
51impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for Formatter<F> {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 (self.0)(f)
54 }
55}
56
57impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Display for Formatter<F> {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 (self.0)(f)
60 }
61}
62
63#[doc(hidden)]
64#[macro_export]
65macro_rules! for_both {
66 ($value:expr, $pattern:pat => $result:expr) => {
67 match $value {
68 tokio_util::either::Either::Left($pattern) => $result,
69 tokio_util::either::Either::Right($pattern) => $result,
70 }
71 };
72}
73
74pub use for_both;