multipart_write/write/
lift.rs1use 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 #[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 pub fn into_inner(self) -> Wr {
30 self.inner
31 }
32
33 pub fn get_ref(&self) -> &Wr {
35 &self.inner
36 }
37
38 pub fn get_mut(&mut self) -> &mut Wr {
42 &mut self.inner
43 }
44
45 pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut Wr> {
49 self.project().inner
50 }
51
52 pub fn get_outer_ref(&self) -> &U {
54 &self.writer
55 }
56
57 pub fn get_outer_mut(&mut self) -> &mut U {
61 &mut self.writer
62 }
63
64 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}