在 Rust 中,如何将一个对象不安全的 Trait 装箱

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
    }
}