use std::pin::Pin;
pub trait PlaybackSource: Send + 'static {
#[allow(missing_docs)]
fn poll_read(
self: Pin<&mut Self>,
cx: &mut futures::task::Context<'_>,
buf: &mut [u8],
) -> futures::task::Poll<usize>;
}
pub trait AsPlaybackSource {
#[allow(clippy::wrong_self_convention)]
fn as_playback_source(self) -> impl PlaybackSource;
}
struct CallbackWrapper<T: FnMut(&mut [u8]) -> usize + Send + 'static>(T);
impl<T> PlaybackSource for CallbackWrapper<T>
where
T: FnMut(&mut [u8]) -> usize + Send + 'static,
{
fn poll_read(
self: Pin<&mut CallbackWrapper<T>>,
_cx: &mut futures::task::Context<'_>,
buf: &mut [u8],
) -> futures::task::Poll<usize> {
let len = unsafe {
let pinned_closure = Pin::get_unchecked_mut(self);
pinned_closure.0(buf)
};
futures::task::Poll::Ready(len)
}
}
impl<T> AsPlaybackSource for T
where
T: FnMut(&mut [u8]) -> usize + Send + 'static,
{
fn as_playback_source(self) -> impl PlaybackSource {
CallbackWrapper(self)
}
}
impl<T> PlaybackSource for T
where
T: futures::AsyncRead + Send + 'static,
{
fn poll_read(
self: Pin<&mut Self>,
cx: &mut futures::task::Context<'_>,
buf: &mut [u8],
) -> futures::task::Poll<usize> {
futures::AsyncRead::poll_read(self, cx, buf).map(|result| result.unwrap_or_default())
}
}