webrtc_constraints/
capability.rs

1mod value;
2mod value_range;
3mod value_sequence;
4
5use std::ops::RangeInclusive;
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10pub use self::{
11    value::MediaTrackValueCapability, value_range::MediaTrackValueRangeCapability,
12    value_sequence::MediaTrackValueSequenceCapability,
13};
14
15/// A single [capability][media_track_capabilities] value of a [`MediaStreamTrack`][media_stream_track] object.
16///
17/// # W3C Spec Compliance
18///
19/// There exists no corresponding type in the W3C ["Media Capture and Streams"][media_capture_and_streams_spec] spec.
20///
21/// [media_stream_track]: https://www.w3.org/TR/mediacapture-streams/#dom-mediastreamtrack
22/// [media_track_capabilities]: https://www.w3.org/TR/mediacapture-streams/#dom-mediatrackcapabilities
23/// [media_capture_and_streams_spec]: https://www.w3.org/TR/mediacapture-streams
24#[derive(Debug, Clone, PartialEq)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26#[cfg_attr(feature = "serde", serde(untagged))]
27pub enum MediaTrackCapability {
28    // IMPORTANT:
29    // `BoolSequence` must be ordered before `Bool(…)` in order for
30    // `serde` to decode the correct variant.
31    /// A sequence of boolean-valued media track capabilities.
32    BoolSequence(MediaTrackValueSequenceCapability<bool>),
33    /// A single boolean-valued media track capability.
34    Bool(MediaTrackValueCapability<bool>),
35    // `IntegerRange` must be ordered before `FloatRange(…)` in order for
36    // `serde` to decode the correct variant.
37    /// A range of integer-valued media track capabilities.
38    IntegerRange(MediaTrackValueRangeCapability<u64>),
39    /// A range of floating-point-valued media track capabilities.
40    FloatRange(MediaTrackValueRangeCapability<f64>),
41    // IMPORTANT:
42    // `StringSequence` must be ordered before `String(…)` in order for
43    // `serde` to decode the correct variant.
44    /// A sequence of string-valued media track capabilities.
45    StringSequence(MediaTrackValueSequenceCapability<String>),
46    /// A single string-valued media track capability.
47    String(MediaTrackValueCapability<String>),
48}
49
50impl From<bool> for MediaTrackCapability {
51    fn from(capability: bool) -> Self {
52        Self::Bool(capability.into())
53    }
54}
55
56impl From<Vec<bool>> for MediaTrackCapability {
57    fn from(capability: Vec<bool>) -> Self {
58        Self::BoolSequence(capability.into())
59    }
60}
61
62impl From<RangeInclusive<u64>> for MediaTrackCapability {
63    fn from(capability: RangeInclusive<u64>) -> Self {
64        Self::IntegerRange(capability.into())
65    }
66}
67
68impl From<RangeInclusive<f64>> for MediaTrackCapability {
69    fn from(capability: RangeInclusive<f64>) -> Self {
70        Self::FloatRange(capability.into())
71    }
72}
73
74impl From<String> for MediaTrackCapability {
75    fn from(capability: String) -> Self {
76        Self::String(capability.into())
77    }
78}
79
80impl<'a> From<&'a str> for MediaTrackCapability {
81    fn from(capability: &'a str) -> Self {
82        let capability: String = capability.to_owned();
83        Self::from(capability)
84    }
85}
86
87impl From<Vec<String>> for MediaTrackCapability {
88    fn from(capability: Vec<String>) -> Self {
89        Self::StringSequence(capability.into())
90    }
91}
92
93impl From<Vec<&str>> for MediaTrackCapability {
94    fn from(capability: Vec<&str>) -> Self {
95        let capability: Vec<String> = capability.into_iter().map(|c| c.to_owned()).collect();
96        Self::from(capability)
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    type Subject = MediaTrackCapability;
105
106    mod from {
107        use super::*;
108
109        #[test]
110        fn bool_sequence() {
111            let actual = Subject::from(vec![false, true]);
112            let expected = Subject::BoolSequence(vec![false, true].into());
113
114            assert_eq!(actual, expected);
115        }
116
117        #[test]
118        fn bool() {
119            let actual = Subject::from(true);
120            let expected = Subject::Bool(true.into());
121
122            assert_eq!(actual, expected);
123        }
124
125        #[test]
126        fn integer_range() {
127            let actual = Subject::from(12..=34);
128            let expected = Subject::IntegerRange((12..=34).into());
129
130            assert_eq!(actual, expected);
131        }
132
133        #[test]
134        fn float() {
135            let actual = Subject::from(1.2..=3.4);
136            let expected = Subject::FloatRange((1.2..=3.4).into());
137
138            assert_eq!(actual, expected);
139        }
140
141        #[test]
142        fn string_sequence() {
143            let actual = Subject::from(vec!["foo".to_owned(), "bar".to_owned()]);
144            let expected = Subject::StringSequence(vec!["foo".to_owned(), "bar".to_owned()].into());
145
146            assert_eq!(actual, expected);
147        }
148
149        #[test]
150        fn string() {
151            let actual = Subject::from("foo".to_owned());
152            let expected = Subject::String("foo".to_owned().into());
153
154            assert_eq!(actual, expected);
155        }
156    }
157}
158
159#[cfg(feature = "serde")]
160#[cfg(test)]
161mod serde_tests {
162    use crate::macros::test_serde_symmetry;
163
164    use super::*;
165
166    type Subject = MediaTrackCapability;
167
168    #[test]
169    fn bool_sequence() {
170        let subject = Subject::BoolSequence(vec![false, true].into());
171        let json = serde_json::json!([false, true]);
172
173        test_serde_symmetry!(subject: subject, json: json);
174    }
175
176    #[test]
177    fn bool() {
178        let subject = Subject::Bool(true.into());
179        let json = serde_json::json!(true);
180
181        test_serde_symmetry!(subject: subject, json: json);
182    }
183
184    #[test]
185    fn integer_range() {
186        let subject = Subject::IntegerRange((12..=34).into());
187        let json = serde_json::json!({
188            "min": 12,
189            "max": 34,
190        });
191
192        test_serde_symmetry!(subject: subject, json: json);
193    }
194
195    #[test]
196    fn float() {
197        let subject = Subject::FloatRange((1.2..=3.4).into());
198        let json = serde_json::json!({
199            "min": 1.2,
200            "max": 3.4,
201        });
202
203        test_serde_symmetry!(subject: subject, json: json);
204    }
205
206    #[test]
207    fn string_sequence() {
208        let subject = Subject::StringSequence(vec!["foo".to_owned(), "bar".to_owned()].into());
209        let json = serde_json::json!(["foo", "bar"]);
210
211        test_serde_symmetry!(subject: subject, json: json);
212    }
213
214    #[test]
215    fn string() {
216        let subject = Subject::String("foo".to_owned().into());
217        let json = serde_json::json!("foo");
218
219        test_serde_symmetry!(subject: subject, json: json);
220    }
221}