rtsp_types/headers/
media_range.rs

1// Copyright (C) 2020 Sebastian Dröge <sebastian@centricular.com>
2//
3// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4
5use super::Range;
6use super::*;
7
8/// `Media-Range` header ([RFC 7826 section 18.30](https://tools.ietf.org/html/rfc7826#section-18.30)).
9#[derive(Debug, Clone)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct MediaRange(Vec<Range>);
12
13impl std::ops::Deref for MediaRange {
14    type Target = Vec<Range>;
15
16    fn deref(&self) -> &Self::Target {
17        &self.0
18    }
19}
20
21impl std::ops::DerefMut for MediaRange {
22    fn deref_mut(&mut self) -> &mut Self::Target {
23        &mut self.0
24    }
25}
26
27impl AsRef<Vec<Range>> for MediaRange {
28    fn as_ref(&self) -> &Vec<Range> {
29        &self.0
30    }
31}
32
33impl AsMut<Vec<Range>> for MediaRange {
34    fn as_mut(&mut self) -> &mut Vec<Range> {
35        &mut self.0
36    }
37}
38
39impl From<Vec<Range>> for MediaRange {
40    fn from(v: Vec<Range>) -> Self {
41        MediaRange(v)
42    }
43}
44
45impl<'a> From<&'a [Range]> for MediaRange {
46    fn from(v: &'a [Range]) -> Self {
47        MediaRange(v.to_vec())
48    }
49}
50
51impl MediaRange {
52    /// Creates a new `Media-Range` header builder.
53    pub fn builder() -> MediaRangeBuilder {
54        MediaRangeBuilder(Vec::new())
55    }
56}
57
58/// Builder for the 'Media-Range' header.
59#[derive(Debug, Clone)]
60pub struct MediaRangeBuilder(Vec<Range>);
61
62impl MediaRangeBuilder {
63    /// Add the provided range to the `Media-Range` header.
64    pub fn range(mut self, range: Range) -> Self {
65        self.0.push(range);
66        self
67    }
68
69    /// Build the `Media-Range` header.
70    pub fn build(self) -> MediaRange {
71        MediaRange(self.0)
72    }
73}
74
75impl super::TypedHeader for MediaRange {
76    fn from_headers(headers: impl AsRef<Headers>) -> Result<Option<Self>, HeaderParseError> {
77        let headers = headers.as_ref();
78
79        let header = match headers.get(&MEDIA_RANGE) {
80            None => return Ok(None),
81            Some(header) => header,
82        };
83
84        let mut ranges = Vec::new();
85        for range in header.as_str().split(',') {
86            let range = range.trim();
87
88            ranges.push(range.parse()?);
89        }
90
91        Ok(Some(MediaRange(ranges)))
92    }
93
94    fn insert_into(&self, mut headers: impl AsMut<Headers>) {
95        let headers = headers.as_mut();
96
97        let mut ranges = String::new();
98        for range in &self.0 {
99            if !ranges.is_empty() {
100                ranges.push_str(", ");
101            }
102
103            ranges.push_str(&range.to_string());
104        }
105
106        headers.insert(MEDIA_RANGE, ranges);
107    }
108}
109
110impl super::TypedAppendableHeader for MediaRange {
111    fn append_to(&self, mut headers: impl AsMut<Headers>) {
112        let headers = headers.as_mut();
113
114        let mut ranges = String::new();
115        for range in &self.0 {
116            if !ranges.is_empty() {
117                ranges.push_str(", ");
118            }
119
120            ranges.push_str(&range.to_string());
121        }
122
123        headers.append(MEDIA_RANGE, ranges);
124    }
125}