rtsp_types/headers/
content_type.rs1use super::*;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct ContentType {
11 pub media_type: super::MediaType,
13 pub media_subtype: String,
15 pub params: Vec<(String, Option<String>)>,
17}
18
19impl super::TypedHeader for ContentType {
20 fn from_headers(headers: impl AsRef<Headers>) -> Result<Option<Self>, HeaderParseError> {
21 use super::parser_helpers::split_once;
22
23 let headers = headers.as_ref();
24
25 let header = match headers.get(&CONTENT_TYPE) {
26 None => return Ok(None),
27 Some(header) => header,
28 };
29
30 let content_type = header.as_str();
31
32 let (media_type, params) = match split_once(content_type, ';') {
33 None => (content_type, Vec::new()),
34 Some((media_type, params_string)) => {
35 let mut params = Vec::new();
36 for param in params_string.split(';') {
37 let param = param.trim();
38 if let Some((param, value)) = split_once(param, '=') {
39 params.push((String::from(param), Some(String::from(value))));
40 } else {
41 params.push((String::from(param), None));
42 }
43 }
44
45 (media_type, params)
46 }
47 };
48
49 let (media_type, media_subtype) = split_once(media_type, '/').ok_or(HeaderParseError)?;
50 let media_type = media_type.parse().map_err(|_| HeaderParseError)?;
51
52 Ok(Some(ContentType {
53 media_type,
54 media_subtype: media_subtype.into(),
55 params,
56 }))
57 }
58
59 fn insert_into(&self, mut headers: impl AsMut<Headers>) {
60 use std::fmt::Write;
61
62 let headers = headers.as_mut();
63
64 let mut content_type = String::new();
65 write!(
66 &mut content_type,
67 "{}/{}",
68 self.media_type, self.media_subtype
69 )
70 .unwrap();
71
72 for param in &self.params {
73 content_type.push(';');
74 if let Some(ref value) = param.1 {
75 write!(&mut content_type, "{}={}", param.0, value).unwrap();
76 } else {
77 content_type.push_str(¶m.0);
78 }
79 }
80
81 headers.insert(CONTENT_TYPE, content_type);
82 }
83}