broker_tokio/io/
async_seek.rs

1use std::io::{self, SeekFrom};
2use std::ops::DerefMut;
3use std::pin::Pin;
4use 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
18pub trait AsyncSeek {
19    /// Attempt 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    fn start_seek(
27        self: Pin<&mut Self>,
28        cx: &mut Context<'_>,
29        position: SeekFrom,
30    ) -> Poll<io::Result<()>>;
31
32    /// Wait for a seek operation to complete.
33    ///
34    /// If the seek operation completed successfully,
35    /// this method returns the new position from the start of the stream.
36    /// That position can be used later with [`SeekFrom::Start`].
37    ///
38    /// # Errors
39    ///
40    /// Seeking to a negative offset is considered an error.
41    ///
42    /// # Panics
43    ///
44    /// Calling this method without calling `start_seek` first is an error.
45    fn poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>>;
46}
47
48macro_rules! deref_async_seek {
49    () => {
50        fn start_seek(
51            mut self: Pin<&mut Self>,
52            cx: &mut Context<'_>,
53            pos: SeekFrom,
54        ) -> Poll<io::Result<()>> {
55            Pin::new(&mut **self).start_seek(cx, pos)
56        }
57
58        fn poll_complete(
59            mut self: Pin<&mut Self>,
60            cx: &mut Context<'_>,
61        ) -> Poll<io::Result<u64>> {
62            Pin::new(&mut **self).poll_complete(cx)
63        }
64    }
65}
66
67impl<T: ?Sized + AsyncSeek + Unpin> AsyncSeek for Box<T> {
68    deref_async_seek!();
69}
70
71impl<T: ?Sized + AsyncSeek + Unpin> AsyncSeek for &mut T {
72    deref_async_seek!();
73}
74
75impl<P> AsyncSeek for Pin<P>
76where
77    P: DerefMut + Unpin,
78    P::Target: AsyncSeek,
79{
80    fn start_seek(
81        self: Pin<&mut Self>,
82        cx: &mut Context<'_>,
83        pos: SeekFrom,
84    ) -> Poll<io::Result<()>> {
85        self.get_mut().as_mut().start_seek(cx, pos)
86    }
87
88    fn poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
89        self.get_mut().as_mut().poll_complete(cx)
90    }
91}
92
93impl<T: AsRef<[u8]> + Unpin> AsyncSeek for io::Cursor<T> {
94    fn start_seek(
95        mut self: Pin<&mut Self>,
96        _: &mut Context<'_>,
97        pos: SeekFrom,
98    ) -> Poll<io::Result<()>> {
99        Poll::Ready(io::Seek::seek(&mut *self, pos).map(drop))
100    }
101    fn poll_complete(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<u64>> {
102        Poll::Ready(Ok(self.get_mut().position()))
103    }
104}