#![allow(clippy::type_complexity)]
use std::{fmt::Debug, future::Future, io, net::SocketAddr, pin::Pin, sync::Arc, time::Duration};
pub struct JoinHandle {
inner: Box<dyn JoinHandleInner>,
}
impl JoinHandle {
pub fn abort(&self) {
self.inner.abort();
}
pub fn is_finished(&self) -> bool {
self.inner.is_finished()
}
}
impl Drop for JoinHandle {
fn drop(&mut self) {
self.inner.detach();
}
}
trait JoinHandleInner: Send + Sync {
fn detach(&self);
fn abort(&self);
fn is_finished(&self) -> bool;
}
pub trait Runtime: Send + Sync + Debug + 'static {
#[track_caller]
fn spawn(&self, future: Pin<Box<dyn Future<Output = ()> + Send>>) -> JoinHandle;
fn wrap_udp_socket(&self, socket: std::net::UdpSocket) -> io::Result<Arc<dyn AsyncUdpSocket>>;
}
pub trait AsyncUdpSocket: Send + Sync + Debug + 'static {
fn send_to<'a>(
&'a self,
buf: &'a [u8],
target: SocketAddr,
) -> Pin<Box<dyn Future<Output = io::Result<usize>> + Send + 'a>>;
fn recv_from<'a>(
&'a self,
buf: &'a mut [u8],
) -> Pin<Box<dyn Future<Output = io::Result<(usize, SocketAddr)>> + Send + 'a>>;
fn local_addr(&self) -> io::Result<SocketAddr>;
}
pub trait AsyncMutex<T: ?Sized>: Send + Sync {
type Guard<'a>: std::ops::Deref<Target = T> + std::ops::DerefMut + Send + 'a
where
Self: 'a,
T: 'a;
fn lock(&self) -> Pin<Box<dyn Future<Output = Self::Guard<'_>> + Send + '_>>;
}
pub trait AsyncNotify: Send + Sync {
fn notify_one(&self);
fn notify_waiters(&self);
fn notified(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>;
}
pub trait AsyncSender<T>: Send + Sync {
fn send(&self, value: T)
-> Pin<Box<dyn Future<Output = Result<(), SendError<T>>> + Send + '_>>;
fn try_send(&self, value: T) -> Result<(), TrySendError<T>>;
}
pub trait AsyncReceiver<T>: Send {
fn recv(&mut self) -> Pin<Box<dyn Future<Output = Option<T>> + Send + '_>>;
fn try_recv(&mut self) -> Result<T, TryRecvError>;
}
#[derive(Debug)]
pub struct SendError<T>(pub T);
#[derive(Debug)]
pub enum TrySendError<T> {
Full(T),
Disconnected(T),
}
#[derive(Debug)]
pub enum TryRecvError {
Empty,
Disconnected,
}
impl<T> std::fmt::Display for SendError<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "channel disconnected")
}
}
impl<T: std::fmt::Debug> std::error::Error for SendError<T> {}
#[derive(Debug)]
pub struct BroadcastSendError<T>(pub T);
#[derive(Debug)]
pub enum BroadcastRecvError {
Closed,
Lagged(u64),
}
impl<T> std::fmt::Display for BroadcastSendError<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "broadcast send failed: no receivers")
}
}
impl<T: std::fmt::Debug> std::error::Error for BroadcastSendError<T> {}
impl std::fmt::Display for BroadcastRecvError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BroadcastRecvError::Closed => write!(f, "broadcast channel closed"),
BroadcastRecvError::Lagged(n) => write!(f, "broadcast receiver lagged by {n}"),
}
}
}
impl std::error::Error for BroadcastRecvError {}
#[cfg(any(feature = "runtime-tokio", feature = "runtime-smol"))]
pub fn default_runtime() -> Option<std::sync::Arc<dyn Runtime>> {
#[cfg(feature = "runtime-tokio")]
{
Some(std::sync::Arc::new(TokioRuntime))
}
#[cfg(all(not(feature = "runtime-tokio"), feature = "runtime-smol"))]
{
Some(std::sync::Arc::new(SmolRuntime))
}
}
#[cfg(not(any(feature = "runtime-tokio", feature = "runtime-smol")))]
pub fn default_runtime() -> Option<std::sync::Arc<dyn Runtime>> {
None
}
#[cfg(any(feature = "runtime-tokio", feature = "runtime-smol"))]
pub fn smol_runtime() -> Option<std::sync::Arc<dyn Runtime>> {
#[cfg(feature = "runtime-smol")]
{
Some(std::sync::Arc::new(SmolRuntime))
}
#[cfg(not(feature = "runtime-smol"))]
None
}
#[cfg(feature = "runtime-tokio")]
mod tokio;
#[cfg(feature = "runtime-tokio")]
pub use tokio::TokioRuntime;
#[cfg(feature = "runtime-tokio")]
pub use tokio::{
TokioInterval, block_on, broadcast_channel, channel, interval, resolve_host, sleep, timeout,
};
#[cfg(feature = "runtime-tokio")]
pub type Interval = TokioInterval;
#[cfg(feature = "runtime-tokio")]
pub type Mutex<T> = tokio::TokioMutex<T>;
#[cfg(feature = "runtime-tokio")]
pub type Notify = tokio::TokioNotify;
#[cfg(feature = "runtime-tokio")]
pub type Sender<T> = tokio::TokioSender<T>;
#[cfg(feature = "runtime-tokio")]
pub type Receiver<T> = tokio::TokioReceiver<T>;
#[cfg(feature = "runtime-tokio")]
pub type BroadcastSender<T> = tokio::TokioBroadcastSender<T>;
#[cfg(feature = "runtime-tokio")]
pub type BroadcastReceiver<T> = tokio::TokioBroadcastReceiver<T>;
#[cfg(feature = "runtime-smol")]
mod smol;
#[cfg(feature = "runtime-smol")]
pub use smol::SmolRuntime;
#[cfg(feature = "runtime-smol")]
pub use smol::{
SmolInterval, block_on, broadcast_channel, channel, interval, resolve_host, sleep, timeout,
};
#[cfg(feature = "runtime-smol")]
pub type Interval = SmolInterval;
#[cfg(feature = "runtime-smol")]
pub type Mutex<T> = smol::SmolMutex<T>;
#[cfg(feature = "runtime-smol")]
pub type Notify = smol::SmolNotify;
#[cfg(feature = "runtime-smol")]
pub type Sender<T> = smol::SmolSender<T>;
#[cfg(feature = "runtime-smol")]
pub type Receiver<T> = smol::SmolReceiver<T>;
#[cfg(feature = "runtime-smol")]
pub type BroadcastSender<T> = smol::SmolBroadcastSender<T>;
#[cfg(feature = "runtime-smol")]
pub type BroadcastReceiver<T> = smol::SmolBroadcastReceiver<T>;