1 | use crate::io::AsyncSeek; |
2 | |
3 | use pin_project_lite::pin_project; |
4 | use std::future::Future; |
5 | use std::io::{self, SeekFrom}; |
6 | use std::marker::PhantomPinned; |
7 | use std::pin::Pin; |
8 | use std::task::{Context, Poll}; |
9 | |
10 | pin_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 | |
23 | pub(crate) fn seek<S>(seek: &mut S, pos: SeekFrom) -> Seek<'_, S> |
24 | where |
25 | S: AsyncSeek + ?Sized + Unpin, |
26 | { |
27 | Seek { |
28 | seek, |
29 | pos: Some(pos), |
30 | _pin: PhantomPinned, |
31 | } |
32 | } |
33 | |
34 | impl<S> Future for Seek<'_, S> |
35 | where |
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: Projection<'_, '_, S> = self.project(); |
42 | match me.pos { |
43 | Some(pos: &mut SeekFrom) => { |
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: Error) => Poll::Ready(Err(e)), |
52 | } |
53 | } |
54 | None => Pin::new(&mut *me.seek).poll_complete(cx), |
55 | } |
56 | } |
57 | } |
58 | |