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}