#![no_std]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(docsrs, feature(doc_cfg_hide))]
#![cfg_attr(docsrs, doc(cfg_hide(doc)))]
use core::{
pin::Pin,
task::{Context, Poll},
};
use futures_sink::Sink;
pub trait RouteSink<Route, Msg> {
type Error;
fn poll_ready(
self: Pin<&mut Self>,
route: &Route,
cx: &mut Context<'_>,
) -> Poll<Result<(), Self::Error>>;
fn poll_ready_any(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let _ = cx;
Poll::Pending
}
fn start_send(self: Pin<&mut Self>, route: Route, msg: Msg) -> Result<(), Self::Error>;
fn poll_flush(
self: Pin<&mut Self>,
route: &Route,
cx: &mut Context<'_>,
) -> Poll<Result<(), Self::Error>>;
fn poll_flush_all(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let _ = cx;
Poll::Pending
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
fn is_routing(&self) -> bool {
true
}
}
#[diagnostic::do_not_recommend]
impl<Route, Msg, E, T: ?Sized + Sink<(Route, Msg), Error = E>> RouteSink<Route, Msg> for T {
type Error = E;
fn poll_ready(
self: Pin<&mut Self>,
_: &Route,
cx: &mut Context<'_>,
) -> Poll<Result<(), Self::Error>> {
self.poll_ready_any(cx)
}
fn poll_ready_any(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Sink::poll_ready(self, cx)
}
fn start_send(self: Pin<&mut Self>, route: Route, msg: Msg) -> Result<(), Self::Error> {
Sink::start_send(self, (route, msg))
}
fn poll_flush(
self: Pin<&mut Self>,
_: &Route,
cx: &mut Context<'_>,
) -> Poll<Result<(), Self::Error>> {
self.poll_flush_all(cx)
}
fn poll_flush_all(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Sink::poll_flush(self, cx)
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Sink::poll_close(self, cx)
}
fn is_routing(&self) -> bool {
false
}
}
#[derive(Debug)]
pub struct WithRoute<'a, T: ?Sized, Route> {
route_sink: Pin<&'a mut T>,
route: Route,
}
impl<T: ?Sized, Route> Unpin for WithRoute<'_, T, Route> {}
impl<Route: Clone, Msg, E, T: ?Sized + RouteSink<Route, Msg, Error = E>> Sink<Msg>
for WithRoute<'_, T, Route>
{
type Error = E;
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let this = self.get_mut();
this.route_sink.as_mut().poll_ready(&this.route, cx)
}
fn start_send(self: Pin<&mut Self>, msg: Msg) -> Result<(), Self::Error> {
let this = self.get_mut();
this.route_sink.as_mut().start_send(this.route.clone(), msg)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let this = self.get_mut();
this.route_sink.as_mut().poll_flush(&this.route, cx)
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.get_mut().route_sink.as_mut().poll_close(cx)
}
}
pub trait RouteExt<Route> {
type T: ?Sized;
#[must_use]
fn route(&mut self, route: Route) -> WithRoute<'_, Self::T, Route>;
}
impl<T: ?Sized, Route> RouteExt<Route> for Pin<&'_ mut T> {
type T = T;
fn route(&mut self, route: Route) -> WithRoute<'_, Self::T, Route> {
WithRoute {
route_sink: self.as_mut(),
route,
}
}
}
impl<T: ?Sized + Unpin, Route> RouteExt<Route> for &'_ mut T {
type T = T;
fn route(&mut self, route: Route) -> WithRoute<'_, Self::T, Route> {
WithRoute {
route_sink: Pin::new(self),
route,
}
}
}
#[cfg(feature = "unroute")]
#[pin_project::pin_project]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Unroute<S>(#[pin] pub S);
#[cfg(feature = "unroute")]
impl<S> Unroute<S> {
pub fn new_checked<Route, Msg>(sink: S) -> Self
where
S: RouteSink<Route, Msg>,
{
assert!(!sink.is_routing());
Self(sink)
}
}
#[cfg(feature = "unroute")]
impl<S: futures_core::Stream> futures_core::Stream for Unroute<S> {
type Item = S::Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.project().0.poll_next(cx)
}
}
#[cfg(feature = "unroute")]
impl<Route, Msg, S: RouteSink<Route, Msg>> Sink<(Route, Msg)> for Unroute<S> {
type Error = S::Error;
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
assert!(!self.0.is_routing());
self.project().0.poll_ready_any(cx)
}
fn start_send(self: Pin<&mut Self>, (route, msg): (Route, Msg)) -> Result<(), Self::Error> {
assert!(!self.0.is_routing());
self.project().0.start_send(route, msg)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
assert!(!self.0.is_routing());
self.project().0.poll_flush_all(cx)
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.project().0.poll_close(cx)
}
}