1use std::fmt::Debug;
2use dce_util::mixed::{DceErr, DceResult};
3use crate::request::{Context, Response};
4use crate::serializer::{Deserializer, Serializable, Serialized, Serializer};
5use log::{error, warn};
6use std::any::Any;
7use std::collections::HashMap;
8use std::ops::{Deref, DerefMut};
9use std::sync::Arc;
10use crate::api::{ApiTrait, Method};
11use crate::router::{CODE_NOT_FOUND, Router};
12#[cfg(feature = "async")]
13use async_trait::async_trait;
14
15
16pub const HEAD_PATH_NAME: &'static str = "$#path#";
17pub const HEAD_ID_NAME: &'static str = "$#id#";
18#[cfg(feature = "session")]
19pub const HEAD_SID_NAME: &'static str = "Session-Id";
20
21
22#[derive(Debug)]
23pub struct Meta<Req, Resp> {
24 req: Option<Req>,
25 resp: Option<Response<Resp>>,
26 heads: HashMap<String, String>,
27 resp_heads: HashMap<String, String>,
28}
29
30impl<Req, Resp> Meta<Req, Resp> {
31 pub fn new(req: Req, heads: HashMap<String, String>) -> Self {
32 Self { req: Some(req), resp: None, heads, resp_heads: Default::default() }
33 }
34
35 pub fn req(&self) -> DceResult<&Req> {
36 self.req.as_ref().ok_or_else(|| DceErr::closed0("Invalid empty request"))
37 }
38
39 pub fn req_mut(&mut self) -> &mut Option<Req> {
40 &mut self.req
41 }
42
43 pub fn resp_mut(&mut self) -> &mut Option<Response<Resp>> {
44 &mut self.resp
45 }
46
47 pub fn heads(&self) -> &HashMap<String, String> {
48 &self.heads
49 }
50
51 pub fn resp_heads(&self) -> &HashMap<String, String> {
52 &self.resp_heads
53 }
54
55 pub fn resp_heads_mut(&mut self) -> &mut HashMap<String, String> {
56 &mut self.resp_heads
57 }
58}
59
60
61#[cfg_attr(feature = "async", async_trait)]
62pub trait RoutableProtocol: From<Self::Req> + Into<Self::Resp> + Deref<Target = Meta<Self::Req, Self::Resp>> + DerefMut + Debug {
63 type Req;
64 type Resp: Debug;
65
66 #[cfg(feature = "async")]
67 async fn body(&mut self) -> DceResult<Serialized>;
68 #[cfg(not(feature = "async"))]
69 fn body(&mut self) -> DceResult<Serialized>;
70 fn pack_resp(&self, serialized: Serialized) -> Self::Resp;
71
72 fn path(&self) -> &str {
73 self.heads.get(HEAD_PATH_NAME).map_or("", |v| v.as_str())
74 }
75
76 fn id(&self) -> Option<&str> {
77 self.heads.get(HEAD_ID_NAME).map(|v| v.as_str())
78 }
79
80 #[cfg(feature = "async")]
81 async fn handle(self, router: Arc<Router<Self>>, context_data: HashMap<String, Box<dyn Any + Send>>) -> Option<Self::Resp> {
82 let mut context = Context::new(router, self, context_data);
83 let result = Router::route(&mut context).await;
84 context.take_rp()?.handle_result(result, &mut context)
85 }
86
87 #[cfg(not(feature = "async"))]
88 fn handle(self, router: Arc<Router<Self>>, context_data: HashMap<String, Box<dyn Any + Send>>) -> Option<Self::Resp> {
89 let mut context = Context::new(router, self, context_data);
90 let result = Router::route(&mut context);
91 context.take_rp()?.handle_result(result, &mut context)
92 }
93
94 fn api_match(&self, apis: &[&'static (dyn ApiTrait<Self> + Send + Sync)]) -> DceResult<&'static (dyn ApiTrait<Self> + Send + Sync)> {
95 apis.iter().find(|n| n.method_match(self)).map(|a| *a)
96 .ok_or_else(|| DceErr::openly(CODE_NOT_FOUND, format!(r#"Path "{}" cannot match any Api by Method"#, self.path())))
97 }
98
99 fn deserializer<'a, ReqDto>(deserializers: &'a [Box<dyn Deserializer<ReqDto> + Send + Sync>], _context: &Context<Self>) -> DceResult<&'a Box<dyn Deserializer<ReqDto> + Send + Sync>> {
100 deserializers.first().ok_or_else(|| DceErr::closed0("No deserializer configured"))
101 }
102
103 fn serializer<'a, RespDto>(serializers: &'a [Box<dyn Serializer<RespDto> + Send + Sync>], _context: &Context<Self>) -> DceResult<&'a Box<dyn Serializer<RespDto> + Send + Sync>> {
104 serializers.last().ok_or_else(|| DceErr::closed0("No serializer configured"))
105 }
106
107 fn deserialize<ReqDto>(serializers: &[Box<dyn Deserializer<ReqDto> + Send + Sync>], seq: Serialized, context: &Context<Self>) -> DceResult<ReqDto> {
108 Self::deserializer(serializers, context)?.deserialize(seq)
109 }
110
111 fn serialize<RespDto>(serializers: &[Box<dyn Serializer<RespDto> + Send + Sync>], dto: Serializable<RespDto>, context: &Context<Self>) -> DceResult<Serialized> {
112 Self::serializer(serializers, context)?.serialize(dto)
113 }
114
115 fn pack_responsible<RespDto: 'static>(
116 context: &Context<Self>,
117 serializers: &[Box<dyn Serializer<RespDto> + Send + Sync>],
118 responsible: Serializable<RespDto>,
119 ) -> DceResult<Option<Response<Self::Resp>>> {
120 Self::serialize(serializers, responsible, &context).map(|sd| Some(Response::Serialized(sd)))
121 }
122
123 fn parse_api_method_and_extras(prop_tuples: Vec<(&'static str, Box<dyn Any + Send + Sync>)>) -> (Option<Box<dyn Method<Self> + Send + Sync>>, HashMap<&'static str, Box<dyn Any + Send + Sync>>) {
126 let mut prop_mapping: HashMap<_, _> = prop_tuples.into_iter().collect();
127 (Self::parse_api_method(&mut prop_mapping), prop_mapping)
128 }
129
130 fn parse_api_method(_prop_mapping: &mut HashMap<&'static str, Box<dyn Any + Send + Sync>>) -> Option<Box<dyn Method<Self> + Send + Sync>> {
132 None
133 }
134
135 fn try_print_err(response: &DceResult<()>) {
136 if let Err(error) = response {
137 match error {
138 DceErr::Openly(err) => warn!("code {}, {}", err.code, err.message),
139 DceErr::Closed(err) => error!("code {}, {}", err.code, err.message),
140 };
141 }
142 }
143
144 fn err_into(mut self, err: DceErr) -> Self::Resp {
145 self.resp = Some(Response::Raw(self.pack_resp(Serialized::String(err.to_responsible()))));
146 self.into()
147 }
148
149 fn handle_result(self, result: DceResult<()>, context: &mut Context<Self>) -> Option<Self::Resp> {
150 Self::try_print_err(&result);
151 if ! context.api().map_or_else(|| self.id().is_none(), |a| a.unresponsive()) {
152 return Some(match result {
153 Ok(_) => self.into(),
154 Err(err) => self.err_into(err),
155 });
156 }
157 None
158 }
159
160 #[cfg(feature = "session")]
161 fn sid(&self) -> Option<&str> {
162 self.heads.get(HEAD_SID_NAME).map(String::as_str)
163 }
164
165 #[cfg(feature = "session")]
166 fn set_resp_sid(&mut self, sid: String) {
167 self.resp_heads.insert(HEAD_SID_NAME.to_string(), sid);
168 }
169
170 #[cfg(feature = "session")]
171 fn get_resp_sid(&mut self) -> Option<&String> {
172 self.resp_heads.get(HEAD_SID_NAME)
173 }
174
175 #[cfg(feature = "session")]
176 fn set_session<Rp: RoutableProtocol + Debug + 'static>(context: &mut Context<Rp>, value: Box<dyn Any + Send>) {
177 context.put_data("$#session#".to_string(), value);
178 }
179
180 #[cfg(feature = "session")]
181 fn session<S: 'static, Rp: RoutableProtocol + Debug + 'static>(context: &mut Context<Rp>) -> DceResult<&mut S> {
182 context.get_as_mut("$#session#")
183 }
184}