1 use std::{
2     iter::FromIterator,
3     ops::{Deref, DerefMut},
4 };
5 
6 #[cfg(feature = "serde")]
7 use serde::{Deserialize, Serialize};
8 
9 use crate::{
10     MediaTrackConstraint, MediaTrackConstraintResolutionStrategy, MediaTrackSupportedConstraints,
11     ResolvedMediaTrackConstraint, SanitizedMediaTrackConstraint,
12 };
13 
14 use super::constraint_set::GenericMediaTrackConstraintSet;
15 
16 /// Advanced media track constraints that contain sets of either bare values or constraints.
17 pub type AdvancedMediaTrackConstraints = GenericAdvancedMediaTrackConstraints<MediaTrackConstraint>;
18 
19 /// Advanced media track constraints that contain sets of constraints (both, empty and non-empty).
20 pub type ResolvedAdvancedMediaTrackConstraints =
21     GenericAdvancedMediaTrackConstraints<ResolvedMediaTrackConstraint>;
22 
23 /// Advanced media track constraints that contain sets of only non-empty constraints.
24 pub type SanitizedAdvancedMediaTrackConstraints =
25     GenericAdvancedMediaTrackConstraints<SanitizedMediaTrackConstraint>;
26 
27 /// The list of advanced constraint sets for a [`MediaStreamTrack`][media_stream_track] object.
28 ///
29 /// # W3C Spec Compliance
30 ///
31 /// Corresponds to [`ResolvedMediaTrackConstraints.advanced`][media_track_constraints_advanced]
32 /// from the W3C ["Media Capture and Streams"][media_capture_and_streams_spec] spec.
33 ///
34 /// [media_stream_track]: https://www.w3.org/TR/mediacapture-streams/#dom-mediastreamtrack
35 /// [media_track_constraints_advanced]: https://www.w3.org/TR/mediacapture-streams/#dom-mediatrackconstraints-advanced
36 /// [media_capture_and_streams_spec]: https://www.w3.org/TR/mediacapture-streams/
37 #[derive(Debug, Clone, Eq, PartialEq)]
38 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
39 #[cfg_attr(feature = "serde", serde(transparent))]
40 pub struct GenericAdvancedMediaTrackConstraints<T>(Vec<GenericMediaTrackConstraintSet<T>>);
41 
42 impl<T> GenericAdvancedMediaTrackConstraints<T> {
new(constraints: Vec<GenericMediaTrackConstraintSet<T>>) -> Self43     pub fn new(constraints: Vec<GenericMediaTrackConstraintSet<T>>) -> Self {
44         Self(constraints)
45     }
46 
into_inner(self) -> Vec<GenericMediaTrackConstraintSet<T>>47     pub fn into_inner(self) -> Vec<GenericMediaTrackConstraintSet<T>> {
48         self.0
49     }
50 }
51 
52 impl<T> Deref for GenericAdvancedMediaTrackConstraints<T> {
53     type Target = Vec<GenericMediaTrackConstraintSet<T>>;
54 
deref(&self) -> &Self::Target55     fn deref(&self) -> &Self::Target {
56         &self.0
57     }
58 }
59 
60 impl<T> DerefMut for GenericAdvancedMediaTrackConstraints<T> {
deref_mut(&mut self) -> &mut Self::Target61     fn deref_mut(&mut self) -> &mut Self::Target {
62         &mut self.0
63     }
64 }
65 
66 impl<T> Default for GenericAdvancedMediaTrackConstraints<T> {
default() -> Self67     fn default() -> Self {
68         Self(Default::default())
69     }
70 }
71 
72 impl<T> FromIterator<GenericMediaTrackConstraintSet<T>>
73     for GenericAdvancedMediaTrackConstraints<T>
74 {
from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = GenericMediaTrackConstraintSet<T>>,75     fn from_iter<I>(iter: I) -> Self
76     where
77         I: IntoIterator<Item = GenericMediaTrackConstraintSet<T>>,
78     {
79         Self::new(iter.into_iter().collect())
80     }
81 }
82 
83 impl<T> IntoIterator for GenericAdvancedMediaTrackConstraints<T> {
84     type Item = GenericMediaTrackConstraintSet<T>;
85     type IntoIter = std::vec::IntoIter<GenericMediaTrackConstraintSet<T>>;
86 
into_iter(self) -> Self::IntoIter87     fn into_iter(self) -> Self::IntoIter {
88         self.0.into_iter()
89     }
90 }
91 
92 impl AdvancedMediaTrackConstraints {
to_resolved(&self) -> ResolvedAdvancedMediaTrackConstraints93     pub fn to_resolved(&self) -> ResolvedAdvancedMediaTrackConstraints {
94         self.clone().into_resolved()
95     }
96 
into_resolved(self) -> ResolvedAdvancedMediaTrackConstraints97     pub fn into_resolved(self) -> ResolvedAdvancedMediaTrackConstraints {
98         let strategy = MediaTrackConstraintResolutionStrategy::BareToExact;
99         ResolvedAdvancedMediaTrackConstraints::from_iter(
100             self.into_iter()
101                 .map(|constraint_set| constraint_set.into_resolved(strategy)),
102         )
103     }
104 }
105 
106 impl ResolvedAdvancedMediaTrackConstraints {
to_sanitized( &self, supported_constraints: &MediaTrackSupportedConstraints, ) -> SanitizedAdvancedMediaTrackConstraints107     pub fn to_sanitized(
108         &self,
109         supported_constraints: &MediaTrackSupportedConstraints,
110     ) -> SanitizedAdvancedMediaTrackConstraints {
111         self.clone().into_sanitized(supported_constraints)
112     }
113 
into_sanitized( self, supported_constraints: &MediaTrackSupportedConstraints, ) -> SanitizedAdvancedMediaTrackConstraints114     pub fn into_sanitized(
115         self,
116         supported_constraints: &MediaTrackSupportedConstraints,
117     ) -> SanitizedAdvancedMediaTrackConstraints {
118         SanitizedAdvancedMediaTrackConstraints::from_iter(
119             self.into_iter()
120                 .map(|constraint_set| constraint_set.into_sanitized(supported_constraints))
121                 .filter(|constraint_set| !constraint_set.is_empty()),
122         )
123     }
124 }
125 
126 #[cfg(feature = "serde")]
127 #[cfg(test)]
128 mod serde_tests {
129     use crate::{property::all::name::*, MediaTrackConstraintSet};
130 
131     use super::*;
132 
133     #[test]
serialize_default()134     fn serialize_default() {
135         let advanced = AdvancedMediaTrackConstraints::default();
136         let actual = serde_json::to_value(advanced).unwrap();
137         let expected = serde_json::json!([]);
138 
139         assert_eq!(actual, expected);
140     }
141 
142     #[test]
deserialize_default()143     fn deserialize_default() {
144         let json = serde_json::json!([]);
145         let actual: AdvancedMediaTrackConstraints = serde_json::from_value(json).unwrap();
146         let expected = AdvancedMediaTrackConstraints::default();
147 
148         assert_eq!(actual, expected);
149     }
150 
151     #[test]
serialize()152     fn serialize() {
153         let advanced =
154             AdvancedMediaTrackConstraints::new(vec![MediaTrackConstraintSet::from_iter([
155                 (&DEVICE_ID, "device-id".into()),
156                 (&AUTO_GAIN_CONTROL, true.into()),
157                 (&CHANNEL_COUNT, 2.into()),
158                 (&LATENCY, 0.123.into()),
159             ])]);
160         let actual = serde_json::to_value(advanced).unwrap();
161         let expected = serde_json::json!([
162             {
163                 "deviceId": "device-id".to_owned(),
164                 "autoGainControl": true,
165                 "channelCount": 2,
166                 "latency": 0.123,
167             }
168         ]);
169 
170         assert_eq!(actual, expected);
171     }
172 
173     #[test]
deserialize()174     fn deserialize() {
175         let json = serde_json::json!([
176             {
177                 "deviceId": "device-id".to_owned(),
178                 "autoGainControl": true,
179                 "channelCount": 2,
180                 "latency": 0.123,
181             }
182         ]);
183         let actual: AdvancedMediaTrackConstraints = serde_json::from_value(json).unwrap();
184         let expected =
185             AdvancedMediaTrackConstraints::new(vec![MediaTrackConstraintSet::from_iter([
186                 (&DEVICE_ID, "device-id".into()),
187                 (&AUTO_GAIN_CONTROL, true.into()),
188                 (&CHANNEL_COUNT, 2.into()),
189                 (&LATENCY, 0.123.into()),
190             ])]);
191 
192         assert_eq!(actual, expected);
193     }
194 }
195