multipart_write/write/
with.rs

1use crate::{FusedMultipartWrite, MultipartWrite};
2
3use futures_core::ready;
4use std::fmt::{self, Debug, Formatter};
5use std::pin::Pin;
6use std::task::{Context, Poll};
7
8pin_project_lite::pin_project! {
9    /// `MultipartWrite` for [`with`](super::MultipartWriteExt::with).
10    #[must_use = "futures do nothing unless polled"]
11    pub struct With<Wr, Part, Fut, F> {
12        #[pin]
13        writer: Wr,
14        f: F,
15        #[pin]
16        future: Option<Fut>,
17        buffered: Option<Part>,
18    }
19}
20
21impl<Wr, Part, Fut, F> With<Wr, Part, Fut, F> {
22    pub(super) fn new(writer: Wr, f: F) -> Self {
23        Self {
24            writer,
25            f,
26            future: None,
27            buffered: None,
28        }
29    }
30
31    /// Consumes `With`, returning the underlying writer.
32    pub fn into_inner(self) -> Wr {
33        self.writer
34    }
35
36    /// Acquires a reference to the underlying writer.
37    pub fn get_ref(&self) -> &Wr {
38        &self.writer
39    }
40
41    /// Acquires a mutable reference to the underlying writer.
42    ///
43    /// It is inadvisable to directly write to the underlying writer.
44    pub fn get_mut(&mut self) -> &mut Wr {
45        &mut self.writer
46    }
47
48    /// Acquires a pinned mutable reference to the underlying writer.
49    ///
50    /// It is inadvisable to directly write to the underlying writer.
51    pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut Wr> {
52        self.project().writer
53    }
54
55    fn poll<U, E>(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), E>>
56    where
57        Wr: MultipartWrite<Part>,
58        F: FnMut(U) -> Fut,
59        Fut: Future<Output = Result<Part, E>>,
60        E: From<Wr::Error>,
61    {
62        let mut this = self.project();
63
64        if this.buffered.is_some() {
65            match this.writer.as_mut().poll_ready(cx)? {
66                Poll::Ready(()) => {
67                    this.writer.start_send(this.buffered.take().unwrap())?;
68                }
69                Poll::Pending => return Poll::Pending,
70            }
71        }
72        if let Some(fut) = this.future.as_mut().as_pin_mut() {
73            let part = ready!(fut.poll(cx))?;
74            *this.buffered = Some(part);
75            this.future.set(None);
76        }
77
78        Poll::Ready(Ok(()))
79    }
80}
81
82impl<U, E, Wr, Part, Fut, F> FusedMultipartWrite<U> for With<Wr, Part, Fut, F>
83where
84    Wr: FusedMultipartWrite<Part>,
85    F: FnMut(U) -> Fut,
86    Fut: Future<Output = Result<Part, E>>,
87    E: From<Wr::Error>,
88{
89    fn is_terminated(&self) -> bool {
90        self.writer.is_terminated()
91    }
92}
93
94impl<U, E, Wr, Part, Fut, F> MultipartWrite<U> for With<Wr, Part, Fut, F>
95where
96    Wr: MultipartWrite<Part>,
97    F: FnMut(U) -> Fut,
98    Fut: Future<Output = Result<Part, E>>,
99    E: From<Wr::Error>,
100{
101    type Ret = ();
102    type Output = Wr::Output;
103    type Error = E;
104
105    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
106        ready!(self.as_mut().poll(cx))?;
107        self.project().writer.poll_ready(cx).map_err(E::from)
108    }
109
110    fn start_send(self: Pin<&mut Self>, part: U) -> Result<Self::Ret, Self::Error> {
111        let mut this = self.project();
112        this.future.set(Some((this.f)(part)));
113        Ok(())
114    }
115
116    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
117        ready!(self.as_mut().poll(cx))?;
118        ready!(self.project().writer.poll_flush(cx)?);
119        Poll::Ready(Ok(()))
120    }
121
122    fn poll_complete(
123        mut self: Pin<&mut Self>,
124        cx: &mut Context<'_>,
125    ) -> Poll<Result<Self::Output, Self::Error>> {
126        ready!(self.as_mut().poll(cx))?;
127        let out = ready!(self.project().writer.poll_complete(cx))?;
128        Poll::Ready(Ok(out))
129    }
130}
131
132impl<Wr, Part, Fut, F> Debug for With<Wr, Part, Fut, F>
133where
134    Wr: Debug,
135    Fut: Debug,
136    Part: Debug,
137{
138    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
139        f.debug_struct("With")
140            .field("writer", &self.writer)
141            .field("f", &"impl FnMut(U) -> Fut")
142            .field("future", &self.future)
143            .field("buffered", &self.buffered)
144            .finish()
145    }
146}