use std::future::Future;
use std::time::Duration;
pub use futures_channel::oneshot::{Receiver as OneshotReceiver, Sender as OneshotSender};
pub use futures_util::lock::Mutex;
pub struct Sender<T>(async_channel::Sender<T>);
impl<T> Clone for Sender<T> {
fn clone(&self) -> Self {
Sender(self.0.clone())
}
}
impl<T> Sender<T> {
pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
self.0.send(value).await.map_err(|e| SendError(e.0))
}
pub fn try_send(&self, value: T) -> Result<(), TrySendError<T>> {
self.0.try_send(value).map_err(|e| match e {
async_channel::TrySendError::Full(v) => TrySendError::Full(v),
async_channel::TrySendError::Closed(v) => TrySendError::Closed(v),
})
}
pub fn is_closed(&self) -> bool {
self.0.is_closed()
}
}
pub struct SendError<T>(pub T);
impl<T> std::fmt::Debug for SendError<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SendError").finish_non_exhaustive()
}
}
impl<T> std::fmt::Display for SendError<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "channel closed")
}
}
impl<T> std::error::Error for SendError<T> {}
pub enum TrySendError<T> {
Full(T),
Closed(T),
}
impl<T> std::fmt::Debug for TrySendError<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TrySendError::Full(_) => f.debug_struct("TrySendError::Full").finish_non_exhaustive(),
TrySendError::Closed(_) => f
.debug_struct("TrySendError::Closed")
.finish_non_exhaustive(),
}
}
}
pub struct Receiver<T>(async_channel::Receiver<T>);
impl<T> Receiver<T> {
pub async fn recv(&mut self) -> Option<T> {
self.0.recv().await.ok()
}
}
pub type UnboundedSender<T> = Sender<T>;
pub type UnboundedReceiver<T> = Receiver<T>;
pub fn channel<T>(buffer: usize) -> (Sender<T>, Receiver<T>) {
let (tx, rx) = async_channel::bounded(buffer);
(Sender(tx), Receiver(rx))
}
pub fn unbounded_channel<T>() -> (Sender<T>, Receiver<T>) {
let (tx, rx) = async_channel::unbounded();
(Sender(tx), Receiver(rx))
}
pub fn oneshot<T>() -> (OneshotSender<T>, OneshotReceiver<T>) {
futures_channel::oneshot::channel()
}
#[derive(Debug)]
pub struct AbortHandle;
impl AbortHandle {
pub fn abort(&self) -> bool {
false
}
}
pub fn spawn<F>(future: F)
where
F: Future<Output = ()> + 'static,
{
wasm_bindgen_futures::spawn_local(future);
}
pub fn spawn_with_abort<F>(future: F) -> AbortHandle
where
F: Future<Output = ()> + 'static,
{
wasm_bindgen_futures::spawn_local(future);
AbortHandle
}
pub async fn sleep(duration: Duration) {
gloo_timers::future::sleep(duration).await;
}
pub async fn timeout<F, T>(duration: Duration, future: F) -> Option<T>
where
F: Future<Output = T>,
{
use futures_util::future::{Either, select};
use std::pin::pin;
let sleep_fut = pin!(gloo_timers::future::sleep(duration));
let work_fut = pin!(future);
match select(work_fut, sleep_fut).await {
Either::Left((result, _)) => Some(result),
Either::Right((_, _)) => None,
}
}