Skip to main content

msf_rtsp/header/
speed.rs

1//! Speed header and related types.
2
3use std::{
4    fmt::{self, Display, Formatter},
5    str::FromStr,
6};
7
8use crate::{Error, header::HeaderFieldValue};
9
10/// Speed header.
11#[derive(Copy, Clone)]
12pub struct SpeedHeader {
13    min: Option<f32>,
14    max: f32,
15}
16
17impl SpeedHeader {
18    /// Create a new RTSP/1.0 Speed header.
19    ///
20    /// # Panics
21    /// Panics if `max` is not greater than zero.
22    #[inline]
23    pub const fn new_v10(max: f32) -> Self {
24        assert!(max > 0f32);
25
26        Self { min: None, max }
27    }
28
29    /// Create a new RTSP/2.0 Speed header.
30    ///
31    /// # Panics
32    /// Panics if `min` or `max` are not greater than zero, or if `min` is
33    /// greater than `max`.
34    #[inline]
35    pub const fn new_v20(min: f32, max: f32) -> Self {
36        assert!(min > 0f32);
37        assert!(max > 0f32);
38        assert!(min <= max);
39
40        Self {
41            min: Some(min),
42            max,
43        }
44    }
45
46    /// Get the minimum acceptable speed.
47    #[inline]
48    pub fn min(&self) -> f32 {
49        self.min.unwrap_or(self.max)
50    }
51
52    /// Get the maximum acceptable speed.
53    #[inline]
54    pub fn max(&self) -> f32 {
55        self.max
56    }
57}
58
59impl Display for SpeedHeader {
60    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
61        if let Some(min) = self.min {
62            write!(f, "{}-{}", min, self.max)
63        } else {
64            Display::fmt(&self.max, f)
65        }
66    }
67}
68
69impl From<SpeedHeader> for HeaderFieldValue {
70    #[inline]
71    fn from(value: SpeedHeader) -> Self {
72        HeaderFieldValue::from(value.to_string())
73    }
74}
75
76impl FromStr for SpeedHeader {
77    type Err = Error;
78
79    fn from_str(s: &str) -> Result<Self, Self::Err> {
80        if let Some((min, max)) = s.split_once('-') {
81            let min = min
82                .parse()
83                .map_err(|_| Error::from_static_msg("invalid speed header"))?;
84
85            let max = max
86                .parse()
87                .map_err(|_| Error::from_static_msg("invalid speed header"))?;
88
89            if min <= 0f32 || max <= 0f32 || min > max {
90                return Err(Error::from_static_msg("speed out of bounds"));
91            }
92
93            let res = Self {
94                min: Some(min),
95                max,
96            };
97
98            Ok(res)
99        } else {
100            let max = s
101                .parse()
102                .map_err(|_| Error::from_static_msg("invalid speed header"))?;
103
104            if max <= 0f32 {
105                return Err(Error::from_static_msg("speed out of bounds"));
106            }
107
108            let res = Self { min: None, max };
109
110            Ok(res)
111        }
112    }
113}
114
115impl TryFrom<&HeaderFieldValue> for SpeedHeader {
116    type Error = Error;
117
118    fn try_from(value: &HeaderFieldValue) -> Result<Self, Self::Error> {
119        value
120            .to_str()
121            .map_err(|_| Error::from_static_msg("header field is not UTF-8 encoded"))?
122            .parse()
123    }
124}