Skip to main content

multipart_write/write/
resolve.rs

1use std::fmt::{self, Debug, Formatter};
2use std::ops::{Deref, DerefMut};
3use std::pin::Pin;
4use std::task::{Context, Poll};
5
6use futures_core::{Future, ready};
7
8use crate::{FusedMultipartWrite, MultipartWrite};
9
10/// Create a `MultipartWrite` from a future that resolves to one.
11///
12/// Call `poll_ready` first to satisfy the API contract.  The first time
13/// `poll_ready` is called creates the writer and returns `Poll::Pending` until
14/// it exists. inner writer type, at which point it can be used normally.
15///
16/// A `poll_complete` does not drop the inner writer, but it  may or may not be
17/// usable.  It depends on the particular implementation; `Resolve` defers to
18/// the inner writer for fusing behavior.
19///
20/// # Panics
21///
22/// Panics when `poll_ready` is not called first in order to poll the provided
23/// future resolving to the writer.
24pub fn resolve<Wr, E, Fut>(fut: Fut) -> Resolve<Fut, Wr>
25where
26    Fut: Future<Output = Result<Wr, E>>,
27{
28    Resolve::new(fut)
29}
30
31pin_project_lite::pin_project! {
32    /// Writer returned by [`resolve`].
33    #[must_use = "futures do nothing unless polled"]
34    pub struct Resolve<Fut, Wr> {
35        #[pin]
36        fut: Option<Fut>,
37        #[pin]
38        writer: Option<Wr>,
39    }
40}
41
42impl<Fut, Wr> Resolve<Fut, Wr> {
43    fn new(fut: Fut) -> Self {
44        Self { fut: Some(fut), writer: None }
45    }
46
47    /// Returns whether this writer has had the inner writer created.
48    pub fn has_writer(&self) -> bool {
49        self.writer.is_some()
50    }
51
52    /// Consumes `Resolve`, returning the underlying writer.
53    pub fn into_inner(self) -> Option<Wr> {
54        self.writer
55    }
56
57    /// Acquires a reference to the underlying writer.
58    pub fn as_ref(&self) -> Option<&Wr> {
59        self.writer.as_ref()
60    }
61
62    /// Returns a reference to the inner writer's `Deref::Target`.
63    pub fn as_deref(&self) -> Option<&Wr::Target>
64    where
65        Wr: Deref,
66    {
67        self.writer.as_deref()
68    }
69
70    /// Returns a mutable reference to the inner writer's `Deref::Target`.
71    pub fn as_deref_mut(&mut self) -> Option<&mut Wr::Target>
72    where
73        Wr: DerefMut,
74    {
75        self.writer.as_deref_mut()
76    }
77
78    /// Project a pin onto the inner writer, returning it in an option.
79    pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut Wr>> {
80        self.project().writer.as_pin_mut()
81    }
82
83    fn poll_writer<E>(
84        self: Pin<&mut Self>,
85        cx: &mut Context<'_>,
86    ) -> Poll<Result<(), E>>
87    where
88        Fut: Future<Output = Result<Wr, E>>,
89    {
90        if self.writer.is_some() {
91            return Poll::Ready(Ok(()));
92        }
93        let mut this = self.project();
94        let fut = this
95            .fut
96            .as_mut()
97            .as_pin_mut()
98            .expect("missing both writer and future to create it");
99        let writer = ready!(fut.poll(cx))?;
100        this.writer.set(Some(writer));
101        this.fut.set(None);
102
103        Poll::Ready(Ok(()))
104    }
105}
106
107impl<Wr, Part, E, Fut> FusedMultipartWrite<Part> for Resolve<Fut, Wr>
108where
109    Fut: Future<Output = Result<Wr, E>>,
110    Wr: FusedMultipartWrite<Part, Error = E>,
111{
112    fn is_terminated(&self) -> bool {
113        self.fut.is_none()
114            && self.writer.as_ref().is_some_and(|w| w.is_terminated())
115    }
116}
117
118impl<Wr, Part, E, Fut> MultipartWrite<Part> for Resolve<Fut, Wr>
119where
120    Fut: Future<Output = Result<Wr, E>>,
121    Wr: MultipartWrite<Part, Error = E>,
122{
123    type Error = E;
124    type Output = Wr::Output;
125    type Recv = Wr::Recv;
126
127    fn poll_ready(
128        mut self: Pin<&mut Self>,
129        cx: &mut Context<'_>,
130    ) -> Poll<Result<(), Self::Error>> {
131        ready!(self.as_mut().poll_writer(cx))?;
132        let mut this = self.project();
133
134        this.writer
135            .as_mut()
136            .as_pin_mut()
137            .expect("inner writer lost unexpectedly")
138            .poll_ready(cx)
139    }
140
141    fn start_send(
142        self: Pin<&mut Self>,
143        part: Part,
144    ) -> Result<Self::Recv, Self::Error> {
145        let mut this = self.project();
146        let writer = this
147            .writer
148            .as_mut()
149            .as_pin_mut()
150            .expect("start_send with no existing writer");
151        writer.start_send(part)
152    }
153
154    fn poll_flush(
155        self: Pin<&mut Self>,
156        cx: &mut Context<'_>,
157    ) -> Poll<Result<(), Self::Error>> {
158        let mut this = self.project();
159        let writer = this
160            .writer
161            .as_mut()
162            .as_pin_mut()
163            .expect("poll_flush with no existing writer");
164        writer.poll_flush(cx)
165    }
166
167    fn poll_complete(
168        self: Pin<&mut Self>,
169        cx: &mut Context<'_>,
170    ) -> Poll<Result<Self::Output, Self::Error>> {
171        let mut this = self.project();
172        let writer = this
173            .writer
174            .as_mut()
175            .as_pin_mut()
176            .expect("poll_complete with no existing writer");
177        let out = ready!(writer.poll_complete(cx));
178
179        Poll::Ready(out)
180    }
181}
182
183impl<Fut, Wr> Debug for Resolve<Fut, Wr>
184where
185    Wr: Debug,
186    Fut: Debug,
187{
188    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
189        f.debug_struct("Resolve")
190            .field("fut", &self.fut)
191            .field("writer", &self.writer)
192            .finish()
193    }
194}