http_types/content/
content_type.rs1use std::{convert::TryInto, str::FromStr};
2
3use crate::headers::{HeaderName, HeaderValue, Headers, CONTENT_TYPE};
4use crate::Mime;
5
6#[derive(Debug)]
35pub struct ContentType {
36 media_type: Mime,
37}
38
39impl ContentType {
40 pub fn new<U>(media_type: U) -> Self
42 where
43 U: TryInto<Mime>,
44 U::Error: std::fmt::Debug,
45 {
46 Self {
47 media_type: media_type
48 .try_into()
49 .expect("could not convert into a valid Mime type"),
50 }
51 }
52
53 pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
60 let headers = match headers.as_ref().get(CONTENT_TYPE) {
61 Some(headers) => headers,
62 None => return Ok(None),
63 };
64
65 let ctation = headers.iter().last().unwrap();
68
69 let media_type = Mime::from_str(ctation.as_str()).map_err(|mut e| {
70 e.set_status(400);
71 e
72 })?;
73 Ok(Some(Self { media_type }))
74 }
75
76 pub fn apply(&self, mut headers: impl AsMut<Headers>) {
78 headers.as_mut().insert(self.name(), self.value());
79 }
80
81 pub fn name(&self) -> HeaderName {
83 CONTENT_TYPE
84 }
85
86 pub fn value(&self) -> HeaderValue {
88 let output = format!("{}", self.media_type);
89 unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
91 }
92}
93
94impl PartialEq<Mime> for ContentType {
95 fn eq(&self, other: &Mime) -> bool {
96 &self.media_type == other
97 }
98}
99
100impl PartialEq<&Mime> for ContentType {
101 fn eq(&self, other: &&Mime) -> bool {
102 &&self.media_type == other
103 }
104}
105
106impl From<Mime> for ContentType {
107 fn from(media_type: Mime) -> Self {
108 Self { media_type }
109 }
110}
111
112#[cfg(test)]
113mod test {
114 use super::*;
115 use crate::headers::Headers;
116
117 #[test]
118 fn smoke() -> crate::Result<()> {
119 let ct = ContentType::new(Mime::from_str("text/*")?);
120
121 let mut headers = Headers::new();
122 ct.apply(&mut headers);
123
124 let ct = ContentType::from_headers(headers)?.unwrap();
125 assert_eq!(
126 ct.value(),
127 format!("{}", Mime::from_str("text/*")?).as_str()
128 );
129 Ok(())
130 }
131
132 #[test]
133 fn bad_request_on_parse_error() {
134 let mut headers = Headers::new();
135 headers.insert(CONTENT_TYPE, "<nori ate the tag. yum.>");
136 let err = ContentType::from_headers(headers).unwrap_err();
137 assert_eq!(err.status(), 400);
138 }
139}