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 // `BoolSequence` must be ordered before `Bool(…)` in order for 29 // `serde` to decode the correct variant. 30 BoolSequence(MediaTrackValueSequenceCapability<bool>), 31 Bool(MediaTrackValueCapability<bool>), 32 // `IntegerRange` must be ordered before `FloatRange(…)` in order for 33 // `serde` to decode the correct variant. 34 IntegerRange(MediaTrackValueRangeCapability<u64>), 35 FloatRange(MediaTrackValueRangeCapability<f64>), 36 // `StringSequence` must be ordered before `String(…)` in order for 37 // `serde` to decode the correct variant. 38 StringSequence(MediaTrackValueSequenceCapability<String>), 39 String(MediaTrackValueCapability<String>), 40 } 41 42 impl From<bool> for MediaTrackCapability { 43 fn from(capability: bool) -> Self { 44 Self::Bool(capability.into()) 45 } 46 } 47 48 impl From<Vec<bool>> for MediaTrackCapability { 49 fn from(capability: Vec<bool>) -> Self { 50 Self::BoolSequence(capability.into()) 51 } 52 } 53 54 impl From<RangeInclusive<u64>> for MediaTrackCapability { 55 fn from(capability: RangeInclusive<u64>) -> Self { 56 Self::IntegerRange(capability.into()) 57 } 58 } 59 60 impl From<RangeInclusive<f64>> for MediaTrackCapability { 61 fn from(capability: RangeInclusive<f64>) -> Self { 62 Self::FloatRange(capability.into()) 63 } 64 } 65 66 impl From<String> for MediaTrackCapability { 67 fn from(capability: String) -> Self { 68 Self::String(capability.into()) 69 } 70 } 71 72 impl<'a> From<&'a str> for MediaTrackCapability { 73 fn from(capability: &'a str) -> Self { 74 let capability: String = capability.to_owned(); 75 Self::from(capability) 76 } 77 } 78 79 impl From<Vec<String>> for MediaTrackCapability { 80 fn from(capability: Vec<String>) -> Self { 81 Self::StringSequence(capability.into()) 82 } 83 } 84 85 impl From<Vec<&str>> for MediaTrackCapability { 86 fn from(capability: Vec<&str>) -> Self { 87 let capability: Vec<String> = capability.into_iter().map(|c| c.to_owned()).collect(); 88 Self::from(capability) 89 } 90 } 91 92 #[cfg(test)] 93 mod tests { 94 use super::*; 95 96 type Subject = MediaTrackCapability; 97 98 mod from { 99 use super::*; 100 101 #[test] 102 fn bool_sequence() { 103 let actual = Subject::from(vec![false, true]); 104 let expected = Subject::BoolSequence(vec![false, true].into()); 105 106 assert_eq!(actual, expected); 107 } 108 109 #[test] 110 fn bool() { 111 let actual = Subject::from(true); 112 let expected = Subject::Bool(true.into()); 113 114 assert_eq!(actual, expected); 115 } 116 117 #[test] 118 fn integer_range() { 119 let actual = Subject::from(12..=34); 120 let expected = Subject::IntegerRange((12..=34).into()); 121 122 assert_eq!(actual, expected); 123 } 124 125 #[test] 126 fn float() { 127 let actual = Subject::from(1.2..=3.4); 128 let expected = Subject::FloatRange((1.2..=3.4).into()); 129 130 assert_eq!(actual, expected); 131 } 132 133 #[test] 134 fn string_sequence() { 135 let actual = Subject::from(vec!["foo".to_owned(), "bar".to_owned()]); 136 let expected = Subject::StringSequence(vec!["foo".to_owned(), "bar".to_owned()].into()); 137 138 assert_eq!(actual, expected); 139 } 140 141 #[test] 142 fn string() { 143 let actual = Subject::from("foo".to_owned()); 144 let expected = Subject::String("foo".to_owned().into()); 145 146 assert_eq!(actual, expected); 147 } 148 } 149 } 150 151 #[cfg(feature = "serde")] 152 #[cfg(test)] 153 mod serde_tests { 154 use crate::macros::test_serde_symmetry; 155 156 use super::*; 157 158 type Subject = MediaTrackCapability; 159 160 #[test] 161 fn bool_sequence() { 162 let subject = Subject::BoolSequence(vec![false, true].into()); 163 let json = serde_json::json!([false, true]); 164 165 test_serde_symmetry!(subject: subject, json: json); 166 } 167 168 #[test] 169 fn bool() { 170 let subject = Subject::Bool(true.into()); 171 let json = serde_json::json!(true); 172 173 test_serde_symmetry!(subject: subject, json: json); 174 } 175 176 #[test] 177 fn integer_range() { 178 let subject = Subject::IntegerRange((12..=34).into()); 179 let json = serde_json::json!({ 180 "min": 12, 181 "max": 34, 182 }); 183 184 test_serde_symmetry!(subject: subject, json: json); 185 } 186 187 #[test] 188 fn float() { 189 let subject = Subject::FloatRange((1.2..=3.4).into()); 190 let json = serde_json::json!({ 191 "min": 1.2, 192 "max": 3.4, 193 }); 194 195 test_serde_symmetry!(subject: subject, json: json); 196 } 197 198 #[test] 199 fn string_sequence() { 200 let subject = Subject::StringSequence(vec!["foo".to_owned(), "bar".to_owned()].into()); 201 let json = serde_json::json!(["foo", "bar"]); 202 203 test_serde_symmetry!(subject: subject, json: json); 204 } 205 206 #[test] 207 fn string() { 208 let subject = Subject::String("foo".to_owned().into()); 209 let json = serde_json::json!("foo"); 210 211 test_serde_symmetry!(subject: subject, json: json); 212 } 213 } 214