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}