1#[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#[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#[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#[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#[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#[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#[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#[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 {
144 let actual = serde_json::to_value($s.clone()).unwrap();
145 let expected = $j.clone();
146
147 assert_eq!(actual, expected);
148 }
149
150 {
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 let actual = value_constraint!("foobar".to_owned());
201
202 let expected = ValueConstraint::Bare("foobar".to_owned());
203
204 assert_eq!(actual, expected);
205
206 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 let actual = value_range_constraint!(42);
227
228 let expected = ValueRangeConstraint::Bare(42);
229
230 assert_eq!(actual, expected);
231
232 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 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 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}