use std::cell::RefCell; use std::pin::Pin; use std::rc::Rc; use std::task::{Context, Poll}; use futures_util::{Sink, Stream}; use pin_project::{pin_project, pinned_drop}; #[pin_project(PinnedDrop)] pub struct DropObservable { #[pin] inner: S, handle: Rc>, } #[pinned_drop] impl PinnedDrop for DropObservable { fn drop(self: Pin<&mut Self>) { *self.project().handle.borrow_mut() = true } } pub struct DropObserver { handle: Rc>, } impl DropObserver { pub fn is_dropped(&self) -> bool { *self.handle.borrow() } } pub fn observe_drop(inner: T) -> (DropObservable, DropObserver) { let handle = Rc::new(RefCell::new(false)); ( DropObservable { inner, handle: handle.clone(), }, DropObserver { handle }, ) } impl Stream for DropObservable { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().inner.poll_next(cx) } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } impl Sink for DropObservable where S: Sink, { type Error = S::Error; fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().inner.poll_ready(cx) } fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { self.project().inner.start_send(item) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().inner.poll_flush(cx) } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().inner.poll_close(cx) } }