Coverage Report

Created: 2025-12-28 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tower-0.5.2/src/hedge/select.rs
Line
Count
Source
1
use pin_project_lite::pin_project;
2
use std::{
3
    future::Future,
4
    pin::Pin,
5
    task::{Context, Poll},
6
};
7
use tower_service::Service;
8
9
/// A policy which decides which requests can be cloned and sent to the B
10
/// service.
11
pub trait Policy<Request> {
12
    fn clone_request(&self, req: &Request) -> Option<Request>;
13
}
14
15
/// Select is a middleware which attempts to clone the request and sends the
16
/// original request to the A service and, if the request was able to be cloned,
17
/// the cloned request to the B service.  Both resulting futures will be polled
18
/// and whichever future completes first will be used as the result.
19
#[derive(Debug)]
20
pub struct Select<P, A, B> {
21
    policy: P,
22
    a: A,
23
    b: B,
24
}
25
26
pin_project! {
27
    #[derive(Debug)]
28
    pub struct ResponseFuture<AF, BF> {
29
        #[pin]
30
        a_fut: AF,
31
        #[pin]
32
        b_fut: Option<BF>,
33
    }
34
}
35
36
impl<P, A, B> Select<P, A, B> {
37
0
    pub const fn new<Request>(policy: P, a: A, b: B) -> Self
38
0
    where
39
0
        P: Policy<Request>,
40
0
        A: Service<Request>,
41
0
        A::Error: Into<crate::BoxError>,
42
0
        B: Service<Request, Response = A::Response>,
43
0
        B::Error: Into<crate::BoxError>,
44
    {
45
0
        Select { policy, a, b }
46
0
    }
47
}
48
49
impl<P, A, B, Request> Service<Request> for Select<P, A, B>
50
where
51
    P: Policy<Request>,
52
    A: Service<Request>,
53
    A::Error: Into<crate::BoxError>,
54
    B: Service<Request, Response = A::Response>,
55
    B::Error: Into<crate::BoxError>,
56
{
57
    type Response = A::Response;
58
    type Error = crate::BoxError;
59
    type Future = ResponseFuture<A::Future, B::Future>;
60
61
0
    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
62
0
        match (self.a.poll_ready(cx), self.b.poll_ready(cx)) {
63
0
            (Poll::Ready(Ok(())), Poll::Ready(Ok(()))) => Poll::Ready(Ok(())),
64
0
            (Poll::Ready(Err(e)), _) => Poll::Ready(Err(e.into())),
65
0
            (_, Poll::Ready(Err(e))) => Poll::Ready(Err(e.into())),
66
0
            _ => Poll::Pending,
67
        }
68
0
    }
69
70
0
    fn call(&mut self, request: Request) -> Self::Future {
71
0
        let b_fut = if let Some(cloned_req) = self.policy.clone_request(&request) {
72
0
            Some(self.b.call(cloned_req))
73
        } else {
74
0
            None
75
        };
76
0
        ResponseFuture {
77
0
            a_fut: self.a.call(request),
78
0
            b_fut,
79
0
        }
80
0
    }
81
}
82
83
impl<AF, BF, T, AE, BE> Future for ResponseFuture<AF, BF>
84
where
85
    AF: Future<Output = Result<T, AE>>,
86
    AE: Into<crate::BoxError>,
87
    BF: Future<Output = Result<T, BE>>,
88
    BE: Into<crate::BoxError>,
89
{
90
    type Output = Result<T, crate::BoxError>;
91
92
0
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
93
0
        let this = self.project();
94
95
0
        if let Poll::Ready(r) = this.a_fut.poll(cx) {
96
0
            return Poll::Ready(Ok(r.map_err(Into::into)?));
97
0
        }
98
0
        if let Some(b_fut) = this.b_fut.as_pin_mut() {
99
0
            if let Poll::Ready(r) = b_fut.poll(cx) {
100
0
                return Poll::Ready(Ok(r.map_err(Into::into)?));
101
0
            }
102
0
        }
103
0
        Poll::Pending
104
0
    }
105
}