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