1use core::pin::Pin;
2use core::task::{ready, Context, Poll};
3
4use crate::buf::Buf;
5use crate::error::{IoError, WriteError};
6
7#[cfg(feature = "alloc")]
8use crate::transaction::{
9 WriteTransactionKind, WriteTransactionVariant,
10};
11
12mod flush;
13mod write_buf;
14mod write_buf_all;
15
16use self::flush::Flush;
17use self::write_buf::WriteBuf;
18use self::write_buf_all::WriteBufAll;
19
20pub trait Write {
24 type Error: WriteError;
26
27 fn write_slice(
35 &mut self,
36 buf: &[u8],
37 ) -> Result<usize, Self::Error>;
38
39 fn flush_once(&mut self) -> Result<(), Self::Error>;
46}
47
48pub trait AsyncWrite {
52 type Error: WriteError;
54
55 fn poll_write_slice(
60 self: Pin<&mut Self>,
61 cx: &mut Context,
62 buf: &[u8],
63 ) -> Poll<Result<usize, Self::Error>>;
64
65 fn poll_flush_once(
67 self: Pin<&mut Self>,
68 cx: &mut Context,
69 ) -> Poll<Result<(), Self::Error>>;
70}
71
72pub trait WriteExt: Write {
76 fn write_buf<B>(&mut self, buf: B) -> Result<(), Self::Error>
78 where
79 B: Buf,
80 {
81 write_buf(self, buf)
82 }
83
84 fn write_buf_all<B>(&mut self, buf: B) -> Result<(), Self::Error>
89 where
90 B: Buf,
91 {
92 write_buf_all(self, buf)
93 }
94
95 fn flush(&mut self) -> Result<(), Self::Error> {
97 flush(self)
98 }
99
100 fn by_ref(&mut self) -> &mut Self
103 where
104 Self: Sized,
105 {
106 self
107 }
108
109 #[cfg(feature = "alloc")]
113 fn transaction(
114 self,
115 kind: WriteTransactionKind,
116 ) -> WriteTransactionVariant<'_, Self>
117 where
118 Self: Sized,
119 {
120 WriteTransactionVariant::new(self, kind)
121 }
122}
123
124pub trait AsyncWriteExt: AsyncWrite {
130 fn poll_write_buf<B>(
132 self: Pin<&mut Self>,
133 cx: &mut Context,
134 buf: &mut B,
135 ) -> Poll<Result<(), Self::Error>>
136 where
137 B: Buf + ?Sized,
138 {
139 poll_write_buf(self, cx, buf)
140 }
141
142 fn poll_write_buf_all<B>(
144 self: Pin<&mut Self>,
145 cx: &mut Context,
146 buf: &mut B,
147 ) -> Poll<Result<(), Self::Error>>
148 where
149 B: Buf + ?Sized,
150 {
151 poll_write_buf_all(self, cx, buf)
152 }
153
154 fn poll_flush(
156 self: Pin<&mut Self>,
157 cx: &mut Context,
158 ) -> Poll<Result<(), Self::Error>> {
159 poll_flush(self, cx)
160 }
161
162 fn write_buf<B>(&mut self, buf: B) -> WriteBuf<'_, Self, B>
170 where
171 B: Buf + Unpin,
172 Self: Unpin,
173 {
174 WriteBuf::new(self, buf)
175 }
176
177 fn write_buf_all<B>(&mut self, buf: B) -> WriteBufAll<'_, Self, B>
185 where
186 B: Buf + Unpin,
187 Self: Unpin,
188 {
189 WriteBufAll::new(self, buf)
190 }
191
192 fn flush(&mut self) -> Flush<'_, Self>
200 where
201 Self: Unpin,
202 {
203 Flush::new(self)
204 }
205
206 fn by_ref(&mut self) -> &mut Self
209 where
210 Self: Sized,
211 {
212 self
213 }
214
215 #[cfg(feature = "alloc")]
219 fn transaction(
220 self,
221 kind: WriteTransactionKind,
222 ) -> WriteTransactionVariant<'_, Self>
223 where
224 Self: Sized,
225 {
226 WriteTransactionVariant::new(self, kind)
227 }
228}
229
230impl<T: Write + ?Sized> WriteExt for T {}
231
232impl<T: AsyncWrite + ?Sized> AsyncWriteExt for T {}
233
234fn write_buf<T, B>(writer: &mut T, mut buf: B) -> Result<(), T::Error>
235where
236 T: WriteExt + ?Sized,
237 B: Buf,
238{
239 if !buf.has_remaining() {
240 return Ok(());
241 }
242
243 loop {
244 match writer.write_slice(buf.chunk()) {
245 Ok(0) => return Err(T::Error::write_zero()),
246 Ok(n) => {
247 buf.advance(n);
248 return Ok(());
249 },
250 Err(e) if e.should_retry() => continue,
251 Err(e) => return Err(e),
252 }
253 }
254}
255
256fn poll_write_buf<T, B>(
257 mut writer: Pin<&mut T>,
258 cx: &mut Context,
259 buf: &mut B,
260) -> Poll<Result<(), T::Error>>
261where
262 T: AsyncWriteExt + ?Sized,
263 B: Buf + ?Sized,
264{
265 use Poll::Ready;
266
267 if !buf.has_remaining() {
268 return Ready(Ok(()));
269 }
270
271 loop {
272 match ready!(writer
273 .as_mut()
274 .poll_write_slice(cx, buf.chunk()))
275 {
276 Ok(0) => return Ready(Err(T::Error::write_zero())),
277 Ok(n) => {
278 buf.advance(n);
279 return Ready(Ok(()));
280 },
281 Err(e) if e.should_retry() => continue,
282 Err(e) => return Ready(Err(e)),
283 }
284 }
285}
286
287fn write_buf_all<T, B>(
288 writer: &mut T,
289 mut buf: B,
290) -> Result<(), T::Error>
291where
292 T: WriteExt + ?Sized,
293 B: Buf,
294{
295 while buf.has_remaining() {
296 match writer.write_slice(buf.chunk()) {
297 Ok(0) => return Err(T::Error::write_zero()),
298 Ok(n) => buf.advance(n),
299 Err(e) if e.should_retry() => continue,
300 Err(e) => return Err(e),
301 }
302 }
303
304 Ok(())
305}
306
307fn poll_write_buf_all<T, B>(
308 mut writer: Pin<&mut T>,
309 cx: &mut Context,
310 buf: &mut B,
311) -> Poll<Result<(), T::Error>>
312where
313 T: AsyncWriteExt + ?Sized,
314 B: Buf + ?Sized,
315{
316 use Poll::Ready;
317
318 while buf.has_remaining() {
319 match ready!(writer
320 .as_mut()
321 .poll_write_slice(cx, buf.chunk()))
322 {
323 Ok(0) => return Ready(Err(T::Error::write_zero())),
324 Ok(n) => buf.advance(n),
325 Err(e) if e.should_retry() => continue,
326 Err(e) => return Ready(Err(e)),
327 }
328 }
329
330 Ready(Ok(()))
331}
332
333fn flush<T>(writer: &mut T) -> Result<(), T::Error>
334where
335 T: WriteExt + ?Sized,
336{
337 loop {
338 match writer.flush_once() {
339 Ok(()) => break Ok(()),
340 Err(e) if e.should_retry() => continue,
341 Err(e) => break Err(e),
342 }
343 }
344}
345
346fn poll_flush<T>(
347 mut writer: Pin<&mut T>,
348 cx: &mut Context,
349) -> Poll<Result<(), T::Error>>
350where
351 T: AsyncWrite + ?Sized,
352{
353 loop {
354 match ready!(writer.as_mut().poll_flush_once(cx)) {
355 Ok(()) => return Poll::Ready(Ok(())),
356 Err(e) if e.should_retry() => continue,
357 Err(e) => return Poll::Ready(Err(e)),
358 }
359 }
360}
361
362macro_rules! forward_impl_write {
363 ($to:ty) => {
364 type Error = <$to>::Error;
365
366 fn write_slice(
367 &mut self,
368 buf: &[u8],
369 ) -> Result<usize, Self::Error> {
370 <$to>::write_slice(self, buf)
371 }
372
373 fn flush_once(&mut self) -> Result<(), Self::Error> {
374 <$to>::flush_once(self)
375 }
376 };
377}
378
379macro_rules! forward_impl_async_write {
380 ($to:ty) => {
381 type Error = <$to>::Error;
382
383 fn poll_write_slice(
384 mut self: Pin<&mut Self>,
385 cx: &mut Context,
386 buf: &[u8],
387 ) -> Poll<Result<usize, Self::Error>> {
388 let this = Pin::new(&mut **self);
389 <$to>::poll_write_slice(this, cx, buf)
390 }
391
392 fn poll_flush_once(
393 mut self: Pin<&mut Self>,
394 cx: &mut Context,
395 ) -> Poll<Result<(), Self::Error>> {
396 let this = Pin::new(&mut **self);
397 <$to>::poll_flush_once(this, cx)
398 }
399 };
400}
401
402impl<T: Write + ?Sized> Write for &mut T {
403 forward_impl_write!(T);
404}
405
406impl<T: AsyncWrite + Unpin + ?Sized> AsyncWrite for &mut T {
407 forward_impl_async_write!(T);
408}
409
410#[cfg(feature = "alloc")]
411impl<T: Write + ?Sized> Write for alloc::boxed::Box<T> {
412 forward_impl_write!(T);
413}
414
415#[cfg(feature = "alloc")]
416impl<T: AsyncWrite + Unpin + ?Sized> AsyncWrite
417 for alloc::boxed::Box<T>
418{
419 forward_impl_async_write!(T);
420}