Skip to main content

multipart_write/write/
lift.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 [`lift`](super::MultipartWriteExt::lift).
12    #[must_use = "futures do nothing unless polled"]
13    pub struct Lift<Wr, U, P, Part> {
14        #[pin]
15        inner: Wr,
16        #[pin]
17        writer: U,
18        buffered: Option<Part>,
19        _p: PhantomData<fn(P)>,
20    }
21}
22
23impl<Wr, U, P, Part> Lift<Wr, U, P, Part> {
24    pub(super) fn new(inner: Wr, writer: U) -> Self {
25        Self { inner, writer, buffered: None, _p: PhantomData }
26    }
27
28    /// Consumes `Lift`, returning the underlying writer.
29    pub fn into_inner(self) -> Wr {
30        self.inner
31    }
32
33    /// Acquires a reference to the underlying writer.
34    pub fn get_ref(&self) -> &Wr {
35        &self.inner
36    }
37
38    /// Acquires a mutable reference to the underlying writer.
39    ///
40    /// It is inadvisable to directly write to the underlying writer.
41    pub fn get_mut(&mut self) -> &mut Wr {
42        &mut self.inner
43    }
44
45    /// Acquires a pinned mutable reference to the underlying writer.
46    ///
47    /// It is inadvisable to directly write to the underlying writer.
48    pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut Wr> {
49        self.project().inner
50    }
51
52    /// Acquires a reference to the outermost writer.
53    pub fn get_outer_ref(&self) -> &U {
54        &self.writer
55    }
56
57    /// Acquires a mutable reference to the outermost writer.
58    ///
59    /// It is inadvisable to directly write to the outermost writer.
60    pub fn get_outer_mut(&mut self) -> &mut U {
61        &mut self.writer
62    }
63
64    /// Acquires a pinned mutable reference to the outermost writer.
65    ///
66    /// It is inadvisable to directly write to the outermost writer.
67    pub fn get_outer_pin_mut(self: Pin<&mut Self>) -> Pin<&mut U> {
68        self.project().writer
69    }
70
71    fn poll_send_inner(
72        self: Pin<&mut Self>,
73        cx: &mut Context<'_>,
74    ) -> Poll<Result<(), Wr::Error>>
75    where
76        U: MultipartWrite<P, Output = Part>,
77        Wr: MultipartWrite<Part>,
78        Wr::Error: From<U::Error>,
79    {
80        let mut this = self.project();
81
82        if this.buffered.is_none() {
83            let part = ready!(this.writer.as_mut().poll_complete(cx))?;
84            *this.buffered = Some(part);
85        }
86        ready!(this.inner.as_mut().poll_ready(cx))?;
87        let _ =
88            this.inner.as_mut().start_send(this.buffered.take().unwrap())?;
89
90        Poll::Ready(Ok(()))
91    }
92}
93
94impl<Wr, U, P, Part> FusedMultipartWrite<P> for Lift<Wr, U, P, Part>
95where
96    U: FusedMultipartWrite<P, Output = Part>,
97    Wr: FusedMultipartWrite<Part>,
98    Wr::Error: From<U::Error>,
99{
100    fn is_terminated(&self) -> bool {
101        self.inner.is_terminated() || self.writer.is_terminated()
102    }
103}
104
105impl<Wr, U, P, Part> MultipartWrite<P> for Lift<Wr, U, P, Part>
106where
107    U: MultipartWrite<P, Output = Part>,
108    Wr: MultipartWrite<Part>,
109    Wr::Error: From<U::Error>,
110{
111    type Error = Wr::Error;
112    type Output = Wr::Output;
113    type Recv = U::Recv;
114
115    fn poll_ready(
116        self: Pin<&mut Self>,
117        cx: &mut Context<'_>,
118    ) -> Poll<Result<(), Self::Error>> {
119        self.project().writer.as_mut().poll_ready(cx).map_err(Wr::Error::from)
120    }
121
122    fn start_send(
123        self: Pin<&mut Self>,
124        part: P,
125    ) -> Result<Self::Recv, Self::Error> {
126        self.project().writer.as_mut().start_send(part).map_err(Wr::Error::from)
127    }
128
129    fn poll_flush(
130        mut self: Pin<&mut Self>,
131        cx: &mut Context<'_>,
132    ) -> Poll<Result<(), Self::Error>> {
133        ready!(self.as_mut().poll_send_inner(cx))?;
134        self.project().inner.poll_flush(cx)
135    }
136
137    fn poll_complete(
138        mut self: Pin<&mut Self>,
139        cx: &mut Context<'_>,
140    ) -> Poll<Result<Self::Output, Self::Error>> {
141        ready!(self.as_mut().poll_send_inner(cx))?;
142        self.project().inner.poll_complete(cx)
143    }
144}
145
146impl<Wr, U, P, Part> Debug for Lift<Wr, U, P, Part>
147where
148    Wr: Debug,
149    U: Debug,
150    Part: Debug,
151{
152    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
153        f.debug_struct("Lift")
154            .field("inner", &self.inner)
155            .field("writer", &self.writer)
156            .field("buffered", &self.buffered)
157            .finish()
158    }
159}