use std::future::Future;
use std::ops::DerefMut;
use crate::raw::*;
use crate::*;
pub type Copier = Box<dyn CopyDyn>;
pub trait Copy: Unpin + Send + Sync {
fn next(&mut self) -> impl Future<Output = Result<Option<usize>>> + MaybeSend;
fn close(&mut self) -> impl Future<Output = Result<Metadata>> + MaybeSend;
fn abort(&mut self) -> impl Future<Output = Result<()>> + MaybeSend;
}
impl Copy for () {
async fn next(&mut self) -> Result<Option<usize>> {
Ok(None)
}
async fn close(&mut self) -> Result<Metadata> {
Ok(Metadata::default())
}
async fn abort(&mut self) -> Result<()> {
Ok(())
}
}
pub struct OneShotCopier {
fut: Option<BoxedStaticFuture<Result<Metadata>>>,
meta: Option<Metadata>,
}
unsafe impl Sync for OneShotCopier {}
unsafe impl Send for OneShotCopier {}
impl OneShotCopier {
pub fn new(fut: impl Future<Output = Result<Metadata>> + MaybeSend + 'static) -> Self {
Self {
fut: Some(Box::pin(fut)),
meta: None,
}
}
pub fn completed() -> Self {
Self {
fut: None,
meta: Some(Metadata::default()),
}
}
}
impl Copy for OneShotCopier {
async fn next(&mut self) -> Result<Option<usize>> {
if self.meta.is_none() {
self.close().await?;
}
Ok(None)
}
async fn close(&mut self) -> Result<Metadata> {
if let Some(fut) = self.fut.take() {
self.meta = Some(fut.await?);
}
Ok(self.meta.clone().unwrap_or_default())
}
async fn abort(&mut self) -> Result<()> {
self.fut = None;
self.meta = None;
Ok(())
}
}
pub trait CopyDyn: Unpin + Send + Sync {
fn next_dyn(&mut self) -> BoxedFuture<'_, Result<Option<usize>>>;
fn close_dyn(&mut self) -> BoxedFuture<'_, Result<Metadata>>;
fn abort_dyn(&mut self) -> BoxedFuture<'_, Result<()>>;
}
impl<T: Copy + ?Sized> CopyDyn for T {
fn next_dyn(&mut self) -> BoxedFuture<'_, Result<Option<usize>>> {
Box::pin(self.next())
}
fn close_dyn(&mut self) -> BoxedFuture<'_, Result<Metadata>> {
Box::pin(self.close())
}
fn abort_dyn(&mut self) -> BoxedFuture<'_, Result<()>> {
Box::pin(self.abort())
}
}
impl<T: CopyDyn + ?Sized> Copy for Box<T> {
async fn next(&mut self) -> Result<Option<usize>> {
self.deref_mut().next_dyn().await
}
async fn close(&mut self) -> Result<Metadata> {
self.deref_mut().close_dyn().await
}
async fn abort(&mut self) -> Result<()> {
self.deref_mut().abort_dyn().await
}
}