Skip to main content

multipart_write/write/
ready_part.rs

1use std::fmt::{self, Debug, Formatter};
2use std::marker::PhantomData;
3use std::pin::Pin;
4use std::task::{Context, Poll};
5
6use futures_core::ready;
7
8use crate::{FusedMultipartWrite, MultipartWrite};
9
10pin_project_lite::pin_project! {
11    /// `MultipartWrite` for [`ready_part`].
12    ///
13    /// [`ready_part`]: super::MultipartWriteExt::ready_part
14    #[must_use = "futures do nothing unless polled"]
15    pub struct ReadyPart<Wr, Part, P, Fut, F> {
16        #[pin]
17        writer: Wr,
18        f: F,
19        #[pin]
20        future: Option<Fut>,
21        buffered: Option<Part>,
22        _p: PhantomData<fn(P) -> Part>,
23    }
24}
25
26impl<Wr, Part, P, Fut, F> ReadyPart<Wr, Part, P, Fut, F> {
27    pub(super) fn new(writer: Wr, f: F) -> Self {
28        Self { writer, f, future: None, buffered: None, _p: PhantomData }
29    }
30
31    /// Consumes `ReadyPart`, 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(
56        self: Pin<&mut Self>,
57        cx: &mut Context,
58    ) -> Poll<Result<(), Wr::Error>>
59    where
60        Wr: MultipartWrite<Part>,
61        F: FnMut(P) -> Fut,
62        Fut: Future<Output = Result<Part, Wr::Error>>,
63    {
64        let mut this = self.project();
65
66        if this.buffered.is_some() {
67            match this.writer.as_mut().poll_ready(cx)? {
68                Poll::Ready(()) => {
69                    this.writer.start_send(this.buffered.take().unwrap())?;
70                },
71                Poll::Pending => return Poll::Pending,
72            }
73        }
74        if let Some(fut) = this.future.as_mut().as_pin_mut() {
75            let part = ready!(fut.poll(cx))?;
76            *this.buffered = Some(part);
77            this.future.set(None);
78        }
79
80        Poll::Ready(Ok(()))
81    }
82}
83
84impl<Wr, Part, P, Fut, F> FusedMultipartWrite<P>
85    for ReadyPart<Wr, Part, P, Fut, F>
86where
87    Wr: FusedMultipartWrite<Part>,
88    F: FnMut(P) -> Fut,
89    Fut: Future<Output = Result<Part, Wr::Error>>,
90{
91    fn is_terminated(&self) -> bool {
92        self.writer.is_terminated()
93    }
94}
95
96impl<Wr, Part, P, Fut, F> MultipartWrite<P> for ReadyPart<Wr, Part, P, Fut, F>
97where
98    Wr: MultipartWrite<Part>,
99    F: FnMut(P) -> Fut,
100    Fut: Future<Output = Result<Part, Wr::Error>>,
101{
102    type Error = Wr::Error;
103    type Output = Wr::Output;
104    type Recv = ();
105
106    fn poll_ready(
107        mut self: Pin<&mut Self>,
108        cx: &mut Context<'_>,
109    ) -> Poll<Result<(), Self::Error>> {
110        ready!(self.as_mut().poll(cx))?;
111        self.project().writer.poll_ready(cx)
112    }
113
114    fn start_send(
115        self: Pin<&mut Self>,
116        part: P,
117    ) -> Result<Self::Recv, Self::Error> {
118        let mut this = self.project();
119        this.future.set(Some((this.f)(part)));
120        Ok(())
121    }
122
123    fn poll_flush(
124        mut self: Pin<&mut Self>,
125        cx: &mut Context<'_>,
126    ) -> Poll<Result<(), Self::Error>> {
127        ready!(self.as_mut().poll(cx))?;
128        ready!(self.project().writer.poll_flush(cx)?);
129        Poll::Ready(Ok(()))
130    }
131
132    fn poll_complete(
133        mut self: Pin<&mut Self>,
134        cx: &mut Context<'_>,
135    ) -> Poll<Result<Self::Output, Self::Error>> {
136        ready!(self.as_mut().poll(cx))?;
137        let out = ready!(self.project().writer.poll_complete(cx))?;
138        Poll::Ready(Ok(out))
139    }
140}
141
142impl<Wr, Part, P, Fut, F> Debug for ReadyPart<Wr, Part, P, Fut, F>
143where
144    Wr: Debug,
145    Fut: Debug,
146    Part: Debug,
147{
148    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
149        f.debug_struct("ReadyPart")
150            .field("writer", &self.writer)
151            .field("future", &self.future)
152            .field("buffered", &self.buffered)
153            .finish()
154    }
155}