requiem_service/
transform_err.rs

1use std::future::Future;
2use std::marker::PhantomData;
3use std::pin::Pin;
4use std::task::{Context, Poll};
5
6use super::Transform;
7
8/// Transform for the `map_init_err` combinator, changing the type of a new
9/// transform's init error.
10///
11/// This is created by the `Transform::map_init_err` method.
12pub struct TransformMapInitErr<T, S, F, E> {
13    t: T,
14    f: F,
15    e: PhantomData<(S, E)>,
16}
17
18impl<T, S, F, E> TransformMapInitErr<T, S, F, E> {
19    pub(crate) fn new(t: T, f: F) -> Self
20    where
21        T: Transform<S>,
22        F: Fn(T::InitError) -> E,
23    {
24        Self {
25            t,
26            f,
27            e: PhantomData,
28        }
29    }
30}
31
32impl<T, S, F, E> Clone for TransformMapInitErr<T, S, F, E>
33where
34    T: Clone,
35    F: Clone,
36{
37    fn clone(&self) -> Self {
38        Self {
39            t: self.t.clone(),
40            f: self.f.clone(),
41            e: PhantomData,
42        }
43    }
44}
45
46impl<T, S, F, E> Transform<S> for TransformMapInitErr<T, S, F, E>
47where
48    T: Transform<S>,
49    F: Fn(T::InitError) -> E + Clone,
50{
51    type Request = T::Request;
52    type Response = T::Response;
53    type Error = T::Error;
54    type Transform = T::Transform;
55
56    type InitError = E;
57    type Future = TransformMapInitErrFuture<T, S, F, E>;
58
59    fn new_transform(&self, service: S) -> Self::Future {
60        TransformMapInitErrFuture {
61            fut: self.t.new_transform(service),
62            f: self.f.clone(),
63        }
64    }
65}
66
67#[pin_project::pin_project]
68pub struct TransformMapInitErrFuture<T, S, F, E>
69where
70    T: Transform<S>,
71    F: Fn(T::InitError) -> E,
72{
73    #[pin]
74    fut: T::Future,
75    f: F,
76}
77
78impl<T, S, F, E> Future for TransformMapInitErrFuture<T, S, F, E>
79where
80    T: Transform<S>,
81    F: Fn(T::InitError) -> E + Clone,
82{
83    type Output = Result<T::Transform, E>;
84
85    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
86        let this = self.project();
87        if let Poll::Ready(res) = this.fut.poll(cx) {
88            Poll::Ready(res.map_err(this.f))
89        } else {
90            Poll::Pending
91        }
92    }
93}