multipart_write/write/
mod.rs

1//! `MultipartWrite` combinators.
2//!
3//! This module contains the trait [`MultipartWriteExt`], which provides adapters
4//! for chaining and composing `MultipartWrite`rs.
5use crate::{BoxMultipartWrite, LocalBoxMultipartWrite, MultipartWrite};
6
7use futures_core::future::Future;
8use std::pin::Pin;
9use std::task::{Context, Poll};
10
11mod and_then;
12pub use and_then::AndThen;
13
14mod buffered;
15pub use buffered::Buffered;
16
17mod complete;
18pub use complete::Complete;
19
20mod extend;
21pub use extend::{Extend, extend};
22
23mod fanout;
24pub use fanout::Fanout;
25
26mod feed;
27pub use feed::Feed;
28
29mod filter;
30pub use filter::Filter;
31
32mod filter_map;
33pub use filter_map::FilterMap;
34
35mod fold_ret;
36pub use fold_ret::FoldRet;
37
38mod flush;
39pub use flush::Flush;
40
41mod fuse;
42pub use fuse::Fuse;
43
44mod lift;
45pub use lift::Lift;
46
47mod map_err;
48pub use map_err::MapErr;
49
50mod map_ret;
51pub use map_ret::MapRet;
52
53mod map_ok;
54pub use map_ok::MapOk;
55
56mod send_part;
57pub use send_part::SendPart;
58
59mod then;
60pub use then::Then;
61
62mod with;
63pub use with::With;
64
65impl<Wr: MultipartWrite<Part>, Part> MultipartWriteExt<Part> for Wr {}
66
67/// An extension trait for `MultipartWrite` providing a variety of convenient
68/// combinator functions.
69pub trait MultipartWriteExt<Part>: MultipartWrite<Part> {
70    /// Compute from this writer's output type a new output of a different type
71    /// using an asynchronous closure.
72    ///
73    /// Calling `poll_complete` on this writer will complete the inner writer,
74    /// then run the provided closure `f` with the output to produce the final
75    /// output of this writer.
76    fn and_then<T, E, Fut, F>(self, f: F) -> AndThen<Self, Fut, F>
77    where
78        F: FnMut(Self::Output) -> Fut,
79        Fut: Future<Output = Result<T, E>>,
80        E: From<Self::Error>,
81        Self: Sized,
82    {
83        AndThen::new(self, f)
84    }
85
86    /// Wrap this writer in a `Box`, pinning it.
87    fn boxed<'a>(self) -> BoxMultipartWrite<'a, Part, Self::Ret, Self::Output, Self::Error>
88    where
89        Self: Sized + Send + 'a,
90    {
91        Box::pin(self)
92    }
93
94    /// Wrap this writer in a `Box`, pinning it.
95    ///
96    /// Similar to `boxed` but without the `Send` requirement.
97    fn boxed_local<'a>(
98        self,
99    ) -> LocalBoxMultipartWrite<'a, Part, Self::Ret, Self::Output, Self::Error>
100    where
101        Self: Sized + 'a,
102    {
103        Box::pin(self)
104    }
105
106    /// Adds a fixed size buffer to the current writer.
107    ///
108    /// The resulting `MultipartWrite` will buffer up to `capacity` items when
109    /// the underlying writer is not able to accept new parts.
110    fn buffered(self, capacity: impl Into<Option<usize>>) -> Buffered<Self, Part>
111    where
112        Self: Sized,
113    {
114        Buffered::new(self, capacity.into().unwrap_or_default())
115    }
116
117    /// A future that runs this writer to completion, returning the associated
118    /// output.
119    fn complete(&mut self) -> Complete<'_, Self, Part>
120    where
121        Self: Unpin,
122    {
123        Complete::new(self)
124    }
125
126    /// Fanout the part to multiple writers.
127    ///
128    /// This adapter clones each incoming part and forwards it to both writers.
129    fn fanout<U>(self, other: U) -> Fanout<Self, U, Part>
130    where
131        Part: Clone,
132        U: MultipartWrite<Part, Error = Self::Error>,
133        Self: Sized,
134    {
135        Fanout::new(self, other)
136    }
137
138    /// A future that completes after the given part has been received by the
139    /// writer.
140    ///
141    /// Unlike `send_part`, the returned future does not flush the writer.  It is
142    /// the caller's responsibility to ensure all pending items are processed,
143    /// which can be done with `flush` or `complete`.
144    fn feed(&mut self, part: Part) -> Feed<'_, Self, Part>
145    where
146        Self: Unpin,
147    {
148        Feed::new(self, part)
149    }
150
151    /// Apply a filter to this writer's parts, returning a new writer with the
152    /// same output.
153    ///
154    /// The return type of this writer is `Option<Self::Ret>` and is `None` when
155    /// the part did not pass the filter.
156    fn filter<F>(self, f: F) -> Filter<Self, F>
157    where
158        F: FnMut(&Part) -> bool,
159        Self: Sized,
160    {
161        Filter::new(self, f)
162    }
163
164    /// Attempt to map the input to a part for this writer, filtering out the
165    /// inputs where the mapping returns `None`.
166    ///
167    /// The return type of this writer is `Option<Self::Ret>` and is `None` when
168    /// the mapping of the input `U` did not pass the filter.
169    fn filter_map<U, F>(self, f: F) -> FilterMap<Self, F>
170    where
171        F: FnMut(U) -> Option<Part>,
172        Self: Sized,
173    {
174        FilterMap::new(self, f)
175    }
176
177    /// A future that completes when the underlying writer has been flushed.
178    fn flush(&mut self) -> Flush<'_, Self, Part>
179    where
180        Self: Unpin,
181    {
182        Flush::new(self)
183    }
184
185    /// Accumulate this writer's returned values, returning a new multipart
186    /// writer that pairs the underlying writer's output with the
187    /// result of the accumulating function.
188    fn fold_ret<T, F>(self, id: T, f: F) -> FoldRet<Self, T, F>
189    where
190        F: FnMut(T, &Self::Ret) -> T,
191        Self: Sized,
192    {
193        FoldRet::new(self, id, f)
194    }
195
196    /// Returns a new writer that fuses according to the provided closure.
197    ///
198    /// The resulting writer wraps both `Self::Ret` and `Self::Output` in an
199    /// `Option` and is guaranted to both output and return `Ok(None)` when
200    /// called after becoming fused.
201    fn fuse<F>(self, f: F) -> Fuse<Self, F>
202    where
203        F: FnMut(&Self::Output) -> bool,
204        Self: Sized,
205    {
206        Fuse::new(self, f)
207    }
208
209    /// "Lift" the multipart writer `U` in front of this one.
210    ///
211    /// The result is a new multipart writer that writes parts for `U`, using the
212    /// output of `U` to source the parts to write to this writer, and resolving
213    /// to the output of this writer when polled to completion.
214    ///
215    /// In other words, it expresses this multipart writer as being built from
216    /// the parts of another multipart writer.
217    fn lift<U, T>(self, other: U) -> Lift<Self, U, Part>
218    where
219        U: MultipartWrite<T, Output = Part>,
220        Self: MultipartWrite<Part> + Sized,
221        Self::Error: From<U::Error>,
222    {
223        Lift::new(self, other)
224    }
225
226    /// Map this writer's error type to a different value, returning a new
227    /// multipart writer with the given error type.
228    fn map_err<E, F>(self, f: F) -> MapErr<Self, F>
229    where
230        F: FnMut(Self::Error) -> E,
231        Self: Sized,
232    {
233        MapErr::new(self, f)
234    }
235
236    /// Map this writer's output type to a different type, returning a new
237    /// multipart writer with the given output type.
238    fn map_ok<U, F>(self, f: F) -> MapOk<Self, F>
239    where
240        F: FnMut(Self::Output) -> U,
241        Self: Sized,
242    {
243        MapOk::new(self, f)
244    }
245
246    /// Map this writer's return type to a different value, returning a new
247    /// multipart writer with the given return type.
248    fn map_ret<U, F>(self, f: F) -> MapRet<Self, F>
249    where
250        F: FnMut(Self::Ret) -> U,
251        Self: Sized,
252    {
253        MapRet::new(self, f)
254    }
255
256    /// A convenience method for calling [`MultipartWrite::poll_ready`] on
257    /// [`Unpin`] writer types.
258    #[must_use = "futures do nothing unless polled"]
259    fn poll_ready_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>
260    where
261        Self: Unpin,
262    {
263        Pin::new(self).poll_ready(cx)
264    }
265
266    /// A convenience method for calling [`MultipartWrite::poll_flush`] on
267    /// [`Unpin`] writer types.
268    #[must_use = "futures do nothing unless polled"]
269    fn poll_flush_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>
270    where
271        Self: Unpin,
272    {
273        Pin::new(self).poll_flush(cx)
274    }
275
276    /// A convenience method for calling [`MultipartWrite::poll_complete`] on
277    /// [`Unpin`] writer types.
278    #[must_use = "futures do nothing unless polled"]
279    fn poll_complete_unpin(
280        &mut self,
281        cx: &mut Context<'_>,
282    ) -> Poll<Result<Self::Output, Self::Error>>
283    where
284        Self: Unpin,
285    {
286        Pin::new(self).poll_complete(cx)
287    }
288
289    /// A future that completes when a part has been fully processed into the
290    /// writer, including flushing.
291    fn send_part(&mut self, part: Part) -> SendPart<'_, Self, Part>
292    where
293        Self: Unpin,
294    {
295        SendPart::new(self, part)
296    }
297
298    /// Chain an asynchronous computation on the result of polling the writer for
299    /// completion.
300    fn then<T, E, Fut, F>(self, f: F) -> Then<Self, Fut, F>
301    where
302        F: FnMut(Result<Self::Output, Self::Error>) -> Fut,
303        Fut: Future<Output = Result<T, E>>,
304        E: From<Self::Error>,
305        Self: Sized,
306    {
307        Then::new(self, f)
308    }
309
310    /// Provide a part to this writer in the output of a future.
311    ///
312    /// The result is a new writer over the type `U` that passes each value
313    /// through the function `f`, resolving the output, and sending it to the
314    /// inner writer.
315    fn with<U, E, Fut, F>(self, f: F) -> With<Self, Part, Fut, F>
316    where
317        F: FnMut(U) -> Fut,
318        Fut: Future<Output = Result<Part, E>>,
319        E: From<Self::Error>,
320        Self: Sized,
321    {
322        With::new(self, f)
323    }
324}