xref: /webrtc/constraints/src/macros.rs (revision 86143b07)
1 //! Convenience macros.
2 
3 /// A convenience macro for defining settings.
4 #[macro_export]
5 macro_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 
15 pub use settings;
16 
17 /// A convenience macro for defining individual "value" constraints.
18 #[macro_export]
19 macro_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 
34 pub use value_constraint;
35 
36 /// A convenience macro for defining individual "value range" constraints.
37 #[macro_export]
38 macro_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 
52 pub use value_range_constraint;
53 
54 /// A convenience macro for defining individual "value sequence" constraints.
55 #[macro_export]
56 macro_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 
70 pub use value_sequence_constraint;
71 
72 /// A convenience macro for defining constraint sets.
73 #[macro_export]
74 macro_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 
84 pub use constraint_set;
85 
86 /// A convenience macro for defining "mandatory" constraints.
87 #[macro_export]
88 macro_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 
100 pub use mandatory_constraints;
101 
102 /// A convenience macro for defining "advanced" constraints.
103 #[macro_export]
104 macro_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 
118 pub use advanced_constraints;
119 
120 /// A convenience macro for defining constraints.
121 #[macro_export]
122 macro_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 
136 pub use constraints;
137 
138 #[allow(unused_macros)]
139 #[cfg(test)]
140 macro_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)]
162 pub(crate) use test_serde_symmetry;
163 
164 #[cfg(test)]
165 mod 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]
settings()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]
value()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]
range()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]
sequence()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]
mandatory_constraints()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]
advanced_constraints()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]
constraints()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 }
451