tokio/io/
seek.rs

1use crate::io::AsyncSeek;
2
3use pin_project_lite::pin_project;
4use std::future::Future;
5use std::io::{self, SeekFrom};
6use std::marker::PhantomPinned;
7use std::pin::Pin;
8use std::task::{ready, Context, Poll};
9
10pin_project! {
11    /// Future for the [`seek`](crate::io::AsyncSeekExt::seek) method.
12    #[derive(Debug)]
13    #[must_use = "futures do nothing unless you `.await` or poll them"]
14    pub struct Seek<'a, S: ?Sized> {
15        seek: &'a mut S,
16        pos: Option<SeekFrom>,
17        // Make this future `!Unpin` for compatibility with async trait methods.
18        #[pin]
19        _pin: PhantomPinned,
20    }
21}
22
23pub(crate) fn seek<S>(seek: &mut S, pos: SeekFrom) -> Seek<'_, S>
24where
25    S: AsyncSeek + ?Sized + Unpin,
26{
27    Seek {
28        seek,
29        pos: Some(pos),
30        _pin: PhantomPinned,
31    }
32}
33
34impl<S> Future for Seek<'_, S>
35where
36    S: AsyncSeek + ?Sized + Unpin,
37{
38    type Output = io::Result<u64>;
39
40    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
41        let me = self.project();
42        match me.pos {
43            Some(pos) => {
44                // ensure no seek in progress
45                ready!(Pin::new(&mut *me.seek).poll_complete(cx))?;
46                match Pin::new(&mut *me.seek).start_seek(*pos) {
47                    Ok(()) => {
48                        *me.pos = None;
49                        Pin::new(&mut *me.seek).poll_complete(cx)
50                    }
51                    Err(e) => Poll::Ready(Err(e)),
52                }
53            }
54            None => Pin::new(&mut *me.seek).poll_complete(cx),
55        }
56    }
57}