requiem_service/
transform.rs1use std::future::Future;
2use std::pin::Pin;
3use std::rc::Rc;
4use std::sync::Arc;
5use std::task::{Context, Poll};
6
7use crate::transform_err::TransformMapInitErr;
8use crate::{IntoServiceFactory, Service, ServiceFactory};
9
10pub fn apply<T, S, U>(t: T, factory: U) -> ApplyTransform<T, S>
12where
13 S: ServiceFactory,
14 T: Transform<S::Service, InitError = S::InitError>,
15 U: IntoServiceFactory<S>,
16{
17 ApplyTransform::new(t, factory.into_factory())
18}
19
20pub trait Transform<S> {
93 type Request;
95
96 type Response;
98
99 type Error;
101
102 type Transform: Service<
104 Request = Self::Request,
105 Response = Self::Response,
106 Error = Self::Error,
107 >;
108
109 type InitError;
111
112 type Future: Future<Output = Result<Self::Transform, Self::InitError>>;
114
115 fn new_transform(&self, service: S) -> Self::Future;
117
118 fn map_init_err<F, E>(self, f: F) -> TransformMapInitErr<Self, S, F, E>
121 where
122 Self: Sized,
123 F: Fn(Self::InitError) -> E + Clone,
124 {
125 TransformMapInitErr::new(self, f)
126 }
127}
128
129impl<T, S> Transform<S> for Rc<T>
130where
131 T: Transform<S>,
132{
133 type Request = T::Request;
134 type Response = T::Response;
135 type Error = T::Error;
136 type InitError = T::InitError;
137 type Transform = T::Transform;
138 type Future = T::Future;
139
140 fn new_transform(&self, service: S) -> T::Future {
141 self.as_ref().new_transform(service)
142 }
143}
144
145impl<T, S> Transform<S> for Arc<T>
146where
147 T: Transform<S>,
148{
149 type Request = T::Request;
150 type Response = T::Response;
151 type Error = T::Error;
152 type InitError = T::InitError;
153 type Transform = T::Transform;
154 type Future = T::Future;
155
156 fn new_transform(&self, service: S) -> T::Future {
157 self.as_ref().new_transform(service)
158 }
159}
160
161pub struct ApplyTransform<T, S>(Rc<(T, S)>);
163
164impl<T, S> ApplyTransform<T, S>
165where
166 S: ServiceFactory,
167 T: Transform<S::Service, InitError = S::InitError>,
168{
169 fn new(t: T, service: S) -> Self {
171 Self(Rc::new((t, service)))
172 }
173}
174
175impl<T, S> Clone for ApplyTransform<T, S> {
176 fn clone(&self) -> Self {
177 ApplyTransform(self.0.clone())
178 }
179}
180
181impl<T, S> ServiceFactory for ApplyTransform<T, S>
182where
183 S: ServiceFactory,
184 T: Transform<S::Service, InitError = S::InitError>,
185{
186 type Request = T::Request;
187 type Response = T::Response;
188 type Error = T::Error;
189
190 type Config = S::Config;
191 type Service = T::Transform;
192 type InitError = T::InitError;
193 type Future = ApplyTransformFuture<T, S>;
194
195 fn new_service(&self, cfg: S::Config) -> Self::Future {
196 ApplyTransformFuture {
197 store: self.0.clone(),
198 state: ApplyTransformFutureState::A(self.0.as_ref().1.new_service(cfg)),
199 }
200 }
201}
202
203#[pin_project::pin_project]
204pub struct ApplyTransformFuture<T, S>
205where
206 S: ServiceFactory,
207 T: Transform<S::Service, InitError = S::InitError>,
208{
209 store: Rc<(T, S)>,
210 #[pin]
211 state: ApplyTransformFutureState<T, S>,
212}
213
214#[pin_project::pin_project]
215pub enum ApplyTransformFutureState<T, S>
216where
217 S: ServiceFactory,
218 T: Transform<S::Service, InitError = S::InitError>,
219{
220 A(#[pin] S::Future),
221 B(#[pin] T::Future),
222}
223
224impl<T, S> Future for ApplyTransformFuture<T, S>
225where
226 S: ServiceFactory,
227 T: Transform<S::Service, InitError = S::InitError>,
228{
229 type Output = Result<T::Transform, T::InitError>;
230
231 #[pin_project::project]
232 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
233 let mut this = self.as_mut().project();
234
235 #[project]
236 match this.state.as_mut().project() {
237 ApplyTransformFutureState::A(fut) => match fut.poll(cx)? {
238 Poll::Ready(srv) => {
239 let fut = this.store.0.new_transform(srv);
240 this.state.set(ApplyTransformFutureState::B(fut));
241 self.poll(cx)
242 }
243 Poll::Pending => Poll::Pending,
244 },
245 ApplyTransformFutureState::B(fut) => fut.poll(cx),
246 }
247 }
248}