Skip to main content

wae_effect/
lib.rs

1//! 代数效应系统
2//!
3//! 提供声明式的依赖注入能力,允许在处理请求时通过类型安全的接口获取各种依赖。
4
5#![warn(missing_docs)]
6
7use std::{collections::HashMap, sync::Arc};
8
9use http::{Response, StatusCode, request::Parts};
10use wae_types::{WaeError, WaeResult};
11
12/// 依赖容器
13///
14/// 存储所有注册的服务实例。
15#[derive(Default)]
16pub struct Dependencies {
17    services: HashMap<String, Box<dyn std::any::Any + Send + Sync>>,
18}
19
20impl Dependencies {
21    /// 创建新的依赖容器
22    pub fn new() -> Self {
23        Self { services: HashMap::new() }
24    }
25
26    /// 注册服务
27    pub fn register<T: Send + Sync + 'static>(&mut self, name: &str, service: T) {
28        self.services.insert(name.to_string(), Box::new(service));
29    }
30
31    /// 获取服务
32    pub fn get<T: Clone + Send + Sync + 'static>(&self, name: &str) -> WaeResult<T> {
33        self.services
34            .get(name)
35            .and_then(|s| s.downcast_ref::<T>())
36            .cloned()
37            .ok_or_else(|| WaeError::not_found("Dependency", name))
38    }
39}
40
41/// 代数效应请求上下文
42///
43/// 包含依赖容器和请求信息,用于在请求处理过程中获取依赖。
44pub struct Effectful {
45    deps: Arc<Dependencies>,
46    parts: Parts,
47}
48
49impl Effectful {
50    /// 创建新的 Effectful
51    pub fn new(deps: Arc<Dependencies>, parts: Parts) -> Self {
52        Self { deps, parts }
53    }
54
55    /// 获取依赖
56    pub fn get<T: Clone + Send + Sync + 'static>(&self, name: &str) -> WaeResult<T> {
57        self.deps.get(name)
58    }
59
60    /// 获取请求头
61    pub fn header(&self, name: &str) -> Option<&str> {
62        self.parts.headers.get(name).and_then(|v| v.to_str().ok())
63    }
64}
65
66/// 代数效应构建器
67///
68/// 用于构建依赖容器并注册各种依赖。
69pub struct AlgebraicEffect {
70    deps: Dependencies,
71}
72
73impl Default for AlgebraicEffect {
74    fn default() -> Self {
75        Self::new()
76    }
77}
78
79impl AlgebraicEffect {
80    /// 创建新的代数效应构建器
81    pub fn new() -> Self {
82        Self { deps: Dependencies::new() }
83    }
84
85    /// 注册服务
86    pub fn with<T: Send + Sync + 'static>(mut self, name: &str, service: T) -> Self {
87        self.deps.register(name, service);
88        self
89    }
90
91    /// 构建依赖容器
92    pub fn build(self) -> Arc<Dependencies> {
93        Arc::new(self.deps)
94    }
95}
96
97/// WaeError 的包装类型,用于解决 orphan rule 问题
98pub struct WaeErrorResponse(pub WaeError);
99
100impl WaeErrorResponse {
101    /// 将 WaeError 转换为 http::Response
102    pub fn into_response<B>(self) -> Response<B>
103    where
104        B: From<String>,
105    {
106        let status = self.0.http_status();
107        let body = B::from(self.0.to_string());
108        let status_code = StatusCode::from_u16(status).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
109        Response::builder().status(status_code).body(body).unwrap()
110    }
111}