use core::future::Future;
use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};
use crate::buf::owned::{IoBuf, OwnedBuf};
pub struct Released<B = Vec<u8>> {
inner: Inner,
buf: PhantomData<fn() -> B>,
}
enum Inner {
Ready(Option<OwnedBuf>),
#[cfg(ring)]
Waiting(crate::sync::oneshot::Receiver<OwnedBuf>),
}
impl<B> Released<B> {
pub(crate) fn ready(buf: OwnedBuf) -> Self {
Self {
inner: Inner::Ready(Some(buf)),
buf: PhantomData,
}
}
#[cfg(ring)]
pub(crate) fn waiting(back: crate::sync::oneshot::Receiver<OwnedBuf>) -> Self {
Self {
inner: Inner::Waiting(back),
buf: PhantomData,
}
}
}
impl<B> Future for Released<B>
where
B: IoBuf,
{
type Output = B;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<B> {
#[cfg(not(ring))]
let _ = cx;
let back = match &mut self.inner {
Inner::Ready(buf) => buf.take().unwrap_or_default(),
#[cfg(ring)]
Inner::Waiting(back) => match Pin::new(back).poll(cx) {
Poll::Pending => return Poll::Pending,
Poll::Ready(buf) => buf.unwrap_or_default(),
},
};
Poll::Ready(back.into_written())
}
}
impl<B> core::fmt::Debug for Released<B> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let ready = match &self.inner {
Inner::Ready(_) => true,
#[cfg(ring)]
Inner::Waiting(back) => !back.is_empty(),
};
f.debug_struct("Released").field("ready", &ready).finish()
}
}