1 use std::{ 2 collections::HashMap, 3 ops::{Deref, DerefMut}, 4 }; 5 6 #[cfg(feature = "serde")] 7 use serde::{Deserialize, Serialize}; 8 9 use crate::MediaTrackCapability; 10 11 /// The capabilities of a [`MediaStreamTrack`][media_stream_track] object. 12 /// 13 /// # W3C Spec Compliance 14 /// 15 /// Corresponds to [`MediaTrackCapabilities`][media_track_capabilities] 16 /// from the W3C ["Media Capture and Streams"][media_capture_and_streams_spec] spec. 17 /// 18 /// The W3C spec defines `MediaTrackSettings` in terma of a dictionary, 19 /// which per the [WebIDL spec][webidl_spec] is an ordered map (e.g. `IndexMap<K, V>`). 20 /// Since the spec however does not make use of the order of items 21 /// in the map we use a simple `HashMap<K, V>`. 22 /// 23 /// [media_stream_track]: https://www.w3.org/TR/mediacapture-streams/#dom-mediastreamtrack 24 /// [media_track_capabilities]: https://www.w3.org/TR/mediacapture-streams/#dom-mediatrackcapabilities 25 /// [media_capture_and_streams_spec]: https://www.w3.org/TR/mediacapture-streams 26 /// [webidl_spec]: https://webidl.spec.whatwg.org/#idl-dictionaries 27 #[derive(Debug, Clone, Default, PartialEq)] 28 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 29 #[cfg_attr(feature = "serde", serde(transparent))] 30 pub struct MediaTrackCapabilities(HashMap<String, MediaTrackCapability>); 31 32 impl MediaTrackCapabilities { 33 pub fn new(capabilities: HashMap<String, MediaTrackCapability>) -> Self { 34 Self(capabilities) 35 } 36 37 pub fn into_inner(self) -> HashMap<String, MediaTrackCapability> { 38 self.0 39 } 40 } 41 42 impl Deref for MediaTrackCapabilities { 43 type Target = HashMap<String, MediaTrackCapability>; 44 45 fn deref(&self) -> &Self::Target { 46 &self.0 47 } 48 } 49 50 impl DerefMut for MediaTrackCapabilities { 51 fn deref_mut(&mut self) -> &mut Self::Target { 52 &mut self.0 53 } 54 } 55 56 impl<T> FromIterator<(T, MediaTrackCapability)> for MediaTrackCapabilities 57 where 58 T: Into<String>, 59 { 60 fn from_iter<I>(iter: I) -> Self 61 where 62 I: IntoIterator<Item = (T, MediaTrackCapability)>, 63 { 64 Self::new(iter.into_iter().map(|(k, v)| (k.into(), v)).collect()) 65 } 66 } 67 68 impl IntoIterator for MediaTrackCapabilities { 69 type Item = (String, MediaTrackCapability); 70 type IntoIter = std::collections::hash_map::IntoIter<String, MediaTrackCapability>; 71 72 fn into_iter(self) -> Self::IntoIter { 73 self.0.into_iter() 74 } 75 } 76 77 #[cfg(feature = "serde")] 78 #[cfg(test)] 79 mod serde_tests { 80 use crate::{macros::test_serde_symmetry, property::name::*}; 81 82 use super::*; 83 84 type Subject = MediaTrackCapabilities; 85 86 #[test] 87 fn default() { 88 let subject = Subject::default(); 89 let json = serde_json::json!({}); 90 91 test_serde_symmetry!(subject: subject, json: json); 92 } 93 94 #[test] 95 fn customized() { 96 let subject = Subject::from_iter([ 97 (DEVICE_ID, "device-id".into()), 98 (AUTO_GAIN_CONTROL, true.into()), 99 (CHANNEL_COUNT, (12..=34).into()), 100 (LATENCY, (1.2..=3.4).into()), 101 ]); 102 let json = serde_json::json!({ 103 "deviceId": "device-id".to_owned(), 104 "autoGainControl": true, 105 "channelCount": { "min": 12, "max": 34 }, 106 "latency": { "min": 1.2, "max": 3.4 }, 107 }); 108 109 test_serde_symmetry!(subject: subject, json: json); 110 } 111 } 112