apache_dubbo/utils/
boxed_clone.rs1use futures_util::future::BoxFuture;
19use std::{
20 fmt,
21 task::{Context, Poll},
22};
23use tower::ServiceExt;
24use tower_layer::{layer_fn, LayerFn};
25use tower_service::Service;
26
27pub struct BoxCloneService<T, U, E>(
28 Box<
29 dyn CloneService<T, Response = U, Error = E, Future = BoxFuture<'static, Result<U, E>>>
30 + Send
31 + Sync,
32 >,
33);
34
35impl<T, U, E> BoxCloneService<T, U, E> {
36 pub fn new<S>(inner: S) -> Self
38 where
39 S: Service<T, Response = U, Error = E> + Clone + Send + Sync + 'static,
40 S::Future: Send + 'static,
41 {
42 let inner = inner.map_future(|f| Box::pin(f) as _);
43 BoxCloneService(Box::new(inner))
44 }
45
46 pub fn layer<S>() -> LayerFn<fn(S) -> Self>
51 where
52 S: Service<T, Response = U, Error = E> + Clone + Send + Sync + 'static,
53 S::Future: Send + 'static,
54 {
55 layer_fn(Self::new)
56 }
57}
58
59impl<T, U, E> Service<T> for BoxCloneService<T, U, E> {
60 type Response = U;
61 type Error = E;
62 type Future = BoxFuture<'static, Result<U, E>>;
63
64 #[inline]
65 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> {
66 self.0.poll_ready(cx)
67 }
68
69 #[inline]
70 fn call(&mut self, request: T) -> Self::Future {
71 self.0.call(request)
72 }
73}
74
75impl<T, U, E> Clone for BoxCloneService<T, U, E> {
76 fn clone(&self) -> Self {
77 Self(self.0.clone_box())
78 }
79}
80
81trait CloneService<R>: Service<R> {
82 fn clone_box(
83 &self,
84 ) -> Box<
85 dyn CloneService<R, Response = Self::Response, Error = Self::Error, Future = Self::Future>
86 + Send
87 + Sync,
88 >;
89}
90
91impl<R, T> CloneService<R> for T
92where
93 T: Service<R> + Send + Sync + Clone + 'static,
94{
95 fn clone_box(
96 &self,
97 ) -> Box<
98 dyn CloneService<R, Response = T::Response, Error = T::Error, Future = T::Future>
99 + Send
100 + Sync,
101 > {
102 Box::new(self.clone())
103 }
104}
105
106impl<T, U, E> fmt::Debug for BoxCloneService<T, U, E> {
107 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
108 fmt.debug_struct("BoxCloneService").finish()
109 }
110}