headers/common/
content_type.rs1use std::fmt;
2
3use http::{HeaderName, HeaderValue};
4use mime::Mime;
5
6use crate::{Error, Header};
7
8#[derive(Clone, Debug, PartialEq)]
42pub struct ContentType(Mime);
43
44impl ContentType {
45 #[inline]
47 pub fn json() -> ContentType {
48 ContentType(mime::APPLICATION_JSON)
49 }
50
51 #[inline]
53 pub fn text() -> ContentType {
54 ContentType(mime::TEXT_PLAIN)
55 }
56
57 #[inline]
59 pub fn text_utf8() -> ContentType {
60 ContentType(mime::TEXT_PLAIN_UTF_8)
61 }
62
63 #[inline]
65 pub fn html() -> ContentType {
66 ContentType(mime::TEXT_HTML)
67 }
68
69 #[inline]
71 pub fn xml() -> ContentType {
72 ContentType(mime::TEXT_XML)
73 }
74
75 #[inline]
77 pub fn form_url_encoded() -> ContentType {
78 ContentType(mime::APPLICATION_WWW_FORM_URLENCODED)
79 }
80 #[inline]
82 pub fn jpeg() -> ContentType {
83 ContentType(mime::IMAGE_JPEG)
84 }
85
86 #[inline]
88 pub fn png() -> ContentType {
89 ContentType(mime::IMAGE_PNG)
90 }
91
92 #[inline]
94 pub fn octet_stream() -> ContentType {
95 ContentType(mime::APPLICATION_OCTET_STREAM)
96 }
97}
98
99impl Header for ContentType {
100 fn name() -> &'static HeaderName {
101 &::http::header::CONTENT_TYPE
102 }
103
104 fn decode<'i, I: Iterator<Item = &'i HeaderValue>>(values: &mut I) -> Result<Self, Error> {
105 values
106 .next()
107 .and_then(|v| v.to_str().ok()?.parse().ok())
108 .map(ContentType)
109 .ok_or_else(Error::invalid)
110 }
111
112 fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
113 let value = self
114 .0
115 .as_ref()
116 .parse()
117 .expect("Mime is always a valid HeaderValue");
118 values.extend(::std::iter::once(value));
119 }
120}
121
122impl From<mime::Mime> for ContentType {
123 fn from(m: mime::Mime) -> ContentType {
124 ContentType(m)
125 }
126}
127
128impl From<ContentType> for mime::Mime {
129 fn from(ct: ContentType) -> mime::Mime {
130 ct.0
131 }
132}
133
134impl fmt::Display for ContentType {
135 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136 fmt::Display::fmt(&self.0, f)
137 }
138}
139
140impl std::str::FromStr for ContentType {
141 type Err = Error;
142
143 fn from_str(s: &str) -> Result<ContentType, Self::Err> {
144 s.parse::<Mime>()
145 .map(|m| m.into())
146 .map_err(|_| Error::invalid())
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::super::test_decode;
153 use super::ContentType;
154
155 #[test]
156 fn json() {
157 assert_eq!(
158 test_decode::<ContentType>(&["application/json"]),
159 Some(ContentType::json()),
160 );
161 }
162
163 #[test]
164 fn from_str() {
165 assert_eq!(
166 "application/json".parse::<ContentType>().unwrap(),
167 ContentType::json(),
168 );
169 assert!("invalid-mimetype".parse::<ContentType>().is_err());
170 }
171
172 bench_header!(bench_plain, ContentType, "text/plain");
173 bench_header!(bench_json, ContentType, "application/json");
174 bench_header!(
175 bench_formdata,
176 ContentType,
177 "multipart/form-data; boundary=---------------abcd"
178 );
179}