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
//! Thin veneer over `futures::channel::oneshot` to fix use with [`select!`](futures::select)
//!
//! A bare [`futures::channel::oneshot::Receiver`] doesn't work properly with
//! `futures::select!`, because it has a broken
//! [`FusedFuture`](futures::future::FusedFuture)
//! implementation.
//! (See [`futures-rs` ticket #2455](https://github.com/rust-lang/futures-rs/issues/2455).)
//!
//! Wrapping it up in a [`future::Fuse`](futures::future::Fuse) works around this,
//! with a minor performance penalty.
//!
//! ### Limitations
//!
//! The API of this [`Receiver`] is rather more limited.
//! For example, it lacks `.try_recv()`.
//
// The veneer is rather thin and the types from `futures-rs` show through.
// If we change this in the future, it will be a breaking change.

use futures::channel::oneshot as fut_oneshot;
use futures::FutureExt as _;

pub use fut_oneshot::Canceled;

/// `oneshot::Sender` type alias
//
// This has to be `pub type` rather than `pub use` so that
// (i) call sites don't trip the "disallowed types" lint
// (ii) we can apply a fine-grained allow, here.
#[allow(clippy::disallowed_types)]
pub type Sender<T> = fut_oneshot::Sender<T>;

/// `oneshot::Receiver` that works properly with [`futures::select!`]
#[allow(clippy::disallowed_types)]
pub type Receiver<T> = futures::future::Fuse<fut_oneshot::Receiver<T>>;

/// Return a fresh oneshot channel
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    #[allow(clippy::disallowed_methods)]
    let (tx, rx) = fut_oneshot::channel();
    (tx, rx.fuse())
}