use std::future::Future;
use std::io::{IoSlice, IoSliceMut, Result, SeekFrom};
use std::marker::PhantomPinned;
use std::pin::Pin;
use std::task::{Context, Poll};
use async_std::io::Cursor;
use async_std::io::prelude::*;
use pin_project_lite::pin_project;
#[cfg(feature = "stackpin")]
mod impl_stackpin;
pin_project! {
pub struct PinCursor<T> {
c: Cursor<T>,
#[pin]
_p: PhantomPinned
}
}
impl<T> PinCursor<T>
where T: Unpin,
Cursor<T>: Write + Read + Seek
{
pub fn wrap(c: Cursor<T>) -> Self {
Self { c, _p: PhantomPinned }
}
pub fn unwrap(self) -> Cursor<T> {
self.c
}
pub fn position(&self) -> u64 {
self.c.position()
}
pub fn set_position(self: Pin<&mut Self>, pos: u64) {
self.project().c.set_position(pos)
}
pub fn write<'a>(self: Pin<&'a mut Self>, buf: &'a [u8]) -> impl Future<Output=Result<usize>> + 'a {
self.project().c.write(buf)
}
pub fn read<'a>(self: Pin<&'a mut Self>, buf: &'a mut [u8]) -> impl Future<Output=Result<usize>> + 'a {
self.project().c.read(buf)
}
pub fn seek(self: Pin<&mut Self>, pos: SeekFrom) -> impl Future<Output=Result<u64>> + '_ {
self.project().c.seek(pos)
}
}
impl<T> Read for PinCursor<T>
where T: Unpin,
Cursor<T>: Read
{
fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>> {
Pin::new(self.project().c).poll_read(cx, buf)
}
fn poll_read_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>]) -> Poll<Result<usize>> {
Pin::new(self.project().c).poll_read_vectored(cx, bufs)
}
}
impl<T> Write for PinCursor<T>
where T: Unpin,
Cursor<T>: Write
{
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
Pin::new(self.project().c).poll_write(cx, buf)
}
fn poll_write_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>]) -> Poll<Result<usize>> {
Pin::new(self.project().c).poll_write_vectored(cx, bufs)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
Pin::new(self.project().c).poll_flush(cx)
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
Pin::new(self.project().c).poll_close(cx)
}
}
impl<T> Seek for PinCursor<T>
where T: Unpin,
Cursor<T>: Seek
{
fn poll_seek(self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom) -> Poll<Result<u64>> {
Pin::new(self.project().c).poll_seek(cx, pos)
}
}
#[cfg(test)]
mod tests {
use static_assertions::{assert_impl_all, assert_not_impl_all};
use super::*;
#[test]
fn impls() {
assert_not_impl_all!(PinCursor<Vec<u8>>: Unpin);
assert_impl_all!(PinCursor<Vec<u8>>: Read, Write, Seek);
}
}