tokio/io/util/
buf_writer.rs1use crate::io::util::DEFAULT_BUF_SIZE;
2use crate::io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, ReadBuf};
3
4use pin_project_lite::pin_project;
5use std::fmt;
6use std::io::{self, IoSlice, SeekFrom, Write};
7use std::pin::Pin;
8use std::task::{ready, Context, Poll};
9
10pin_project! {
11 #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
32 pub struct BufWriter<W> {
33 #[pin]
34 pub(super) inner: W,
35 pub(super) buf: Vec<u8>,
36 pub(super) written: usize,
37 pub(super) seek_state: SeekState,
38 }
39}
40
41impl<W: AsyncWrite> BufWriter<W> {
42 pub fn new(inner: W) -> Self {
45 Self::with_capacity(DEFAULT_BUF_SIZE, inner)
46 }
47
48 pub fn with_capacity(cap: usize, inner: W) -> Self {
50 Self {
51 inner,
52 buf: Vec::with_capacity(cap),
53 written: 0,
54 seek_state: SeekState::Init,
55 }
56 }
57
58 fn flush_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
59 let mut me = self.project();
60
61 let len = me.buf.len();
62 let mut ret = Ok(());
63 while *me.written < len {
64 match ready!(me.inner.as_mut().poll_write(cx, &me.buf[*me.written..])) {
65 Ok(0) => {
66 ret = Err(io::Error::new(
67 io::ErrorKind::WriteZero,
68 "failed to write the buffered data",
69 ));
70 break;
71 }
72 Ok(n) => *me.written += n,
73 Err(e) if e.kind() == io::ErrorKind::Interrupted => continue,
74 Err(e) => {
75 ret = Err(e);
76 break;
77 }
78 }
79 }
80 if *me.written > 0 {
81 me.buf.drain(..*me.written);
82 }
83 *me.written = 0;
84 Poll::Ready(ret)
85 }
86
87 pub fn get_ref(&self) -> &W {
89 &self.inner
90 }
91
92 pub fn get_mut(&mut self) -> &mut W {
96 &mut self.inner
97 }
98
99 pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut W> {
103 self.project().inner
104 }
105
106 pub fn into_inner(self) -> W {
110 self.inner
111 }
112
113 pub fn buffer(&self) -> &[u8] {
115 &self.buf
116 }
117}
118
119impl<W: AsyncWrite> AsyncWrite for BufWriter<W> {
120 fn poll_write(
121 mut self: Pin<&mut Self>,
122 cx: &mut Context<'_>,
123 buf: &[u8],
124 ) -> Poll<io::Result<usize>> {
125 if self.buf.len() + buf.len() > self.buf.capacity() {
126 ready!(self.as_mut().flush_buf(cx))?;
127 }
128
129 let me = self.project();
130 if buf.len() >= me.buf.capacity() {
131 me.inner.poll_write(cx, buf)
132 } else {
133 Poll::Ready(me.buf.write(buf))
134 }
135 }
136
137 fn poll_write_vectored(
138 mut self: Pin<&mut Self>,
139 cx: &mut Context<'_>,
140 mut bufs: &[IoSlice<'_>],
141 ) -> Poll<io::Result<usize>> {
142 if self.inner.is_write_vectored() {
143 let total_len = bufs
144 .iter()
145 .fold(0usize, |acc, b| acc.saturating_add(b.len()));
146 if total_len > self.buf.capacity() - self.buf.len() {
147 ready!(self.as_mut().flush_buf(cx))?;
148 }
149 let me = self.as_mut().project();
150 if total_len >= me.buf.capacity() {
151 me.inner.poll_write_vectored(cx, bufs)
156 } else {
157 bufs.iter().for_each(|b| me.buf.extend_from_slice(b));
158 Poll::Ready(Ok(total_len))
159 }
160 } else {
161 while bufs.first().map(|buf| buf.len()) == Some(0) {
163 bufs = &bufs[1..];
164 }
165 if bufs.is_empty() {
166 return Poll::Ready(Ok(0));
167 }
168 let first_len = bufs[0].len();
170 if first_len > self.buf.capacity() - self.buf.len() {
171 ready!(self.as_mut().flush_buf(cx))?;
172 debug_assert!(self.buf.is_empty());
173 }
174 let me = self.as_mut().project();
175 if first_len >= me.buf.capacity() {
176 debug_assert!(me.buf.is_empty());
179 return me.inner.poll_write(cx, &bufs[0]);
180 } else {
181 me.buf.extend_from_slice(&bufs[0]);
182 bufs = &bufs[1..];
183 }
184 let mut total_written = first_len;
185 debug_assert!(total_written != 0);
186 for buf in bufs {
188 if buf.len() > me.buf.capacity() - me.buf.len() {
189 break;
190 } else {
191 me.buf.extend_from_slice(buf);
192 total_written += buf.len();
193 }
194 }
195 Poll::Ready(Ok(total_written))
196 }
197 }
198
199 fn is_write_vectored(&self) -> bool {
200 true
201 }
202
203 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
204 ready!(self.as_mut().flush_buf(cx))?;
205 self.get_pin_mut().poll_flush(cx)
206 }
207
208 fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
209 ready!(self.as_mut().flush_buf(cx))?;
210 self.get_pin_mut().poll_shutdown(cx)
211 }
212}
213
214#[derive(Debug, Clone, Copy)]
215pub(super) enum SeekState {
216 Init,
218 Start(SeekFrom),
220 Pending,
222}
223
224impl<W: AsyncWrite + AsyncSeek> AsyncSeek for BufWriter<W> {
228 fn start_seek(self: Pin<&mut Self>, pos: SeekFrom) -> io::Result<()> {
229 *self.project().seek_state = SeekState::Start(pos);
233 Ok(())
234 }
235
236 fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
237 let pos = match self.seek_state {
238 SeekState::Init => {
239 return self.project().inner.poll_complete(cx);
240 }
241 SeekState::Start(pos) => Some(pos),
242 SeekState::Pending => None,
243 };
244
245 ready!(self.as_mut().flush_buf(cx))?;
247
248 let mut me = self.project();
249 if let Some(pos) = pos {
250 ready!(me.inner.as_mut().poll_complete(cx))?;
252 if let Err(e) = me.inner.as_mut().start_seek(pos) {
253 *me.seek_state = SeekState::Init;
254 return Poll::Ready(Err(e));
255 }
256 }
257 match me.inner.poll_complete(cx) {
258 Poll::Ready(res) => {
259 *me.seek_state = SeekState::Init;
260 Poll::Ready(res)
261 }
262 Poll::Pending => {
263 *me.seek_state = SeekState::Pending;
264 Poll::Pending
265 }
266 }
267 }
268}
269
270impl<W: AsyncWrite + AsyncRead> AsyncRead for BufWriter<W> {
271 fn poll_read(
272 self: Pin<&mut Self>,
273 cx: &mut Context<'_>,
274 buf: &mut ReadBuf<'_>,
275 ) -> Poll<io::Result<()>> {
276 self.get_pin_mut().poll_read(cx, buf)
277 }
278}
279
280impl<W: AsyncWrite + AsyncBufRead> AsyncBufRead for BufWriter<W> {
281 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
282 self.get_pin_mut().poll_fill_buf(cx)
283 }
284
285 fn consume(self: Pin<&mut Self>, amt: usize) {
286 self.get_pin_mut().consume(amt);
287 }
288}
289
290impl<W: fmt::Debug> fmt::Debug for BufWriter<W> {
291 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292 f.debug_struct("BufWriter")
293 .field("writer", &self.inner)
294 .field(
295 "buffer",
296 &format_args!("{}/{}", self.buf.len(), self.buf.capacity()),
297 )
298 .field("written", &self.written)
299 .finish()
300 }
301}
302
303#[cfg(test)]
304mod tests {
305 use super::*;
306
307 #[test]
308 fn assert_unpin() {
309 crate::is_unpin::<BufWriter<()>>();
310 }
311}