use std::future::Future; use std::marker::PhantomData; use std::pin::Pin; use std::task::{Context, Poll}; use super::Transform; /// Transform for the `map_init_err` combinator, changing the type of a new /// transform's init error. /// /// This is created by the `Transform::map_init_err` method. pub struct TransformMapInitErr { t: T, f: F, e: PhantomData<(S, E)>, } impl TransformMapInitErr { pub(crate) fn new(t: T, f: F) -> Self where T: Transform, F: Fn(T::InitError) -> E, { Self { t, f, e: PhantomData, } } } impl Clone for TransformMapInitErr where T: Clone, F: Clone, { fn clone(&self) -> Self { Self { t: self.t.clone(), f: self.f.clone(), e: PhantomData, } } } impl Transform for TransformMapInitErr where T: Transform, F: Fn(T::InitError) -> E + Clone, { type Request = T::Request; type Response = T::Response; type Error = T::Error; type Transform = T::Transform; type InitError = E; type Future = TransformMapInitErrFuture; fn new_transform(&self, service: S) -> Self::Future { TransformMapInitErrFuture { fut: self.t.new_transform(service), f: self.f.clone(), } } } #[pin_project::pin_project] pub struct TransformMapInitErrFuture where T: Transform, F: Fn(T::InitError) -> E, { #[pin] fut: T::Future, f: F, } impl Future for TransformMapInitErrFuture where T: Transform, F: Fn(T::InitError) -> E + Clone, { type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); if let Poll::Ready(res) = this.fut.poll(cx) { Poll::Ready(res.map_err(this.f)) } else { Poll::Pending } } }