1 use std::io::{self, SeekFrom}; 2 use std::ops::DerefMut; 3 use std::pin::Pin; 4 use std::task::{Context, Poll}; 5 6 /// Seek bytes asynchronously. 7 /// 8 /// This trait is analogous to the [`std::io::Seek`] trait, but integrates 9 /// with the asynchronous task system. In particular, the `start_seek` 10 /// method, unlike [`Seek::seek`], will not block the calling thread. 11 /// 12 /// Utilities for working with `AsyncSeek` values are provided by 13 /// [`AsyncSeekExt`]. 14 /// 15 /// [`std::io::Seek`]: std::io::Seek 16 /// [`Seek::seek`]: std::io::Seek::seek() 17 /// [`AsyncSeekExt`]: crate::io::AsyncSeekExt 18 pub trait AsyncSeek { 19 /// Attempts to seek to an offset, in bytes, in a stream. 20 /// 21 /// A seek beyond the end of a stream is allowed, but behavior is defined 22 /// by the implementation. 23 /// 24 /// If this function returns successfully, then the job has been submitted. 25 /// To find out when it completes, call `poll_complete`. 26 /// 27 /// # Errors 28 /// 29 /// This function can return [`io::ErrorKind::Other`] in case there is 30 /// another seek in progress. To avoid this, it is advisable that any call 31 /// to `start_seek` is preceded by a call to `poll_complete` to ensure all 32 /// pending seeks have completed. start_seek(self: Pin<&mut Self>, position: SeekFrom) -> io::Result<()>33 fn start_seek(self: Pin<&mut Self>, position: SeekFrom) -> io::Result<()>; 34 35 /// Waits for a seek operation to complete. 36 /// 37 /// If the seek operation completed successfully, 38 /// this method returns the new position from the start of the stream. 39 /// That position can be used later with [`SeekFrom::Start`]. Repeatedly 40 /// calling this function without calling `start_seek` might return the 41 /// same result. 42 /// 43 /// # Errors 44 /// 45 /// Seeking to a negative offset is considered an error. poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>>46 fn poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>>; 47 } 48 49 macro_rules! deref_async_seek { 50 () => { 51 fn start_seek(mut self: Pin<&mut Self>, pos: SeekFrom) -> io::Result<()> { 52 Pin::new(&mut **self).start_seek(pos) 53 } 54 55 fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> { 56 Pin::new(&mut **self).poll_complete(cx) 57 } 58 }; 59 } 60 61 impl<T: ?Sized + AsyncSeek + Unpin> AsyncSeek for Box<T> { 62 deref_async_seek!(); 63 } 64 65 impl<T: ?Sized + AsyncSeek + Unpin> AsyncSeek for &mut T { 66 deref_async_seek!(); 67 } 68 69 impl<P> AsyncSeek for Pin<P> 70 where 71 P: DerefMut + Unpin, 72 P::Target: AsyncSeek, 73 { start_seek(self: Pin<&mut Self>, pos: SeekFrom) -> io::Result<()>74 fn start_seek(self: Pin<&mut Self>, pos: SeekFrom) -> io::Result<()> { 75 self.get_mut().as_mut().start_seek(pos) 76 } 77 poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>>78 fn poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> { 79 self.get_mut().as_mut().poll_complete(cx) 80 } 81 } 82 83 impl<T: AsRef<[u8]> + Unpin> AsyncSeek for io::Cursor<T> { start_seek(mut self: Pin<&mut Self>, pos: SeekFrom) -> io::Result<()>84 fn start_seek(mut self: Pin<&mut Self>, pos: SeekFrom) -> io::Result<()> { 85 io::Seek::seek(&mut *self, pos).map(drop) 86 } poll_complete(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<u64>>87 fn poll_complete(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<u64>> { 88 Poll::Ready(Ok(self.get_mut().position())) 89 } 90 } 91