webrtc_constraints/constraints/
mandatory.rs

1use std::{
2    iter::FromIterator,
3    ops::{Deref, DerefMut},
4};
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use crate::{
10    MediaTrackConstraint, MediaTrackConstraintResolutionStrategy, MediaTrackProperty,
11    MediaTrackSupportedConstraints, ResolvedMediaTrackConstraint, SanitizedMediaTrackConstraint,
12};
13
14use super::constraint_set::GenericMediaTrackConstraintSet;
15
16/// The list of mandatory constraint sets for a [`MediaStreamTrack`][media_stream_track] object.
17///
18/// # W3C Spec Compliance
19///
20/// Corresponds to [`ResolvedMediaTrackConstraints.mandatory`][media_track_constraints_mandatory]
21/// from the W3C ["Media Capture and Streams"][media_capture_and_streams_spec] spec.
22///
23/// Unlike `ResolvedMandatoryMediaTrackConstraints` this type may contain constraints with bare values.
24///
25/// [media_stream_track]: https://www.w3.org/TR/mediacapture-streams/#dom-mediastreamtrack
26/// [media_track_constraints_mandatory]: https://www.w3.org/TR/mediacapture-streams/#dom-mediatrackconstraints-mandatory
27/// [media_capture_and_streams_spec]: https://www.w3.org/TR/mediacapture-streams/
28pub type MandatoryMediaTrackConstraints =
29    GenericMandatoryMediaTrackConstraints<MediaTrackConstraint>;
30
31/// The list of mandatory constraint sets for a [`MediaStreamTrack`][media_stream_track] object.
32///
33/// # W3C Spec Compliance
34///
35/// Corresponds to [`ResolvedMediaTrackConstraintSet`][media_track_constraints_mandatory]
36/// from the W3C ["Media Capture and Streams"][media_capture_and_streams_spec] spec.
37///
38/// Unlike `MandatoryMediaTrackConstraints` this type does not contain constraints
39/// with bare values, but has them resolved to full constraints instead.
40///
41/// [media_stream_track]: https://www.w3.org/TR/mediacapture-streams/#dom-mediastreamtrack
42/// [media_track_constraints_mandatory]: https://www.w3.org/TR/mediacapture-streams/#dom-mediatrackconstraints-mandatory
43/// [media_capture_and_streams_spec]: https://www.w3.org/TR/mediacapture-streams/
44pub type ResolvedMandatoryMediaTrackConstraints =
45    GenericMandatoryMediaTrackConstraints<ResolvedMediaTrackConstraint>;
46
47/// Set of mandatory media track constraints that contains only non-empty constraints.
48pub type SanitizedMandatoryMediaTrackConstraints =
49    GenericMandatoryMediaTrackConstraints<SanitizedMediaTrackConstraint>;
50
51/// The set of constraints for a [`MediaStreamTrack`][media_stream_track] object.
52///
53/// # W3C Spec Compliance
54///
55/// Corresponds to [`ResolvedMediaTrackConstraintSet`][media_track_constraint_set]
56/// from the W3C ["Media Capture and Streams"][media_capture_and_streams_spec] spec.
57///
58/// [media_stream_track]: https://www.w3.org/TR/mediacapture-streams/#dom-mediastreamtrack
59/// [media_track_constraint_set]: https://www.w3.org/TR/mediacapture-streams/#dom-mediatrackconstraintset
60/// [media_capture_and_streams_spec]: https://www.w3.org/TR/mediacapture-streams/
61#[derive(Debug, Clone, Eq, PartialEq)]
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63#[cfg_attr(feature = "serde", serde(transparent))]
64pub struct GenericMandatoryMediaTrackConstraints<T>(GenericMediaTrackConstraintSet<T>);
65
66impl<T> GenericMandatoryMediaTrackConstraints<T> {
67    pub fn new(constraints: GenericMediaTrackConstraintSet<T>) -> Self {
68        Self(constraints)
69    }
70
71    pub fn into_inner(self) -> GenericMediaTrackConstraintSet<T> {
72        self.0
73    }
74}
75
76impl GenericMandatoryMediaTrackConstraints<ResolvedMediaTrackConstraint> {
77    pub fn basic(&self) -> GenericMediaTrackConstraintSet<ResolvedMediaTrackConstraint> {
78        self.basic_or_required(false)
79    }
80
81    pub fn required(&self) -> GenericMediaTrackConstraintSet<ResolvedMediaTrackConstraint> {
82        self.basic_or_required(true)
83    }
84
85    fn basic_or_required(
86        &self,
87        required: bool,
88    ) -> GenericMediaTrackConstraintSet<ResolvedMediaTrackConstraint> {
89        GenericMediaTrackConstraintSet::new(
90            self.0
91                .iter()
92                .filter_map(|(property, constraint)| {
93                    if constraint.is_required() == required {
94                        Some((property.clone(), constraint.clone()))
95                    } else {
96                        None
97                    }
98                })
99                .collect(),
100        )
101    }
102}
103
104impl<T> Deref for GenericMandatoryMediaTrackConstraints<T> {
105    type Target = GenericMediaTrackConstraintSet<T>;
106
107    fn deref(&self) -> &Self::Target {
108        &self.0
109    }
110}
111
112impl<T> DerefMut for GenericMandatoryMediaTrackConstraints<T> {
113    fn deref_mut(&mut self) -> &mut Self::Target {
114        &mut self.0
115    }
116}
117
118impl<T> Default for GenericMandatoryMediaTrackConstraints<T> {
119    fn default() -> Self {
120        Self(Default::default())
121    }
122}
123
124impl<T, U> FromIterator<(U, T)> for GenericMandatoryMediaTrackConstraints<T>
125where
126    U: Into<MediaTrackProperty>,
127{
128    fn from_iter<I>(iter: I) -> Self
129    where
130        I: IntoIterator<Item = (U, T)>,
131    {
132        Self::new(iter.into_iter().map(|(k, v)| (k.into(), v)).collect())
133    }
134}
135
136impl<T> IntoIterator for GenericMandatoryMediaTrackConstraints<T> {
137    type Item = (MediaTrackProperty, T);
138    type IntoIter = indexmap::map::IntoIter<MediaTrackProperty, T>;
139
140    fn into_iter(self) -> Self::IntoIter {
141        self.0.into_iter()
142    }
143}
144
145impl MandatoryMediaTrackConstraints {
146    pub fn to_resolved(&self) -> ResolvedMandatoryMediaTrackConstraints {
147        self.clone().into_resolved()
148    }
149
150    pub fn into_resolved(self) -> ResolvedMandatoryMediaTrackConstraints {
151        let strategy = MediaTrackConstraintResolutionStrategy::BareToIdeal;
152        ResolvedMandatoryMediaTrackConstraints::new(self.0.into_resolved(strategy))
153    }
154}
155
156impl ResolvedMandatoryMediaTrackConstraints {
157    pub fn to_sanitized(
158        &self,
159        supported_constraints: &MediaTrackSupportedConstraints,
160    ) -> SanitizedMandatoryMediaTrackConstraints {
161        self.clone().into_sanitized(supported_constraints)
162    }
163
164    pub fn into_sanitized(
165        self,
166        supported_constraints: &MediaTrackSupportedConstraints,
167    ) -> SanitizedMandatoryMediaTrackConstraints {
168        SanitizedMandatoryMediaTrackConstraints::new(self.0.into_sanitized(supported_constraints))
169    }
170}
171
172#[cfg(test)]
173mod tests {
174    use crate::{
175        property::all::name::*, ResolvedMediaTrackConstraintSet, ResolvedValueConstraint,
176        ResolvedValueRangeConstraint,
177    };
178
179    use super::*;
180
181    #[test]
182    fn basic() {
183        let mandatory = ResolvedMandatoryMediaTrackConstraints::new(
184            ResolvedMediaTrackConstraintSet::from_iter([
185                (
186                    &DEVICE_ID,
187                    ResolvedValueConstraint::default()
188                        .exact("device-id".to_owned())
189                        .into(),
190                ),
191                (
192                    &AUTO_GAIN_CONTROL,
193                    ResolvedValueConstraint::default().ideal(true).into(),
194                ),
195                (
196                    &CHANNEL_COUNT,
197                    ResolvedValueRangeConstraint::default()
198                        .exact(2)
199                        .ideal(3)
200                        .into(),
201                ),
202            ]),
203        );
204
205        let actual = mandatory.basic();
206        let expected = ResolvedMediaTrackConstraintSet::from_iter([(
207            &AUTO_GAIN_CONTROL,
208            ResolvedValueConstraint::default().ideal(true).into(),
209        )]);
210
211        assert_eq!(actual, expected);
212    }
213
214    #[test]
215    fn required() {
216        let mandatory = ResolvedMandatoryMediaTrackConstraints::new(
217            ResolvedMediaTrackConstraintSet::from_iter([
218                (
219                    &DEVICE_ID,
220                    ResolvedValueConstraint::default()
221                        .exact("device-id".to_owned())
222                        .into(),
223                ),
224                (
225                    &AUTO_GAIN_CONTROL,
226                    ResolvedValueConstraint::default().ideal(true).into(),
227                ),
228                (
229                    &CHANNEL_COUNT,
230                    ResolvedValueRangeConstraint::default()
231                        .exact(2)
232                        .ideal(3)
233                        .into(),
234                ),
235            ]),
236        );
237
238        let actual = mandatory.required();
239        let expected = ResolvedMediaTrackConstraintSet::from_iter([
240            (
241                &DEVICE_ID,
242                ResolvedValueConstraint::default()
243                    .exact("device-id".to_owned())
244                    .into(),
245            ),
246            (
247                &CHANNEL_COUNT,
248                ResolvedValueRangeConstraint::default()
249                    .exact(2)
250                    .ideal(3)
251                    .into(),
252            ),
253        ]);
254
255        assert_eq!(actual, expected);
256    }
257}
258
259#[cfg(feature = "serde")]
260#[cfg(test)]
261mod serde_tests {
262    use crate::{property::all::name::*, MediaTrackConstraintSet};
263
264    use super::*;
265
266    #[test]
267    fn serialize_default() {
268        let mandatory = MandatoryMediaTrackConstraints::default();
269        let actual = serde_json::to_value(mandatory).unwrap();
270        let expected = serde_json::json!({});
271
272        assert_eq!(actual, expected);
273    }
274
275    #[test]
276    fn deserialize_default() {
277        let json = serde_json::json!({});
278        let actual: MandatoryMediaTrackConstraints = serde_json::from_value(json).unwrap();
279        let expected = MandatoryMediaTrackConstraints::default();
280
281        assert_eq!(actual, expected);
282    }
283
284    #[test]
285    fn serialize() {
286        let mandatory = MandatoryMediaTrackConstraints::new(MediaTrackConstraintSet::from_iter([
287            (&DEVICE_ID, "device-id".into()),
288            (&AUTO_GAIN_CONTROL, true.into()),
289            (&CHANNEL_COUNT, 2.into()),
290            (&LATENCY, 0.123.into()),
291        ]));
292        let actual = serde_json::to_value(mandatory).unwrap();
293        let expected = serde_json::json!(
294            {
295                "deviceId": "device-id".to_owned(),
296                "autoGainControl": true,
297                "channelCount": 2,
298                "latency": 0.123,
299            }
300        );
301
302        assert_eq!(actual, expected);
303    }
304
305    #[test]
306    fn deserialize() {
307        let json = serde_json::json!(
308            {
309                "deviceId": "device-id".to_owned(),
310                "autoGainControl": true,
311                "channelCount": 2,
312                "latency": 0.123,
313            }
314        );
315        let actual: MandatoryMediaTrackConstraints = serde_json::from_value(json).unwrap();
316        let expected = MandatoryMediaTrackConstraints::new(MediaTrackConstraintSet::from_iter([
317            (&DEVICE_ID, "device-id".into()),
318            (&AUTO_GAIN_CONTROL, true.into()),
319            (&CHANNEL_COUNT, 2.into()),
320            (&LATENCY, 0.123.into()),
321        ]));
322
323        assert_eq!(actual, expected);
324    }
325}