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