boluo_core/service/
boxed.rs

1use std::sync::Arc;
2
3use futures_core::future::BoxFuture;
4
5use super::Service;
6
7/// 装箱的 [`Service`] 特征对象。
8///
9/// [`BoxService`] 将服务转换为特征对象并装箱,允许服务的 [`Future`] 是动态的。
10///
11/// 如果需要一个实现 [`Clone`] 的装箱服务,考虑使用 [`BoxCloneService`] 或 [`ArcService`]。
12pub struct BoxService<Req, Res, Err> {
13    service: Box<dyn AnyService<Req, Response = Res, Error = Err>>,
14}
15
16impl<Req, Res, Err> BoxService<Req, Res, Err> {
17    /// 将服务转换为[`Service`]特征对象并装箱。
18    pub fn new<S>(service: S) -> Self
19    where
20        S: Service<Req, Response = Res, Error = Err> + 'static,
21    {
22        Self {
23            service: Box::new(service),
24        }
25    }
26}
27
28impl<Req, Res, Err> Service<Req> for BoxService<Req, Res, Err> {
29    type Response = Res;
30    type Error = Err;
31
32    fn call(&self, req: Req) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send {
33        self.service.call(req)
34    }
35}
36
37impl<Req, Res, Err> std::fmt::Debug for BoxService<Req, Res, Err> {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        f.debug_struct("BoxService").finish()
40    }
41}
42
43/// 装箱的 [`Service`] 特征对象。
44///
45/// [`ArcService`] 将服务转换为特征对象并装箱,允许服务的 [`Future`] 是动态的,
46/// 并允许共享服务。
47///
48/// 这与 [`BoxService`] 类似,只是 [`ArcService`] 实现了 [`Clone`]。
49pub struct ArcService<Req, Res, Err> {
50    service: Arc<dyn AnyService<Req, Response = Res, Error = Err>>,
51}
52
53impl<Req, Res, Err> ArcService<Req, Res, Err> {
54    /// 将服务转换为[`Service`]特征对象并装箱。
55    pub fn new<S>(service: S) -> Self
56    where
57        S: Service<Req, Response = Res, Error = Err> + 'static,
58    {
59        Self {
60            service: Arc::new(service),
61        }
62    }
63}
64
65impl<Req, Res, Err> Service<Req> for ArcService<Req, Res, Err> {
66    type Response = Res;
67    type Error = Err;
68
69    fn call(&self, req: Req) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send {
70        self.service.call(req)
71    }
72}
73
74impl<Req, Res, Err> Clone for ArcService<Req, Res, Err> {
75    fn clone(&self) -> Self {
76        Self {
77            service: Arc::clone(&self.service),
78        }
79    }
80}
81
82impl<Req, Res, Err> std::fmt::Debug for ArcService<Req, Res, Err> {
83    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84        f.debug_struct("ArcService").finish()
85    }
86}
87
88/// 装箱的 [`Service`] 特征对象。
89///
90/// [`BoxCloneService`] 将服务转换为特征对象并装箱,允许服务的 [`Future`] 是动态的,
91/// 并允许克隆服务。
92///
93/// 这与 [`BoxService`] 类似,只是 [`BoxCloneService`] 实现了 [`Clone`]。
94pub struct BoxCloneService<Req, Res, Err> {
95    service: Box<dyn CloneService<Req, Response = Res, Error = Err>>,
96}
97
98impl<Req, Res, Err> BoxCloneService<Req, Res, Err> {
99    /// 将服务转换为[`Service`]特征对象并装箱。
100    pub fn new<S>(service: S) -> Self
101    where
102        S: Service<Req, Response = Res, Error = Err> + Clone + 'static,
103    {
104        Self {
105            service: Box::new(service),
106        }
107    }
108}
109
110impl<Req, Res, Err> Service<Req> for BoxCloneService<Req, Res, Err> {
111    type Response = Res;
112    type Error = Err;
113
114    fn call(&self, req: Req) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send {
115        self.service.call(req)
116    }
117}
118
119impl<Req, Res, Err> Clone for BoxCloneService<Req, Res, Err> {
120    fn clone(&self) -> Self {
121        Self {
122            service: self.service.clone_box(),
123        }
124    }
125}
126
127impl<Req, Res, Err> std::fmt::Debug for BoxCloneService<Req, Res, Err> {
128    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129        f.debug_struct("BoxCloneService").finish()
130    }
131}
132
133trait CloneService<Req>: AnyService<Req> {
134    fn clone_box(
135        &self,
136    ) -> Box<dyn CloneService<Req, Response = Self::Response, Error = Self::Error>>;
137}
138
139impl<S, Req> CloneService<Req> for S
140where
141    S: Service<Req> + Clone + 'static,
142{
143    fn clone_box(
144        &self,
145    ) -> Box<dyn CloneService<Req, Response = Self::Response, Error = Self::Error>> {
146        Box::new(self.clone())
147    }
148}
149
150trait AnyService<Req>: Send + Sync {
151    type Response;
152    type Error;
153
154    fn call<'a>(&'a self, req: Req) -> BoxFuture<'a, Result<Self::Response, Self::Error>>
155    where
156        Req: 'a;
157}
158
159impl<S, Req> AnyService<Req> for S
160where
161    S: Service<Req> + ?Sized,
162{
163    type Response = S::Response;
164    type Error = S::Error;
165
166    fn call<'a>(&'a self, req: Req) -> BoxFuture<'a, Result<Self::Response, Self::Error>>
167    where
168        Req: 'a,
169    {
170        Box::pin(Service::call(self, req))
171    }
172}