/rust/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-util-0.1.20/src/service/oneshot.rs
Line | Count | Source |
1 | | use pin_project_lite::pin_project; |
2 | | use std::future::Future; |
3 | | use std::pin::Pin; |
4 | | use std::task::{ready, Context, Poll}; |
5 | | use tower_service::Service; |
6 | | |
7 | | // Vendored from tower::util to reduce dependencies, the code is small enough. |
8 | | |
9 | | // Not really pub, but used in a trait for bounds |
10 | | pin_project! { |
11 | | #[project = OneshotProj] |
12 | | #[derive(Debug)] |
13 | | pub enum Oneshot<S: Service<Req>, Req> { |
14 | | NotReady { |
15 | | svc: S, |
16 | | req: Option<Req>, |
17 | | }, |
18 | | Called { |
19 | | #[pin] |
20 | | fut: S::Future, |
21 | | }, |
22 | | Done, |
23 | | } |
24 | | } |
25 | | |
26 | | impl<S, Req> Oneshot<S, Req> |
27 | | where |
28 | | S: Service<Req>, |
29 | | { |
30 | 0 | pub(crate) const fn new(svc: S, req: Req) -> Self { |
31 | 0 | Oneshot::NotReady { |
32 | 0 | svc, |
33 | 0 | req: Some(req), |
34 | 0 | } |
35 | 0 | } |
36 | | } |
37 | | |
38 | | impl<S, Req> Future for Oneshot<S, Req> |
39 | | where |
40 | | S: Service<Req>, |
41 | | { |
42 | | type Output = Result<S::Response, S::Error>; |
43 | | |
44 | 0 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
45 | | loop { |
46 | 0 | let this = self.as_mut().project(); |
47 | 0 | match this { |
48 | 0 | OneshotProj::NotReady { svc, req } => { |
49 | 0 | ready!(svc.poll_ready(cx))?; |
50 | 0 | let fut = svc.call(req.take().expect("already called")); |
51 | 0 | self.set(Oneshot::Called { fut }); |
52 | | } |
53 | 0 | OneshotProj::Called { fut } => { |
54 | 0 | let res = ready!(fut.poll(cx))?; |
55 | 0 | self.set(Oneshot::Done); |
56 | 0 | return Poll::Ready(Ok(res)); |
57 | | } |
58 | 0 | OneshotProj::Done => panic!("polled after complete"), |
59 | | } |
60 | | } |
61 | 0 | } |
62 | | } |