use core::{ future::Future, marker::PhantomData, pin::Pin, task::{Context, Poll}, }; use pin_project_lite::pin_project; 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 { transform: T, mapper: F, _phantom: PhantomData<(S, Req, E)>, } impl TransformMapInitErr { pub(crate) fn new(t: T, f: F) -> Self where T: Transform, F: Fn(T::InitError) -> E, { Self { transform: t, mapper: f, _phantom: PhantomData, } } } impl Clone for TransformMapInitErr where T: Clone, F: Clone, { fn clone(&self) -> Self { Self { transform: self.transform.clone(), mapper: self.mapper.clone(), _phantom: PhantomData, } } } impl Transform for TransformMapInitErr where T: Transform, F: Fn(T::InitError) -> E + Clone, { 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.transform.new_transform(service), f: self.mapper.clone(), } } } 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 } } }