1 mod value; 2 mod value_range; 3 mod value_sequence; 4 5 use std::ops::RangeInclusive; 6 7 #[cfg(feature = "serde")] 8 use serde::{Deserialize, Serialize}; 9 10 pub 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))] 27 pub 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 50 impl From<bool> for MediaTrackCapability { from(capability: bool) -> Self51 fn from(capability: bool) -> Self { 52 Self::Bool(capability.into()) 53 } 54 } 55 56 impl From<Vec<bool>> for MediaTrackCapability { from(capability: Vec<bool>) -> Self57 fn from(capability: Vec<bool>) -> Self { 58 Self::BoolSequence(capability.into()) 59 } 60 } 61 62 impl From<RangeInclusive<u64>> for MediaTrackCapability { from(capability: RangeInclusive<u64>) -> Self63 fn from(capability: RangeInclusive<u64>) -> Self { 64 Self::IntegerRange(capability.into()) 65 } 66 } 67 68 impl From<RangeInclusive<f64>> for MediaTrackCapability { from(capability: RangeInclusive<f64>) -> Self69 fn from(capability: RangeInclusive<f64>) -> Self { 70 Self::FloatRange(capability.into()) 71 } 72 } 73 74 impl From<String> for MediaTrackCapability { from(capability: String) -> Self75 fn from(capability: String) -> Self { 76 Self::String(capability.into()) 77 } 78 } 79 80 impl<'a> From<&'a str> for MediaTrackCapability { from(capability: &'a str) -> Self81 fn from(capability: &'a str) -> Self { 82 let capability: String = capability.to_owned(); 83 Self::from(capability) 84 } 85 } 86 87 impl From<Vec<String>> for MediaTrackCapability { from(capability: Vec<String>) -> Self88 fn from(capability: Vec<String>) -> Self { 89 Self::StringSequence(capability.into()) 90 } 91 } 92 93 impl From<Vec<&str>> for MediaTrackCapability { from(capability: Vec<&str>) -> Self94 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)] 101 mod tests { 102 use super::*; 103 104 type Subject = MediaTrackCapability; 105 106 mod from { 107 use super::*; 108 109 #[test] bool_sequence()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] bool()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] integer_range()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] float()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] string_sequence()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] string()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)] 161 mod serde_tests { 162 use crate::macros::test_serde_symmetry; 163 164 use super::*; 165 166 type Subject = MediaTrackCapability; 167 168 #[test] bool_sequence()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] bool()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] integer_range()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] float()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] string_sequence()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] string()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 } 222