1#![warn(missing_docs)]
6
7use std::{collections::HashMap, sync::Arc};
8
9use http::{Response, StatusCode, request::Parts};
10use wae_types::{WaeError, WaeResult};
11
12#[derive(Default)]
16pub struct Dependencies {
17 services: HashMap<String, Box<dyn std::any::Any + Send + Sync>>,
18}
19
20impl Dependencies {
21 pub fn new() -> Self {
23 Self { services: HashMap::new() }
24 }
25
26 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 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
41pub struct Effectful {
45 deps: Arc<Dependencies>,
46 parts: Parts,
47}
48
49impl Effectful {
50 pub fn new(deps: Arc<Dependencies>, parts: Parts) -> Self {
52 Self { deps, parts }
53 }
54
55 pub fn get<T: Clone + Send + Sync + 'static>(&self, name: &str) -> WaeResult<T> {
57 self.deps.get(name)
58 }
59
60 pub fn header(&self, name: &str) -> Option<&str> {
62 self.parts.headers.get(name).and_then(|v| v.to_str().ok())
63 }
64}
65
66pub struct AlgebraicEffect {
70 deps: Dependencies,
71}
72
73impl Default for AlgebraicEffect {
74 fn default() -> Self {
75 Self::new()
76 }
77}
78
79impl AlgebraicEffect {
80 pub fn new() -> Self {
82 Self { deps: Dependencies::new() }
83 }
84
85 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 pub fn build(self) -> Arc<Dependencies> {
93 Arc::new(self.deps)
94 }
95}
96
97pub struct WaeErrorResponse(pub WaeError);
99
100impl WaeErrorResponse {
101 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}