1use std::any::{Any, type_name};
2use std::collections::HashMap;
3use std::fmt::Debug;
4use std::ops::{Deref, DerefMut};
5use std::sync::Arc;
6use crate::api::{Api, ApiTrait};
7use crate::serializer::{Deserializer, Serializable, Serialized};
8use crate::router::Router;
9use crate::protocol::RoutableProtocol;
10use dce_util::mixed::{DceErr, DceResult};
11use serde::Serialize;
12
13
14#[derive(Debug)]
15pub struct Context<Rp: RoutableProtocol + 'static> {
16 router: Arc<Router<Rp>>,
17 api: Option<&'static (dyn ApiTrait<Rp> + Send + Sync)>,
18 rp: Option<Rp>,
19 path_params: HashMap<&'static str, PathParam>,
20 suffix: Option<&'static str>,
21 data: HashMap<String, Box<dyn Any + Send>>,
22}
23
24impl<Rp: RoutableProtocol + Debug + 'static> Context<Rp> {
25 pub fn new(router: Arc<Router<Rp>>, rp: Rp, data: HashMap<String, Box<dyn Any + Send>>) -> Context<Rp> {
26 Context { router, api: None, rp: Some(rp), path_params: Default::default(), suffix: None, data, }
27 }
28
29 pub fn router(&self) -> &Arc<Router<Rp>> {
30 &self.router
31 }
32
33 pub fn api(&self) -> Option<&'static (dyn ApiTrait<Rp> + Send + Sync)> {
34 self.api
35 }
36
37 pub fn rp(&self) -> &Rp {
38 self.rp.as_ref().expect("Routable protocol data has been taken, should not borrow it anymore")
39 }
40
41 pub fn rp_mut(&mut self) -> &mut Rp {
42 self.rp.as_mut().expect("Routable protocol data has been taken, should not borrow mut anymore")
43 }
44
45 pub fn take_rp(&mut self) -> Option<Rp> {
46 self.rp.take()
47 }
48
49 pub fn params(&self) -> &HashMap<&'static str, PathParam> {
50 &self.path_params
51 }
52
53 pub fn param(&self, key: &str) -> DceResult<&PathParam> {
54 self.path_params.get(key).ok_or(DceErr::openly0(format!("no param passed with name '{}'", key)))
55 }
56
57 pub fn suffix(&mut self) -> &'static str {
58 match self.suffix {
59 Some(suffix) => suffix,
60 None => {
61 self.suffix = self.api.iter().find_map(|a| a.suffixes().iter().map(|suffix| &**suffix)
62 .find(|s| self.rp().path().ends_with(format!("{}{}", self.router.suffix_boundary(), s).as_str()))).or_else(|| Some(""));
63 self.suffix()
64 },
65 }
66 }
67
68 pub fn data(&self) -> &HashMap<String, Box<dyn Any + Send>> {
69 &self.data
70 }
71
72 pub fn put_data(&mut self, key: String, value: Box<dyn Any + Send>) {
73 self.data.insert(key, value);
74 }
75
76 pub fn get_as<S: 'static>(&self, key: &str) -> DceResult<&S> {
77 let type_name = type_name::<S>();
78 self.data.get(key).ok_or_else(|| DceErr::closed0(format!("{} has not bound yet", type_name)))?
79 .downcast_ref().ok_or_else(|| DceErr::closed0(format!("Box cannot downcast to {} ref", type_name)))
80 }
81
82 pub fn get_as_mut<S: 'static>(&mut self, key: &str) -> DceResult<&mut S> {
83 let type_name = type_name::<S>();
84 self.data.get_mut(key).ok_or_else(|| DceErr::closed0(format!("{} has not bound yet", type_name)))?
85 .downcast_mut().ok_or_else(|| DceErr::closed0(format!("Box cannot downcast to {} ref", type_name)))
86 }
87
88 pub fn set_routed_info(&mut self, api: &'static (dyn ApiTrait<Rp> + Send + Sync), params: HashMap<&'static str, PathParam>, suffix: Option<&'static str>) {
89 self.api = Some(api);
90 self.path_params = params;
91 self.suffix = suffix;
92 }
93}
94
95#[derive(Debug)]
96pub enum PathParam {
97 Option(Option<String>),
98 Required(String),
99 Vector(Vec<String>),
100}
101
102impl PathParam {
103 pub fn as_str(&self) -> Option<&str> {
104 match self {
105 PathParam::Option(Some(param)) => Some(param.as_str()),
106 PathParam::Option(_) => None,
107 PathParam::Required(param) => Some(param.as_str()),
108 PathParam::Vector(_) => panic!("Vec param cannot get as str"),
109 }
110 }
111
112 pub fn as_vec(&self) -> &Vec<String> {
113 match self {
114 PathParam::Vector(param) => param,
115 _ => panic!("Non vec type param cannot get as vec"),
116 }
117 }
118}
119
120
121
122#[derive(Debug)]
123pub struct Request<'a, Rp, ReqDto, RespDto>
124where Rp: RoutableProtocol + Send + Sync + Debug + 'static,
125 ReqDto: 'static,
126 RespDto: 'static
127{
128 api: &'static Api<Rp, ReqDto, RespDto>,
129 context: &'a mut Context<Rp>,
130}
131
132impl<'a, Rp, ReqDto, RespDto> Request<'a, Rp, ReqDto, RespDto>
133where Rp: RoutableProtocol + Send + Sync + Debug + 'static,
134{
135 #[cfg(feature = "async")]
136 pub async fn req<Req: From<ReqDto>>(&mut self) -> DceResult<Req> {
137 let body = self.context.rp_mut().body().await?;
138 self.parse(body, self.api.deserializers()).map(Req::from)
139 }
140
141 #[cfg(not(feature = "async"))]
142 pub fn req<Req: From<ReqDto>>(&mut self) -> DceResult<Req> {
143 let body = self.context.rp_mut().body()?;
144 self.parse(body, self.api.deserializers()).map(Req::from)
145 }
146
147 #[cfg(feature = "async")]
148 pub async fn dto(&mut self) -> DceResult<ReqDto> {
149 let body = self.context.rp_mut().body().await?;
150 self.parse(body, self.api.deserializers())
151 }
152
153 #[cfg(not(feature = "async"))]
154 pub fn dto(&mut self) -> DceResult<ReqDto> {
155 let body = self.context.rp_mut().body()?;
156 self.parse(body, self.api.deserializers())
157 }
158
159 fn parse(&self, serialized: Serialized, deserializers: &[Box<dyn Deserializer<ReqDto> + Send + Sync>]) -> DceResult<ReqDto> {
160 Rp::deserialize(deserializers, serialized, &self.context)
161 }
162
163 pub fn status<Resp: Into<RespDto>>(self, status: bool, data: Option<Resp>, message: Option<String>, code: isize) -> DceResult<Option<Response<Rp::Resp>>> {
164 let Self{context, api} = self;
165 Rp::pack_responsible::<RespDto>(context, api.serializers(), Serializable::Status(ResponseStatus {
166 status,
167 code,
168 message: message.unwrap_or("".to_string()),
169 data: data.map(|resp| resp.into()),
170 }))
171 }
172
173 pub fn success(self, data: Option<RespDto>) -> DceResult<Option<Response<Rp::Resp>>> {
174 self.status(true, data, None, 0)
175 }
176
177 pub fn fail(self, message: Option<String>, code: isize) -> DceResult<Option<Response<Rp::Resp>>> {
178 self.status::<RespDto>(false, None, message, code)
179 }
180
181 pub fn resp<Resp: Into<RespDto>>(self, resp: Resp) -> DceResult<Option<Response<Rp::Resp>>> {
182 let Self{context, api} = self;
183 Rp::pack_responsible(context, api.serializers(), Serializable::Dto(resp.into()))
184 }
185
186 pub fn end(self, resp: Option<RespDto>) -> DceResult<Option<Response<Rp::Resp>>> {
187 if let Some(resp) = resp {
188 let Self{context , api} = self;
189 Rp::pack_responsible::<RespDto>(context, api.serializers(), Serializable::Dto(resp.into()))
190 } else {
191 Ok(None)
192 }
193 }
194
195 pub fn pack(self, serialized: Serialized) -> DceResult<Option<Response<Rp::Resp>>> {
196 Ok(Some(Response::Serialized(serialized)))
197 }
198
199 pub fn raw_resp(self, resp: Rp::Resp) -> DceResult<Option<Response<Rp::Resp>>> {
200 Ok(Some(Response::Raw(resp)))
201 }
202
203 pub fn new(api: &'static Api<Rp, ReqDto, RespDto>, context: &'a mut Context<Rp>) -> Request<'a, Rp, ReqDto, RespDto> {
204 Request { api, context }
205 }
206}
207
208impl<Rp, ReqDto, RespDto> Deref for Request<'_, Rp, ReqDto, RespDto>
209 where Rp: RoutableProtocol + Send + Sync + Debug + 'static, {
210 type Target = Context<Rp>;
211
212 fn deref(&self) -> &Self::Target {
213 &self.context
214 }
215}
216
217impl<Rp, ReqDto, RespDto> DerefMut for Request<'_, Rp, ReqDto, RespDto>
218 where Rp: RoutableProtocol + Send + Sync + Debug + 'static, {
219
220 fn deref_mut(&mut self) -> &mut Self::Target {
221 &mut self.context
222 }
223}
224
225pub trait RequestTrait {
226 type Rp: RoutableProtocol;
227 type ReqDto;
228 type RespDto;
229}
230
231impl<Rp, ReqDto, RespDto> RequestTrait for Request<'_, Rp, ReqDto, RespDto>
232 where Rp: RoutableProtocol + Send + Sync + Debug + 'static, {
233 type Rp = Rp;
234 type ReqDto = ReqDto;
235 type RespDto = RespDto;
236}
237
238
239#[derive(Debug)]
240pub enum Response<Resp> {
241 Serialized(Serialized),
242 Raw(Resp),
243}
244
245
246#[derive(Debug, Serialize)]
247pub struct ResponseStatus<Dto> {
248 pub status: bool,
249 pub code: isize,
250 pub message: String,
251 pub data: Option<Dto>,
252}