1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::future::Future;
15 use std::io;
16 use std::io::IoSlice;
17 use std::pin::Pin;
18 use std::task::{Context, Poll};
19 
20 use crate::io::AsyncWrite;
21 
22 macro_rules! take_writer {
23     ($self: expr) => {
24         match $self.writer.take() {
25             Some(writer) => writer,
26             None => panic!("write: poll after finished"),
27         }
28     };
29 }
30 
31 /// A future for writing some of the buffer to the io
32 ///
33 /// Returned by [`crate::io::AsyncWriteExt::write`]
34 pub struct WriteTask<'a, W: ?Sized> {
35     writer: Option<&'a mut W>,
36     buf: &'a [u8],
37 }
38 
39 impl<'a, W: ?Sized> WriteTask<'a, W>
40 where
41     W: AsyncWrite + Unpin,
42 {
43     #[inline(always)]
new(writer: &'a mut W, buf: &'a [u8]) -> WriteTask<'a, W>44     pub(crate) fn new(writer: &'a mut W, buf: &'a [u8]) -> WriteTask<'a, W> {
45         WriteTask {
46             writer: Some(writer),
47             buf,
48         }
49     }
50 }
51 
52 impl<'a, W> Future for WriteTask<'a, W>
53 where
54     W: AsyncWrite + Unpin,
55 {
56     type Output = io::Result<usize>;
57 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>58     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
59         let mut writer = take_writer!(self);
60 
61         match Pin::new(&mut writer).poll_write(cx, self.buf) {
62             Poll::Pending => {
63                 self.writer = Some(writer);
64                 Poll::Pending
65             }
66             x => x,
67         }
68     }
69 }
70 
71 /// A future for writing data inside a vector to the io
72 ///
73 /// Returned by [`crate::io::AsyncWriteExt::write_vectored`]
74 pub struct WriteVectoredTask<'a, 'b, W: ?Sized> {
75     writer: Option<&'a mut W>,
76     bufs: &'a [IoSlice<'b>],
77 }
78 
79 impl<'a, 'b, W: ?Sized> WriteVectoredTask<'a, 'b, W>
80 where
81     W: AsyncWrite + Unpin,
82 {
83     #[inline(always)]
new(writer: &'a mut W, bufs: &'a [IoSlice<'b>]) -> WriteVectoredTask<'a, 'b, W>84     pub(crate) fn new(writer: &'a mut W, bufs: &'a [IoSlice<'b>]) -> WriteVectoredTask<'a, 'b, W> {
85         WriteVectoredTask {
86             writer: Some(writer),
87             bufs,
88         }
89     }
90 }
91 
92 impl<'a, 'b, W: ?Sized> Future for WriteVectoredTask<'a, 'b, W>
93 where
94     W: AsyncWrite + Unpin,
95 {
96     type Output = io::Result<usize>;
97 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>98     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
99         let mut writer = take_writer!(self);
100 
101         match Pin::new(&mut writer).poll_write_vectored(cx, self.bufs) {
102             Poll::Pending => {
103                 self.writer = Some(writer);
104                 Poll::Pending
105             }
106             x => x,
107         }
108     }
109 }
110 
111 /// A future for writing every data inside a buffer to the io
112 ///
113 /// Returned by [`crate::io::AsyncWriteExt::write_all`]
114 pub struct WriteAllTask<'a, W: ?Sized> {
115     writer: Option<&'a mut W>,
116     buf: &'a [u8],
117     w_len: usize,
118 }
119 
120 impl<'a, W: ?Sized> WriteAllTask<'a, W>
121 where
122     W: AsyncWrite + Unpin,
123 {
124     #[inline(always)]
new(writer: &'a mut W, buf: &'a [u8]) -> WriteAllTask<'a, W>125     pub(crate) fn new(writer: &'a mut W, buf: &'a [u8]) -> WriteAllTask<'a, W> {
126         WriteAllTask {
127             writer: Some(writer),
128             buf,
129             w_len: 0,
130         }
131     }
132 }
133 
134 impl<'a, W> Future for WriteAllTask<'a, W>
135 where
136     W: AsyncWrite + Unpin,
137 {
138     type Output = io::Result<()>;
139 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>140     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
141         let mut writer = take_writer!(self);
142         while self.w_len < self.buf.len() {
143             match Pin::new(&mut writer).poll_write(cx, &self.buf[self.w_len..]) {
144                 Poll::Ready(Ok(0)) => return Poll::Ready(Err(io::ErrorKind::WriteZero.into())),
145                 Poll::Ready(Ok(n)) => self.w_len += n,
146                 Poll::Ready(Err(e)) => return Poll::Ready(Err(e)),
147                 Poll::Pending => {
148                     self.writer = Some(writer);
149                     return Poll::Pending;
150                 }
151             }
152         }
153         Poll::Ready(Ok(()))
154     }
155 }
156 
157 pub struct FlushTask<'a, W: ?Sized> {
158     writer: &'a mut W,
159 }
160 
161 impl<'a, W: ?Sized> FlushTask<'a, W>
162 where
163     W: AsyncWrite + Unpin,
164 {
165     #[inline(always)]
new(writer: &'a mut W) -> FlushTask<'a, W>166     pub(crate) fn new(writer: &'a mut W) -> FlushTask<'a, W> {
167         FlushTask { writer }
168     }
169 }
170 
171 impl<'a, W> Future for FlushTask<'a, W>
172 where
173     W: AsyncWrite + Unpin + ?Sized,
174 {
175     type Output = io::Result<()>;
176 
poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>177     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
178         let me = self.get_mut();
179         Pin::new(&mut me.writer).poll_flush(cx)
180     }
181 }
182 pub struct ShutdownTask<'a, W: ?Sized> {
183     writer: &'a mut W,
184 }
185 
186 impl<'a, W: ?Sized> ShutdownTask<'a, W>
187 where
188     W: AsyncWrite + Unpin,
189 {
190     #[inline(always)]
new(writer: &'a mut W) -> ShutdownTask<'a, W>191     pub(crate) fn new(writer: &'a mut W) -> ShutdownTask<'a, W> {
192         ShutdownTask { writer }
193     }
194 }
195 
196 impl<'a, W> Future for ShutdownTask<'a, W>
197 where
198     W: AsyncWrite + Unpin + ?Sized,
199 {
200     type Output = io::Result<()>;
201 
poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>202     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
203         let me = self.get_mut();
204         Pin::new(&mut me.writer).poll_shutdown(cx)
205     }
206 }
207