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