http_type/content_type/impl.rs
1use crate::*;
2
3impl ContentType {
4 /// Handles the `application/json` Content-Type by serializing the provided data
5 /// into a JSON string.
6 ///
7 /// # Type Parameters
8 /// - `T`: The type of the data to be serialized, which must implement `Serialize`.
9 ///
10 /// # Parameters
11 /// - `data`: The data to be serialized into JSON.
12 ///
13 /// # Returns
14 /// A string containing the serialized JSON representation of the provided data.
15 /// If serialization fails, it returns an empty JSON object (`{}`).
16 fn get_application_json<T: Serialize + Display>(data: &T) -> String {
17 json_to_string(data).unwrap_or_else(|_| "{}".to_string())
18 }
19
20 /// Handles the `application/xml` Content-Type by serializing the provided data
21 /// into an XML string.
22 ///
23 /// # Type Parameters
24 /// - `T`: The type of the data to be serialized, which must implement `Serialize`.
25 ///
26 /// # Parameters
27 /// - `data`: The data to be serialized into XML.
28 ///
29 /// # Returns
30 /// A string containing the serialized XML representation of the provided data.
31 /// If serialization fails, it returns an empty XML root element (`<root></root>`).
32 fn get_application_xml<T: Serialize + Display>(data: &T) -> String {
33 serde_xml_rs::to_string(data).unwrap_or_else(|_| "<root></root>".to_string())
34 }
35
36 /// Handles the `text/plain` Content-Type by formatting the provided data
37 /// into a plain text string.
38 ///
39 /// # Type Parameters
40 /// - `T`: The type of the data to be formatted, which must implement `Serialize`, `Debug`, `Clone`, and `Default`.
41 ///
42 /// # Parameters
43 /// - `data`: The data to be formatted into plain text.
44 ///
45 /// # Returns
46 /// A plain text string representing the provided data, formatted with the `Debug` trait.
47 fn get_text_plain<T: Serialize + Debug + Clone + Default + Display>(data: &T) -> String {
48 data.to_string()
49 }
50
51 /// Handles the `text/html` Content-Type by formatting the provided data
52 /// into an HTML string, typically inside a simple table.
53 ///
54 /// # Type Parameters
55 /// - `T`: The type of the data to be formatted, which must implement `Serialize`, `Debug`, `Clone`, and `Default`.
56 ///
57 /// # Parameters
58 /// - `data`: The data to be formatted into HTML.
59 ///
60 /// # Returns
61 /// A string containing the HTML representation of the provided data, inside a table row.
62 fn get_text_html<T: Serialize + Debug + Clone + Default>(data: &T) -> String {
63 let mut html: String = String::with_capacity(64);
64 html.push_str("<table><tr><td>");
65 html.push_str(&format!("{:?}", data));
66 html.push_str("</td></tr></table>");
67 html
68 }
69
70 /// Handles the `application/x-www-form-urlencoded` Content-Type by serializing
71 /// the provided data into a URL-encoded string.
72 ///
73 /// # Type Parameters
74 /// - `T`: The type of the data to be serialized, which must implement `Serialize`.
75 ///
76 /// # Parameters
77 /// - `data`: The data to be serialized into URL-encoded format.
78 ///
79 /// # Returns
80 /// A string containing the URL-encoded representation of the provided data.
81 /// If serialization fails, it returns an empty string.
82 fn get_form_url_encoded<T: Serialize + Display>(data: &T) -> String {
83 serde_urlencoded::to_string(data).unwrap_or_else(|_| String::new())
84 }
85
86 /// Handles binary data when the `Content-Type` is unknown by formatting the
87 /// provided data as a hexadecimal string.
88 ///
89 /// # Type Parameters
90 /// - `T`: The type of the data to be formatted, which must implement `Serialize`, `Debug`, `Clone`, and `Default`.
91 ///
92 /// # Parameters
93 /// - `data`: The data to be formatted into binary representation.
94 ///
95 /// # Returns
96 /// A string containing the hexadecimal encoding of the provided data.
97 fn get_binary<T: Serialize + Debug + Clone + Default + Display>(data: &T) -> String {
98 hex::encode(data.to_string())
99 }
100
101 /// Public interface for getting a formatted body string based on the `ContentType`.
102 ///
103 /// This method routes the data to the appropriate handler method based on the
104 /// `ContentType`, formatting the body accordingly.
105 ///
106 /// # Type Parameters
107 /// - `T`: The type of the data to be formatted, which must implement `Serialize`, `Debug`, `Clone`, and `Default`.
108 ///
109 /// # Parameters
110 /// - `data`: The data to be formatted into the body string.
111 ///
112 /// # Returns
113 /// A string containing the formatted body based on the content type, such as JSON, XML, plain text, HTML, etc.
114 pub fn get_body_string<T: Serialize + Debug + Clone + Default + Display>(
115 &self,
116 data: &T,
117 ) -> String {
118 match self {
119 Self::ApplicationJson => Self::get_application_json(data),
120 Self::ApplicationXml => Self::get_application_xml(data),
121 Self::TextPlain => Self::get_text_plain(data),
122 Self::TextHtml => Self::get_text_html(data),
123 Self::FormUrlEncoded => Self::get_form_url_encoded(data),
124 Self::Unknown => Self::get_binary(data),
125 }
126 }
127
128 /// Formats a content type with a charset value.
129 ///
130 /// - `content_type`: The content type (e.g., `"text/html"`).
131 /// - `charset`: The character set (e.g., `"utf-8"`).
132 /// - Returns: A format string like `"text/html; charset=utf-8"`.
133 pub fn format_content_type_with_charset(content_type: &str, charset: &str) -> String {
134 let mut result: String = String::with_capacity(
135 content_type.len() + SEMICOLON_SPACE.len() + CHARSET_EQUAL.len() + charset.len(),
136 );
137 result.push_str(content_type);
138 result.push_str(SEMICOLON_SPACE);
139 result.push_str(CHARSET_EQUAL);
140 result.push_str(charset);
141 result
142 }
143
144 /// Formats a content type with a full charset declaration.
145 ///
146 /// - `content_type`: The content type (e.g., `"text/html"`).
147 /// - `charset_with_key`: The charset declaration (e.g., `"charset=utf-8"`).
148 /// - Returns: A format string like `"text/html; charset=utf-8"`.
149 pub fn format_content_type_with_charset_declaration(
150 content_type: &str,
151 charset_with_key: &str,
152 ) -> String {
153 let mut result: String = String::with_capacity(
154 content_type.len() + SEMICOLON_SPACE.len() + charset_with_key.len(),
155 );
156 result.push_str(content_type);
157 result.push_str(SEMICOLON_SPACE);
158 result.push_str(charset_with_key);
159 result
160 }
161}
162
163impl FromStr for ContentType {
164 type Err = ();
165
166 fn from_str(data: &str) -> Result<Self, Self::Err> {
167 match data.to_ascii_lowercase() {
168 _data if _data == APPLICATION_JSON => Ok(Self::ApplicationJson),
169 _data if _data == APPLICATION_XML => Ok(Self::ApplicationXml),
170 _data if _data == TEXT_PLAIN => Ok(Self::TextPlain),
171 _data if _data == TEXT_HTML => Ok(Self::TextHtml),
172 _data if _data == FORM_URLENCODED => Ok(Self::FormUrlEncoded),
173 _ => Ok(Self::Unknown),
174 }
175 }
176}
177
178impl Default for ContentType {
179 fn default() -> Self {
180 Self::Unknown
181 }
182}