1use super::*;
2
3use async::*;
4use hyper::header::*;
5use std::convert::From;
6
7pub trait Reply<T, E>: serde::Serialize + From<Result<T, E>>
9where
10 T: serde::Serialize + 'static,
11 E: From<Error> + 'static,
12{
13 fn reply(&self, status: hyper::StatusCode) -> HyperFuture {
15 let encoded = match serde_json::to_vec(&self) {
16 Ok(encoded) => encoded,
17 Err(e) => {
18 return Box::new(ok(resp_serv_err::<Error>(
19 ErrorKind::EncodeJson(e).into(),
20 hyper::StatusCode::OK,
21 )));
22 }
23 };
24
25 let header_len = HeaderValue::from_str(&encoded.len().to_string())
26 .expect("should not b an invalid utf-8");
27
28 Box::new(result(
29 Response::builder()
30 .status(status)
31 .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*")
32 .header(CACHE_CONTROL, "no-cache, no-store, must-revalidate")
33 .header(CONTENT_TYPE, "application/json")
34 .header(CONTENT_LENGTH, header_len)
35 .body(encoded.into())
36 .or_else(|e| Ok(resp_serv_err(e, hyper::StatusCode::OK))),
37 ))
38 }
39
40 fn serv_state<F, S, Req>(state: S, f: F) -> HyperService
42 where
43 Self: 'static,
44 F: for<'a> Fn(&'a S, Req) -> Box<Future<Item = T, Error = E>> + 'static,
45 S: 'static,
46 Req: for<'de> serde::Deserialize<'de> + 'static,
47 {
48 let f = AsyncServiceFn::new(move |req| f(&state, req));
49 Box::new(async::AsyncServiceStateW::<_, Self>::new(f))
50 }
51
52 fn serv<F, Req>(f: F) -> HyperService
54 where
55 Self: 'static,
56 F: Fn(Req) -> Box<Future<Item = T, Error = E>> + 'static,
57 Req: for<'de> serde::Deserialize<'de> + 'static,
58 {
59 let f = AsyncServiceFn::new(f);
60 Box::new(async::AsyncServiceStateW::<_, Self>::new(f))
61 }
62
63 fn serv_state_sync<F, S, Req>(state: S, f: F) -> HyperService
65 where
66 Self: 'static,
67 F: for<'a> Fn(&'a S, Req) -> Result<T, E> + 'static,
68 S: 'static,
69 Req: for<'de> serde::Deserialize<'de> + 'static,
70 {
71 let f = async::AsyncServiceFn::new(move |req| Box::new(result(f(&state, req))));
72 Box::new(async::AsyncServiceStateW::<_, Self>::new(f))
73 }
74
75 fn serv_sync<F, Req>(f: F) -> HyperService
77 where
78 Self: 'static,
79 F: Fn(Req) -> Result<T, E> + 'static,
80 Req: for<'de> serde::Deserialize<'de> + 'static,
81 {
82 let f = async::AsyncServiceFn::new(move |req| Box::new(result(f(req))));
83 Box::new(async::AsyncServiceStateW::<_, Self>::new(f))
84 }
85}
86
87#[derive(Serialize)]
88#[serde(tag = "status")]
89pub enum ServiceReply<T: serde::Serialize, E> {
90 #[serde(rename = "ok")]
91 Ok { result: T },
92 #[serde(rename = "error")]
94 Err {
95 reason: String,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 msg: Option<String>,
98 #[serde(skip)]
99 _e: E,
100 },
101}
102
103impl<T, E> From<E> for ServiceReply<T, E>
104where
105 T: serde::Serialize,
106 E: Debug + std::error::Error,
107{
108 #[cfg(debug_assertions)]
109 fn from(e: E) -> ServiceReply<T, E> {
110 let reason = e.description().to_owned();
111 let msg = format!("{:?}", e);
112 ServiceReply::Err {
113 reason,
114 msg: Some(msg),
115 _e: e,
116 }
117 }
118
119 #[cfg(not(debug_assertions))]
120 fn from(e: E) -> ServiceReply<T, E> {
121 let reason = e.description().to_owned();
122 ServiceReply::Err {
123 reason,
124 msg: None,
125 _e: e,
126 }
127 }
128}
129
130impl<T, E> From<Result<T, E>> for ServiceReply<T, E>
131where
132 T: serde::Serialize,
133 E: Debug + std::error::Error,
134{
135 fn from(res: Result<T, E>) -> ServiceReply<T, E> {
136 match res {
137 Ok(resp) => ServiceReply::Ok { result: resp },
138 Err(e) => {
139 trace!("error: {:?}", e);
140 e.into()
141 }
142 }
143 }
144}
145
146impl<T, E> Reply<T, E> for ServiceReply<T, E>
147where
148 T: serde::Serialize + 'static,
149 E: From<Error> + Debug + std::error::Error + 'static,
150{}