     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90

    use std::io::{self, SeekFrom};
    use std::ops::DerefMut;
    use std::pin::Pin;
    use std::task::{Context, Poll};

    /// Seek bytes asynchronously.
    ///
    /// This trait is analogous to the [`std::io::Seek`] trait, but integrates
    /// with the asynchronous task system. In particular, the `start_seek`
    /// method, unlike [`Seek::seek`], will not block the calling thread.
    ///
    /// Utilities for working with `AsyncSeek` values are provided by
    /// [`AsyncSeekExt`].
    ///
    /// [`std::io::Seek`]: std::io::Seek
    /// [`Seek::seek`]: std::io::Seek::seek()
    /// [`AsyncSeekExt`]: crate::io::AsyncSeekExt
    pub trait AsyncSeek {
        /// Attempts to seek to an offset, in bytes, in a stream.
        ///
        /// A seek beyond the end of a stream is allowed, but behavior is defined
        /// by the implementation.
        ///
        /// If this function returns successfully, then the job has been submitted.
        /// To find out when it completes, call `poll_complete`.
        ///
        /// # Errors
        ///
        /// This function can return [`io::ErrorKind::Other`] in case there is
        /// another seek in progress. To avoid this, it is advisable that any call
        /// to `start_seek` is preceded by a call to `poll_complete` to ensure all
        /// pending seeks have completed.
        fn start_seek(self: Pin<&mut Self>, position: SeekFrom) -> io::Result<()>;

        /// Waits for a seek operation to complete.
        ///
        /// If the seek operation completed successfully,
        /// this method returns the new position from the start of the stream.
        /// That position can be used later with [`SeekFrom::Start`]. Repeatedly
        /// calling this function without calling `start_seek` might return the
        /// same result.
        ///
        /// # Errors
        ///
        /// Seeking to a negative offset is considered an error.
        fn poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>>;
    }

    macro_rules! deref_async_seek {
        () => {
            fn start_seek(mut self: Pin<&mut Self>, pos: SeekFrom) -> io::Result<()> {
                Pin::new(&mut **self).start_seek(pos)
            }

            fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
                Pin::new(&mut **self).poll_complete(cx)
            }
        };
    }

    impl<T: ?Sized + AsyncSeek + Unpin> AsyncSeek for Box<T> {
        deref_async_seek!();
    }

    impl<T: ?Sized + AsyncSeek + Unpin> AsyncSeek for &mut T {
        deref_async_seek!();
    }

    impl<P> AsyncSeek for Pin<P>
    where
        P: DerefMut + Unpin,
        P::Target: AsyncSeek,
    {
        fn start_seek(self: Pin<&mut Self>, pos: SeekFrom) -> io::Result<()> {
            self.get_mut().as_mut().start_seek(pos)
        }

        fn poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
            self.get_mut().as_mut().poll_complete(cx)
        }
    }

    impl<T: AsRef<[u8]> + Unpin> AsyncSeek for io::Cursor<T> {
        fn start_seek(mut self: Pin<&mut Self>, pos: SeekFrom) -> io::Result<()> {
            io::Seek::seek(&mut *self, pos).map(drop)
        }
        fn poll_complete(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<u64>> {
            Poll::Ready(Ok(self.get_mut().position()))
        }
    }