use core::pin::Pin;
use core::task::{Context, Poll};
use pin_project_lite::pin_project;
use crate::{Sink, SinkBuild};
pin_project! {
#[must_use = "sinks do nothing unless polled"]
pub struct Inspect<Si, Func> {
#[pin]
sink: Si,
func: Func,
}
}
impl<Si, Func> Inspect<Si, Func> {
pub fn new<Item>(func: Func, sink: Si) -> Self
where
Self: Sink<Item>,
{
Self { sink, func }
}
}
impl<Si, Func, Item> Sink<Item> for Inspect<Si, Func>
where
Si: Sink<Item>,
Func: FnMut(&Item),
{
type Error = Si::Error;
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.project().sink.poll_ready(cx)
}
fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
let this = self.project();
(this.func)(&item);
this.sink.start_send(item)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.project().sink.poll_flush(cx)
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.project().sink.poll_close(cx)
}
}
pub struct InspectBuilder<Prev, Func> {
pub(crate) prev: Prev,
pub(crate) func: Func,
}
impl<Prev, Func> SinkBuild for InspectBuilder<Prev, Func>
where
Prev: SinkBuild,
Func: FnMut(&Prev::Item),
{
type Item = Prev::Item;
type Output<Next: Sink<Prev::Item>> = Prev::Output<Inspect<Next, Func>>;
fn send_to<Next>(self, next: Next) -> Self::Output<Next>
where
Next: Sink<Prev::Item>,
{
self.prev.send_to(Inspect::new(self.func, next))
}
}