burger/
leak.rs

1//! The [`ServiceExt::leak`](crate::ServiceExt::leak) combinator returns [`Leak`], which extends
2//! the lifetime of the [`Service::Permit`].
3//!
4//! This can be only called on [services](Service) within an [`Arc`].
5//!
6//! # Example
7//!
8//! ```rust
9//! use burger::*;
10//! # use std::sync::Arc;
11//!
12//! # #[tokio::main]
13//! # async fn main() {
14//! let svc = Arc::new(service_fn(|x| async move { x + 4 })).leak();
15//! let response = svc.oneshot(3u32).await;
16//! assert_eq!(7, response);
17//! # }
18//! ```
19//!
20//! # Load
21//!
22//! The [`Load::load`] on [`Leak`] defers to the inner service.
23
24use std::{fmt, sync::Arc};
25
26use crate::{load::Load, Middleware, Service};
27
28/// A wrapper [`Service`] for the [`ServiceExt::leak`](crate::ServiceExt::leak) combinator.
29///
30/// See the [module](crate::leak) for more information.
31#[derive(Debug)]
32pub struct Leak<'t, S> {
33    _ref: &'t (),
34    inner: Arc<S>,
35}
36
37impl<'t, S> Leak<'t, S> {
38    pub(crate) fn new(inner: Arc<S>) -> Leak<'t, S> {
39        Leak { _ref: &(), inner }
40    }
41}
42
43/// The [`Service::Permit`] type for [`Leak`].
44pub struct LeakPermit<'t, S, Request>
45where
46    S: Service<Request> + 't,
47{
48    _svc: Arc<S>,
49    inner: S::Permit<'t>,
50}
51
52impl<'t, S, Request> fmt::Debug for LeakPermit<'t, S, Request>
53where
54    S: Service<Request> + fmt::Debug,
55    for<'a> S::Permit<'a>: fmt::Debug,
56{
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        f.debug_struct("LeakPermit")
59            .field("_svc", &self._svc)
60            .field("inner", &self.inner)
61            .finish()
62    }
63}
64
65impl<'t, Request, S> Service<Request> for Leak<'t, S>
66where
67    S: Service<Request> + 't,
68{
69    type Response = S::Response;
70    type Permit<'a> = LeakPermit<'t, S, Request>
71    where
72        S: 'a, 't: 'a;
73
74    async fn acquire(&self) -> Self::Permit<'_> {
75        LeakPermit {
76            _svc: self.inner.clone(),
77            inner: unsafe {
78                std::mem::transmute::<S::Permit<'_>, S::Permit<'t>>(self.inner.acquire().await)
79            },
80        }
81    }
82
83    async fn call<'a>(permit: Self::Permit<'a>, request: Request) -> Self::Response
84    where
85        Self: 'a,
86    {
87        S::call(permit.inner, request).await
88    }
89}
90
91impl<'t, S> Load for Leak<'t, S>
92where
93    S: Load,
94{
95    type Metric = S::Metric;
96
97    fn load(&self) -> Self::Metric {
98        self.inner.load()
99    }
100}
101
102impl<'t, S, T> Middleware<S> for Leak<'t, T>
103where
104    T: Middleware<S>,
105{
106    type Service = Leak<'t, T::Service>;
107
108    fn apply(self, svc: S) -> Self::Service {
109        let Self { inner, _ref } = self;
110        let inner = Arc::into_inner(inner).expect("there cannot be inflight requests");
111        Leak {
112            inner: Arc::new(inner.apply(svc)),
113            _ref,
114        }
115    }
116}