webrtc_constraints/
macros.rs

1//! Convenience macros.
2
3/// A convenience macro for defining settings.
4#[macro_export]
5macro_rules! settings {
6    [
7        $($p:expr => $c:expr),* $(,)?
8    ] => {
9        <$crate::MediaTrackSettings as std::iter::FromIterator<_>>::from_iter([
10            $(($p, $c.into())),*
11        ])
12    };
13}
14
15pub use settings;
16
17/// A convenience macro for defining individual "value" constraints.
18#[macro_export]
19macro_rules! value_constraint {
20    ($($p:ident: $c:expr),+ $(,)?) => {
21        $crate::ValueConstraint::Constraint(
22            #[allow(clippy::needless_update)]
23            $crate::ResolvedValueConstraint {
24                $($p: Some($c)),+,
25                ..Default::default()
26            }
27        )
28    };
29    ($c:expr) => {
30        $crate::ValueConstraint::Bare($c)
31    };
32}
33
34pub use value_constraint;
35
36/// A convenience macro for defining individual "value range" constraints.
37#[macro_export]
38macro_rules! value_range_constraint {
39    {$($p:ident: $c:expr),+ $(,)?} => {
40        $crate::ValueRangeConstraint::Constraint(
41            $crate::ResolvedValueRangeConstraint {
42                $($p: Some($c)),+,
43                ..Default::default()
44            }
45        )
46    };
47    ($c:expr) => {
48        $crate::ValueRangeConstraint::Bare($c)
49    };
50}
51
52pub use value_range_constraint;
53
54/// A convenience macro for defining individual "value sequence" constraints.
55#[macro_export]
56macro_rules! value_sequence_constraint {
57    {$($p:ident: $c:expr),+ $(,)?} => {
58        $crate::ValueSequenceConstraint::Constraint(
59            $crate::ResolvedValueSequenceConstraint {
60                $($p: Some($c)),*,
61                ..Default::default()
62            }
63        )
64    };
65    ($c:expr) => {
66        $crate::ValueSequenceConstraint::Bare($c)
67    };
68}
69
70pub use value_sequence_constraint;
71
72/// A convenience macro for defining constraint sets.
73#[macro_export]
74macro_rules! constraint_set {
75    {
76        $($p:expr => $c:expr),* $(,)?
77    } => {
78        <$crate::MediaTrackConstraintSet as std::iter::FromIterator<_>>::from_iter([
79            $(($p, $c.into())),*
80        ])
81    };
82}
83
84pub use constraint_set;
85
86/// A convenience macro for defining "mandatory" constraints.
87#[macro_export]
88macro_rules! mandatory_constraints {
89    {
90        $($p:expr => $c:expr),* $(,)?
91    } => {
92        $crate::MandatoryMediaTrackConstraints::new(
93            constraint_set!{
94                $($p => $c),*
95            }
96        )
97    };
98}
99
100pub use mandatory_constraints;
101
102/// A convenience macro for defining "advanced" constraints.
103#[macro_export]
104macro_rules! advanced_constraints {
105    [
106        $({
107            $($p:expr => $c:expr),* $(,)?
108        }),* $(,)?
109    ] => {
110        <$crate::AdvancedMediaTrackConstraints as std::iter::FromIterator<_>>::from_iter([
111            $(constraint_set!{
112                $($p => $c),*
113            }),*
114        ])
115    };
116}
117
118pub use advanced_constraints;
119
120/// A convenience macro for defining constraints.
121#[macro_export]
122macro_rules! constraints {
123    [
124        mandatory: {$($mp:expr => $mc:expr),* $(,)?},
125        advanced: [$(
126            {$($ap:expr => $ac:expr),* $(,)?}
127        ),* $(,)?]
128    ] => {
129        $crate::MediaTrackConstraints {
130            mandatory: mandatory_constraints!($($mp => $mc),*),
131            advanced: advanced_constraints!($({ $($ap => $ac),* }),*)
132        }
133    };
134}
135
136pub use constraints;
137
138#[allow(unused_macros)]
139#[cfg(test)]
140macro_rules! test_serde_symmetry {
141    (subject: $s:expr, json: $j:expr) => {
142        // Serialize:
143        {
144            let actual = serde_json::to_value($s.clone()).unwrap();
145            let expected = $j.clone();
146
147            assert_eq!(actual, expected);
148        }
149
150        // Deserialize:
151        {
152            let actual: Subject = serde_json::from_value($j).unwrap();
153            let expected = $s;
154
155            assert_eq!(actual, expected);
156        }
157    };
158}
159
160#[allow(unused_imports)]
161#[cfg(test)]
162pub(crate) use test_serde_symmetry;
163
164#[cfg(test)]
165mod tests {
166    use crate::{
167        property::all::name::*, AdvancedMediaTrackConstraints, FacingMode,
168        MandatoryMediaTrackConstraints, MediaTrackConstraintSet, MediaTrackConstraints,
169        MediaTrackSettings, ResolvedValueConstraint, ResolvedValueRangeConstraint,
170        ResolvedValueSequenceConstraint, ValueConstraint, ValueRangeConstraint,
171        ValueSequenceConstraint,
172    };
173
174    #[test]
175    fn settings() {
176        let actual: MediaTrackSettings = settings![
177            &DEVICE_ID => "foobar".to_owned(),
178            &FRAME_RATE => 30.0,
179            &HEIGHT => 1080,
180            &FACING_MODE => FacingMode::user(),
181        ];
182
183        let expected = <MediaTrackSettings as std::iter::FromIterator<_>>::from_iter([
184            (&DEVICE_ID, "foobar".to_owned().into()),
185            (&FRAME_RATE, 30.0.into()),
186            (&HEIGHT, 1080.into()),
187            (&FACING_MODE, FacingMode::user().into()),
188        ]);
189
190        assert_eq!(actual, expected);
191    }
192
193    mod constraint {
194        use super::*;
195
196        #[test]
197        fn value() {
198            // Bare:
199
200            let actual = value_constraint!("foobar".to_owned());
201
202            let expected = ValueConstraint::Bare("foobar".to_owned());
203
204            assert_eq!(actual, expected);
205
206            // Constraint:
207
208            let actual = value_constraint! {
209                exact: "foobar".to_owned(),
210                ideal: "bazblee".to_owned(),
211            };
212
213            let expected = ValueConstraint::Constraint(
214                ResolvedValueConstraint::default()
215                    .exact("foobar".to_owned())
216                    .ideal("bazblee".to_owned()),
217            );
218
219            assert_eq!(actual, expected);
220        }
221
222        #[test]
223        fn range() {
224            // Bare:
225
226            let actual = value_range_constraint!(42);
227
228            let expected = ValueRangeConstraint::Bare(42);
229
230            assert_eq!(actual, expected);
231
232            // Constraint:
233
234            let actual = value_range_constraint! {
235                min: 30.0,
236                max: 60.0,
237            };
238
239            let expected = ValueRangeConstraint::Constraint(
240                ResolvedValueRangeConstraint::default().min(30.0).max(60.0),
241            );
242
243            assert_eq!(actual, expected);
244        }
245
246        #[test]
247        fn sequence() {
248            // Bare:
249
250            let actual = value_sequence_constraint![vec![FacingMode::user()]];
251
252            let expected = ValueSequenceConstraint::Bare(vec![FacingMode::user()]);
253
254            assert_eq!(actual, expected);
255
256            // Constraint:
257
258            let actual = value_sequence_constraint! {
259                ideal: vec![FacingMode::user()],
260            };
261
262            let expected = ValueSequenceConstraint::Constraint(
263                ResolvedValueSequenceConstraint::default().ideal(vec![FacingMode::user()]),
264            );
265
266            assert_eq!(actual, expected);
267        }
268    }
269
270    #[test]
271    fn mandatory_constraints() {
272        let actual = mandatory_constraints! {
273            &DEVICE_ID => value_constraint! {
274                exact: "foobar".to_owned(),
275                ideal: "bazblee".to_owned(),
276            },
277            &FRAME_RATE => value_range_constraint! {
278                min: 30.0,
279                max: 60.0,
280            },
281            &FACING_MODE => value_sequence_constraint! {
282                exact: vec![FacingMode::user(), FacingMode::environment()]
283            },
284        };
285
286        let expected = <MandatoryMediaTrackConstraints as std::iter::FromIterator<_>>::from_iter([
287            (
288                &DEVICE_ID,
289                ValueConstraint::Constraint(
290                    ResolvedValueConstraint::default()
291                        .exact("foobar".to_owned())
292                        .ideal("bazblee".to_owned()),
293                )
294                .into(),
295            ),
296            (
297                &FRAME_RATE,
298                ValueRangeConstraint::Constraint(
299                    ResolvedValueRangeConstraint::default().min(30.0).max(60.0),
300                )
301                .into(),
302            ),
303            (
304                &FACING_MODE,
305                ValueSequenceConstraint::Constraint(
306                    ResolvedValueSequenceConstraint::default()
307                        .exact(vec![FacingMode::user(), FacingMode::environment()]),
308                )
309                .into(),
310            ),
311        ]);
312
313        assert_eq!(actual, expected);
314    }
315
316    #[test]
317    fn advanced_constraints() {
318        let actual = advanced_constraints! [
319            {
320                &DEVICE_ID => value_constraint! {
321                    exact: "foobar".to_owned(),
322                    ideal: "bazblee".to_owned(),
323                },
324            },
325            {
326                &FRAME_RATE => value_range_constraint! {
327                    min: 30.0,
328                    max: 60.0,
329                },
330            },
331            {
332                &FACING_MODE => value_sequence_constraint! {
333                    exact: vec![FacingMode::user(), FacingMode::environment()]
334                },
335            },
336        ];
337
338        let expected = <AdvancedMediaTrackConstraints as std::iter::FromIterator<_>>::from_iter([
339            <MediaTrackConstraintSet as std::iter::FromIterator<_>>::from_iter([(
340                &DEVICE_ID,
341                ResolvedValueConstraint::default()
342                    .exact("foobar".to_owned())
343                    .ideal("bazblee".to_owned())
344                    .into(),
345            )]),
346            <MediaTrackConstraintSet as std::iter::FromIterator<_>>::from_iter([(
347                &FRAME_RATE,
348                ResolvedValueRangeConstraint::default()
349                    .min(30.0)
350                    .max(60.0)
351                    .into(),
352            )]),
353            <MediaTrackConstraintSet as std::iter::FromIterator<_>>::from_iter([(
354                &FACING_MODE,
355                ResolvedValueSequenceConstraint::default()
356                    .exact(vec![FacingMode::user(), FacingMode::environment()])
357                    .into(),
358            )]),
359        ]);
360
361        assert_eq!(actual, expected);
362    }
363
364    #[test]
365    fn constraints() {
366        let actual: MediaTrackConstraints = constraints!(
367            mandatory: {
368                &DEVICE_ID => value_constraint! {
369                    exact: "foobar".to_owned(),
370                    ideal: "bazblee".to_owned(),
371                },
372                &FRAME_RATE => value_range_constraint! {
373                    min: 30.0,
374                    max: 60.0,
375                },
376                &FACING_MODE => value_sequence_constraint! {
377                    exact: vec![FacingMode::user(), FacingMode::environment()]
378                },
379            },
380            advanced: [
381                {
382                    &DEVICE_ID => value_constraint! {
383                        exact: "foobar".to_owned(),
384                        ideal: "bazblee".to_owned(),
385                    },
386                },
387                {
388                    &FRAME_RATE => value_range_constraint! {
389                        min: 30.0,
390                        max: 60.0,
391                    },
392                },
393                {
394                    &FACING_MODE => value_sequence_constraint! {
395                        exact: vec![FacingMode::user(), FacingMode::environment()]
396                    },
397                },
398            ]
399        );
400
401        let expected = MediaTrackConstraints {
402            mandatory: <MandatoryMediaTrackConstraints as std::iter::FromIterator<_>>::from_iter([
403                (
404                    &DEVICE_ID,
405                    ResolvedValueConstraint::default()
406                        .exact("foobar".to_owned())
407                        .ideal("bazblee".to_owned())
408                        .into(),
409                ),
410                (
411                    &FRAME_RATE,
412                    ResolvedValueRangeConstraint::default()
413                        .min(30.0)
414                        .max(60.0)
415                        .into(),
416                ),
417                (
418                    &FACING_MODE,
419                    ResolvedValueSequenceConstraint::default()
420                        .exact(vec![FacingMode::user(), FacingMode::environment()])
421                        .into(),
422                ),
423            ]),
424            advanced: <AdvancedMediaTrackConstraints as std::iter::FromIterator<_>>::from_iter([
425                <MediaTrackConstraintSet as std::iter::FromIterator<_>>::from_iter([(
426                    &DEVICE_ID,
427                    ResolvedValueConstraint::default()
428                        .exact("foobar".to_owned())
429                        .ideal("bazblee".to_owned())
430                        .into(),
431                )]),
432                <MediaTrackConstraintSet as std::iter::FromIterator<_>>::from_iter([(
433                    &FRAME_RATE,
434                    ResolvedValueRangeConstraint::default()
435                        .min(30.0)
436                        .max(60.0)
437                        .into(),
438                )]),
439                <MediaTrackConstraintSet as std::iter::FromIterator<_>>::from_iter([(
440                    &FACING_MODE,
441                    ResolvedValueSequenceConstraint::default()
442                        .exact(vec![FacingMode::user(), FacingMode::environment()])
443                        .into(),
444                )]),
445            ]),
446        };
447
448        assert_eq!(actual, expected);
449    }
450}