multipart_write/
lib.rs

1//! # Description
2//!
3//! This crate contains the trait `MultipartWrite`, assorted implementations,
4//! and combinators.
5//!
6//! A `MultipartWrite` is a similar interface to [`Sink`], except that writing
7//! an item or completing the write both return values.
8//!
9//! [`Sink`]: https://docs.rs/crate/futures-sink/0.3.31
10#![cfg_attr(docsrs, feature(doc_cfg))]
11use std::ops::DerefMut;
12use std::pin::Pin;
13use std::task::{Context, Poll};
14
15pub mod io;
16pub mod stream;
17pub mod write;
18
19/// A prelude for this crate.
20pub mod prelude {
21    pub use super::MultipartWrite;
22    pub use super::stream::{self, MultipartStreamExt as _};
23    pub use super::write::{self, MultipartWriteExt as _};
24}
25
26/// `MultipartWrite` is a `Sink`-like interface for asynchronously writing an
27/// object in parts.
28pub trait MultipartWrite<Part> {
29    /// The type of value returned when writing the part began successfully.
30    type Ret;
31
32    /// The type of value returned when all parts are written.
33    type Output;
34
35    /// The type of value returned when an operation fails.
36    type Error;
37
38    /// Attempts to prepare the `MultipartWrite` to receive a new part.
39    ///
40    /// This method must be called and return `Poll::Ready` before each call to
41    /// `start_send`, indicating that the underlying writer is ready to have
42    /// another part written to it.
43    ///
44    /// This method returns `Poll::Pending` when the object being prepared cannot
45    /// accept another part.
46    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
47
48    /// Begin the process of writing a part to this writer, returning the
49    /// associated type confirming this was done successfully.
50    ///
51    /// Like `Sink`, this should be preceded by a call to `poll_ready` that
52    /// returns `Poll::Ready` to ensure that the `MultipartWrite` is ready to
53    /// receive a new part.
54    ///
55    /// # Errors
56    ///
57    /// Errors returned by this method are implementation-specific, but it is
58    /// always an error to call `start_send` when `poll_ready` would return
59    /// `Poll::Pending`.
60    fn start_send(self: Pin<&mut Self>, part: Part) -> Result<Self::Ret, Self::Error>;
61
62    /// Flush any remaining output from the writer.
63    ///
64    /// Returns `Poll::Ready` when no parts remain and `Poll::Pending` if there
65    /// is more work left to do.
66    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
67
68    /// Complete this writer, returning the output.
69    ///
70    /// This method returns `Poll::Pending` until no buffered, unwritten parts
71    /// remain and the complete output object is available.
72    fn poll_complete(
73        self: Pin<&mut Self>,
74        cx: &mut Context<'_>,
75    ) -> Poll<Result<Self::Output, Self::Error>>;
76}
77
78/// An owned, dynamically typed [`MultipartWrite`] for use in cases where it is
79/// not possible or desirable to statically type it.
80pub type BoxMultipartWrite<'a, Part, R, T, E> =
81    Pin<Box<dyn MultipartWrite<Part, Ret = R, Output = T, Error = E> + Send + 'a>>;
82
83/// `BoxMultipartWrite` but without the `Send` requirement.
84pub type LocalBoxMultipartWrite<'a, Part, R, T, E> =
85    Pin<Box<dyn MultipartWrite<Part, Ret = R, Output = T, Error = E> + 'a>>;
86
87/// A writer that tracks whether or not the underlying writer should no longer
88/// be polled.
89pub trait FusedMultipartWrite<Part>: MultipartWrite<Part> {
90    /// Returns `true` if the writer should no longer be polled.
91    fn is_terminated(&self) -> bool;
92}
93
94impl<W: ?Sized + MultipartWrite<Part> + Unpin, Part> MultipartWrite<Part> for &mut W {
95    type Ret = W::Ret;
96    type Output = W::Output;
97    type Error = W::Error;
98
99    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
100        Pin::new(&mut **self).poll_ready(cx)
101    }
102
103    fn start_send(mut self: Pin<&mut Self>, part: Part) -> Result<Self::Ret, Self::Error> {
104        Pin::new(&mut **self).start_send(part)
105    }
106
107    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
108        Pin::new(&mut **self).poll_flush(cx)
109    }
110
111    fn poll_complete(
112        mut self: Pin<&mut Self>,
113        cx: &mut Context<'_>,
114    ) -> Poll<Result<Self::Output, Self::Error>> {
115        Pin::new(&mut **self).poll_complete(cx)
116    }
117}
118
119impl<W: ?Sized + FusedMultipartWrite<Part> + Unpin, Part> FusedMultipartWrite<Part> for &mut W {
120    fn is_terminated(&self) -> bool {
121        <W as FusedMultipartWrite<Part>>::is_terminated(&**self)
122    }
123}
124
125impl<P, Part> MultipartWrite<Part> for Pin<P>
126where
127    P: DerefMut + Unpin,
128    P::Target: MultipartWrite<Part>,
129{
130    type Ret = <P::Target as MultipartWrite<Part>>::Ret;
131    type Output = <P::Target as MultipartWrite<Part>>::Output;
132    type Error = <P::Target as MultipartWrite<Part>>::Error;
133
134    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
135        self.get_mut().as_mut().poll_ready(cx)
136    }
137
138    fn start_send(self: Pin<&mut Self>, part: Part) -> Result<Self::Ret, Self::Error> {
139        self.get_mut().as_mut().start_send(part)
140    }
141
142    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
143        self.get_mut().as_mut().poll_flush(cx)
144    }
145
146    fn poll_complete(
147        self: Pin<&mut Self>,
148        cx: &mut Context<'_>,
149    ) -> Poll<Result<Self::Output, Self::Error>> {
150        self.get_mut().as_mut().poll_complete(cx)
151    }
152}
153
154impl<P, Part> FusedMultipartWrite<Part> for Pin<P>
155where
156    P: DerefMut + Unpin,
157    P::Target: FusedMultipartWrite<Part>,
158{
159    fn is_terminated(&self) -> bool {
160        <P::Target as FusedMultipartWrite<Part>>::is_terminated(&**self)
161    }
162}