tempest_rt/fs/
stat_file.rs1use std::{
4 io,
5 pin::Pin,
6 task::{Context, Poll},
7};
8
9use tempest_io::{FstatHandle, Io, OpHandle};
10
11use crate::context::{current_io, get_op_handle};
12
13enum StatFileState<I: Io> {
14 NeedsSubmit {
15 fd: I::Fd,
16 op_handle: Option<OpHandle>,
17 },
18 InFlight {
19 fstat_handle: FstatHandle<I::Statx>,
20 op_handle: OpHandle,
21 },
22 Done,
23}
24
25#[must_use = "futures do nothing unless awaited"]
27pub struct StatFile<I: Io> {
28 state: StatFileState<I>,
29}
30
31pub fn stat_file<I: Io>(fd: I::Fd) -> StatFile<I> {
33 StatFile {
34 state: StatFileState::NeedsSubmit {
35 fd,
36 op_handle: None,
37 },
38 }
39}
40
41impl<I: Io> Unpin for StatFile<I> {}
43
44impl<I: Io> Future for StatFile<I> {
45 type Output = io::Result<I::Statx>;
46
47 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
48 let this = self.get_mut();
49
50 match std::mem::replace(&mut this.state, StatFileState::Done) {
51 StatFileState::NeedsSubmit { fd, op_handle } => {
52 let op_handle = op_handle.unwrap_or_else(|| unsafe { get_op_handle(cx) });
53
54 let io = unsafe { current_io::<I>() };
56 match io.fstat(fd, op_handle) {
57 Ok(fstat_handle) => {
58 this.state = StatFileState::InFlight {
59 fstat_handle,
60 op_handle,
61 };
62 Poll::Pending
63 }
64 Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
65 this.state = StatFileState::NeedsSubmit {
66 fd,
67 op_handle: Some(op_handle),
68 };
69 cx.waker().wake_by_ref();
70 Poll::Pending
71 }
72 Err(e) => Poll::Ready(Err(e)),
73 }
74 }
75 StatFileState::InFlight {
76 fstat_handle,
77 op_handle,
78 } => {
79 let io = unsafe { current_io::<I>() };
81 match io.get_cqe(op_handle).transpose()? {
82 Some(_) => Poll::Ready(Ok(fstat_handle.complete())),
83 None => {
84 this.state = StatFileState::InFlight {
85 fstat_handle,
86 op_handle,
87 };
88 Poll::Pending
89 }
90 }
91 }
92 StatFileState::Done => panic!("polled after completion"),
93 }
94 }
95}