rocket_json_response/
lib.rs

1/*!
2# JSON Response for Rocket Framework
3
4This is a crate which provides `JSONResponse` and `JSONResponseWithoutData` structs to response JSON format data with an additional **code** integer value.
5
6Typically, the code **0** means **OK**. You can define other codes by yourself by implementing `JSONResponseCode` trait for your struct.
7
8See `examples`.
9*/
10
11pub extern crate json_gettext;
12
13mod json_response_code;
14mod to_json;
15
16use std::{
17    fmt::{self, Debug, Formatter},
18    io::Cursor,
19    marker::PhantomData,
20};
21
22use json_gettext::JSONGetTextValue;
23pub use json_response_code::JSONResponseCode;
24use rocket::{
25    request::Request,
26    response::{self, Responder, Response},
27};
28pub use to_json::ToJSON;
29
30/// To respond JSON data.
31///
32/// The format of JSON data looks like,
33///
34/// ```json
35/// {
36///    code: <integer>,
37///    data: <json value>
38/// }
39/// ```
40pub struct JSONResponse<'a, T: ToJSON = JSONGetTextValue<'a>> {
41    code:    Box<dyn JSONResponseCode>,
42    data:    T,
43    phantom: PhantomData<&'a T>,
44}
45
46impl<'a, T: ToJSON> Debug for JSONResponse<'a, T> {
47    #[inline]
48    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
49        debug_helper::impl_debug_for_struct!(JSONResponse, f, self, let .code = self.code.get_code(), let .data = self.data.to_json());
50    }
51}
52
53impl<'a, T: ToJSON> JSONResponse<'a, T> {
54    #[inline]
55    pub fn ok(data: T) -> Self {
56        JSONResponse {
57            code: Box::new(0),
58            data,
59            phantom: PhantomData,
60        }
61    }
62
63    #[inline]
64    pub fn err<K: JSONResponseCode + 'static>(code: K, data: T) -> Self {
65        JSONResponse {
66            code: Box::new(code),
67            data,
68            phantom: PhantomData,
69        }
70    }
71}
72
73impl<'r, 'o: 'r, T: ToJSON> Responder<'r, 'o> for JSONResponse<'o, T> {
74    fn respond_to(self, _: &Request) -> response::Result<'o> {
75        let json =
76            format!("{{\"code\":{},\"data\":{}}}", self.code.get_code(), self.data.to_json());
77
78        let mut response = Response::build();
79
80        response
81            .raw_header("Content-Type", "application/json")
82            .sized_body(json.len(), Cursor::new(json));
83
84        response.ok()
85    }
86}
87
88/// To respond JSON data.
89///
90/// The format of JSON data looks like,
91///
92/// ```json
93/// {
94///    code: <integer>
95/// }
96/// ```
97pub struct JSONResponseWithoutData {
98    code: Box<dyn JSONResponseCode>,
99}
100
101impl Debug for JSONResponseWithoutData {
102    #[inline]
103    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
104        debug_helper::impl_debug_for_struct!(JSONResponseWithoutData, f, self, let .code = self.code.get_code());
105    }
106}
107
108impl JSONResponseWithoutData {
109    #[inline]
110    pub fn ok() -> Self {
111        JSONResponseWithoutData {
112            code: Box::new(0)
113        }
114    }
115
116    #[inline]
117    pub fn err<K: JSONResponseCode + 'static>(code: K) -> Self {
118        JSONResponseWithoutData {
119            code: Box::new(code)
120        }
121    }
122}
123
124impl<'r, 'o: 'r> Responder<'r, 'o> for JSONResponseWithoutData {
125    fn respond_to(self, _: &Request) -> response::Result<'o> {
126        let json = format!("{{\"code\":{}}}", self.code.get_code());
127
128        let mut response = Response::build();
129
130        response
131            .raw_header("Content-Type", "application/json")
132            .sized_body(json.len(), Cursor::new(json));
133
134        response.ok()
135    }
136}