use std::pin::Pin;
struct Request {}
struct Response {}
trait Handler {
/// async 函数在 Rust 中会被编译为返回 Future 的函数。
/// 具体的 Future 类型由编译器生成,且每个 async 函数生成的 Future 类型可能不同。
/// 这意味着不同的 async 函数返回的 Future 大小和布局可能不同。
///
/// 为了使 trait 对象安全:方法的返回值大小必须是固定的。
async fn handle(&self, req: Request) -> Response;
}
trait AnyHandler {
/// 所以这里我们定义一个 Box 包裹的 Future,使返回值大小确定。
fn handle(&self, req: Request) -> Pin<Box<dyn Future<Output = Response> + '_>>;
}
/// 我们让 Handler 和 AnyHandler 等价,将 Handler 的 Future 装箱。
impl<H> AnyHandler for H
where
H: Handler,
{
fn handle(&self, req: Request) -> Pin<Box<dyn Future<Output = Response> + '_>> {
Box::pin(self.handle(req))
}
}
/// dyn AnyHandler 就是对象安全的了
struct BoxHandler(Box<dyn AnyHandler>);
impl BoxHandler {
pub fn new<T>(handle: T) -> Self
where
T: Handler + 'static,
{
Self(Box::new(handle))
}
}
/// 让 BoxHandler 实现 Handler trait
impl Handler for BoxHandler {
async fn handle(&self, req: Request) -> Response {
self.0.handle(req).await
}
}