multipart_write/write/
bootstrapped.rs

1use crate::{FusedMultipartWrite, MultipartWrite};
2
3use futures_core::{Future, 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 [`bootstrapped`].
10    ///
11    /// [`bootstrapped`]: super::MultipartWriteExt::bootstrapped
12    #[must_use = "futures do nothing unless polled"]
13    pub struct Bootstrapped<Wr, S, F, Fut> {
14        #[pin]
15        writer: Option<Wr>,
16        f: F,
17        s: S,
18        #[pin]
19        future: Option<Fut>,
20        _f: std::marker::PhantomData<fn(S)>,
21    }
22}
23
24impl<Wr, S, F, Fut> Bootstrapped<Wr, S, F, Fut> {
25    pub(super) fn new(writer: Wr, s: S, f: F) -> Self {
26        Self {
27            writer: Some(writer),
28            f,
29            s,
30            future: None,
31            _f: std::marker::PhantomData,
32        }
33    }
34
35    fn poll_new_writer<Part>(
36        self: Pin<&mut Self>,
37        cx: &mut Context<'_>,
38    ) -> Poll<Result<(), Wr::Error>>
39    where
40        Wr: MultipartWrite<Part>,
41        F: FnMut(&mut S) -> Fut,
42        Fut: Future<Output = Result<Option<Wr>, Wr::Error>>,
43    {
44        let mut this = self.project();
45        if this.future.is_none() {
46            let fut = (this.f)(this.s);
47            this.future.set(Some(fut));
48        }
49        let fut = this.future.as_mut().as_pin_mut().unwrap();
50        match ready!(fut.poll(cx)) {
51            Ok(wr) => {
52                this.future.set(None);
53                this.writer.set(wr);
54                Poll::Ready(Ok(()))
55            }
56            Err(e) => {
57                this.future.set(None);
58                Poll::Ready(Err(e))
59            }
60        }
61    }
62}
63
64impl<Wr, S, F, Fut, Part> FusedMultipartWrite<Part> for Bootstrapped<Wr, S, F, Fut>
65where
66    Wr: FusedMultipartWrite<Part>,
67    F: FnMut(&mut S) -> Fut,
68    Fut: Future<Output = Result<Option<Wr>, Wr::Error>>,
69{
70    fn is_terminated(&self) -> bool {
71        self.writer.is_none() && self.future.is_none()
72    }
73}
74
75impl<Wr, S, F, Fut, Part> MultipartWrite<Part> for Bootstrapped<Wr, S, F, Fut>
76where
77    Wr: MultipartWrite<Part>,
78    F: FnMut(&mut S) -> Fut,
79    Fut: Future<Output = Result<Option<Wr>, Wr::Error>>,
80{
81    type Ret = Wr::Ret;
82    type Output = Wr::Output;
83    type Error = Wr::Error;
84
85    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
86        if self.writer.is_none() {
87            ready!(self.as_mut().poll_new_writer(cx))?;
88        }
89        let mut this = self.project();
90        let wr = this.writer.as_mut().as_pin_mut().unwrap();
91        wr.poll_ready(cx)
92    }
93
94    fn start_send(self: Pin<&mut Self>, part: Part) -> Result<Self::Ret, Self::Error> {
95        let mut this = self.project();
96        assert!(this.writer.is_some());
97        let wr = this.writer.as_mut().as_pin_mut().unwrap();
98        wr.start_send(part)
99    }
100
101    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
102        let mut this = self.project();
103        let wr = this
104            .writer
105            .as_mut()
106            .as_pin_mut()
107            .expect("polled Bootstrapped after completion");
108        wr.poll_flush(cx)
109    }
110
111    fn poll_complete(
112        self: Pin<&mut Self>,
113        cx: &mut Context<'_>,
114    ) -> Poll<Result<Self::Output, Self::Error>> {
115        let mut this = self.project();
116        let wr = this
117            .writer
118            .as_mut()
119            .as_pin_mut()
120            .expect("polled Bootstrapped after completion");
121        let output = ready!(wr.poll_complete(cx));
122        this.writer.set(None);
123        Poll::Ready(output)
124    }
125}
126
127impl<Wr, S, F, Fut> Debug for Bootstrapped<Wr, S, F, Fut>
128where
129    Wr: Debug,
130    S: Debug,
131    Fut: Debug,
132{
133    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
134        f.debug_struct("Bootstrapped")
135            .field("writer", &self.writer)
136            .field("f", &"F")
137            .field("s", &self.s)
138            .field("future", &self.future)
139            .finish()
140    }
141}