tempest_rt/fs/
write_exact.rs1use std::{
4 io,
5 mem::replace,
6 pin::Pin,
7 task::{Context, Poll},
8};
9
10use tempest_io::{Io, IoBuf, Slice};
11
12use super::{WriteAt, write_at};
13
14enum WriteExactState<B: IoBuf, I: Io> {
15 Idle {
16 buf: B,
17 done: usize,
18 },
19 Writing {
20 fut: WriteAt<Slice<B>, I>,
21 done: usize,
22 },
23 Done,
24}
25
26#[must_use = "futures do nothing unless awaited"]
28pub struct WriteExact<B: IoBuf, I: Io> {
29 state: WriteExactState<B, I>,
30 fd: I::Fd,
31 offset: u64,
32 total: usize,
33}
34
35pub fn write_exact<B: IoBuf, I: Io>(fd: I::Fd, buf: B, offset: u64) -> WriteExact<B, I> {
40 let total = buf.bytes_init();
41 WriteExact {
42 state: WriteExactState::Idle { buf, done: 0 },
43 fd,
44 offset,
45 total,
46 }
47}
48
49impl<B: IoBuf, I: Io> Unpin for WriteExact<B, I> {}
50
51impl<B: IoBuf, I: Io> Future for WriteExact<B, I> {
52 type Output = (io::Result<()>, B);
53
54 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
55 let this = self.get_mut();
56
57 loop {
58 match replace(&mut this.state, WriteExactState::Done) {
59 WriteExactState::Idle { buf, done } => {
60 let fut = write_at::<_, I>(
61 this.fd,
62 buf.slice(done..this.total),
63 this.offset + done as u64,
64 );
65 this.state = WriteExactState::Writing { fut, done };
66 }
68 WriteExactState::Writing { mut fut, done } => {
69 match Pin::new(&mut fut).poll(cx) {
70 Poll::Pending => {
71 this.state = WriteExactState::Writing { fut, done };
72 return Poll::Pending;
73 }
74 Poll::Ready((Ok(n), slice)) => {
75 let buf = slice.into_inner();
76 let new_done = done + n;
77 if new_done >= this.total {
78 return Poll::Ready((Ok(()), buf));
79 }
80 this.state = WriteExactState::Idle {
81 buf,
82 done: new_done,
83 };
84 }
86 Poll::Ready((Err(e), slice)) => {
87 return Poll::Ready((Err(e), slice.into_inner()));
88 }
89 }
90 }
91 WriteExactState::Done => panic!("WriteExact polled after completion"),
92 }
93 }
94 }
95}