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