hyper_util/service/
oneshot.rs1use pin_project_lite::pin_project;
2use std::pin::Pin;
3use std::task::{Context, Poll, ready};
4use tower_service::Service;
5
6pin_project! {
10 #[project = OneshotProj]
11 #[derive(Debug)]
12 pub enum Oneshot<S: Service<Req>, Req> {
13 NotReady {
14 svc: S,
15 req: Option<Req>,
16 },
17 Called {
18 #[pin]
19 fut: S::Future,
20 },
21 Done,
22 }
23}
24
25impl<S, Req> Oneshot<S, Req>
26where
27 S: Service<Req>,
28{
29 pub(crate) const fn new(svc: S, req: Req) -> Self {
30 Oneshot::NotReady {
31 svc,
32 req: Some(req),
33 }
34 }
35}
36
37impl<S, Req> Future for Oneshot<S, Req>
38where
39 S: Service<Req>,
40{
41 type Output = Result<S::Response, S::Error>;
42
43 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
44 loop {
45 let this = self.as_mut().project();
46 match this {
47 OneshotProj::NotReady { svc, req } => {
48 ready!(svc.poll_ready(cx))?;
49 let fut = svc.call(req.take().expect("already called"));
50 self.set(Oneshot::Called { fut });
51 }
52 OneshotProj::Called { fut } => {
53 let res = ready!(fut.poll(cx))?;
54 self.set(Oneshot::Done);
55 return Poll::Ready(Ok(res));
56 }
57 OneshotProj::Done => panic!("polled after complete"),
58 }
59 }
60 }
61}