webrtc_constraints/constraints/
track.rs1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4use crate::{
5 constraint::SanitizedMediaTrackConstraint, MediaTrackConstraint,
6 MediaTrackSupportedConstraints, ResolvedMediaTrackConstraint,
7};
8
9use super::{
10 advanced::GenericAdvancedMediaTrackConstraints,
11 mandatory::GenericMandatoryMediaTrackConstraints,
12};
13
14pub type BoolOrMediaTrackConstraints = GenericBoolOrMediaTrackConstraints<MediaTrackConstraint>;
18
19#[derive(Debug, Clone, Eq, PartialEq)]
38#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
39#[cfg_attr(feature = "serde", serde(untagged))]
40pub enum GenericBoolOrMediaTrackConstraints<T> {
41 Bool(bool),
43 Constraints(GenericMediaTrackConstraints<T>),
45}
46
47impl<T> GenericBoolOrMediaTrackConstraints<T>
48where
49 T: Clone,
50{
51 pub fn to_constraints(&self) -> Option<GenericMediaTrackConstraints<T>> {
52 self.clone().into_constraints()
53 }
54
55 pub fn into_constraints(self) -> Option<GenericMediaTrackConstraints<T>> {
56 match self {
57 Self::Bool(false) => None,
58 Self::Bool(true) => Some(GenericMediaTrackConstraints::default()),
59 Self::Constraints(constraints) => Some(constraints),
60 }
61 }
62}
63
64impl<T> Default for GenericBoolOrMediaTrackConstraints<T> {
65 fn default() -> Self {
66 Self::Bool(false)
67 }
68}
69
70impl<T> From<bool> for GenericBoolOrMediaTrackConstraints<T> {
71 fn from(flag: bool) -> Self {
72 Self::Bool(flag)
73 }
74}
75
76impl<T> From<GenericMediaTrackConstraints<T>> for GenericBoolOrMediaTrackConstraints<T> {
77 fn from(constraints: GenericMediaTrackConstraints<T>) -> Self {
78 Self::Constraints(constraints)
79 }
80}
81
82pub type MediaTrackConstraints = GenericMediaTrackConstraints<MediaTrackConstraint>;
84
85pub type ResolvedMediaTrackConstraints = GenericMediaTrackConstraints<ResolvedMediaTrackConstraint>;
87
88pub type SanitizedMediaTrackConstraints =
90 GenericMediaTrackConstraints<SanitizedMediaTrackConstraint>;
91
92#[derive(Debug, Clone, Eq, PartialEq)]
103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
104pub struct GenericMediaTrackConstraints<T> {
105 #[cfg_attr(feature = "serde", serde(flatten))]
109 pub mandatory: GenericMandatoryMediaTrackConstraints<T>,
110
111 #[cfg_attr(
115 feature = "serde",
116 serde(default = "Default::default"),
117 serde(skip_serializing_if = "should_skip_advanced")
118 )]
119 pub advanced: GenericAdvancedMediaTrackConstraints<T>,
120}
121
122#[cfg(feature = "serde")]
123fn should_skip_advanced<T>(advanced: &GenericAdvancedMediaTrackConstraints<T>) -> bool {
124 advanced.is_empty()
125}
126
127impl<T> Default for GenericMediaTrackConstraints<T> {
128 fn default() -> Self {
129 Self {
130 mandatory: Default::default(),
131 advanced: Default::default(),
132 }
133 }
134}
135
136impl MediaTrackConstraints {
137 pub fn to_resolved(&self) -> ResolvedMediaTrackConstraints {
138 self.clone().into_resolved()
139 }
140
141 pub fn into_resolved(self) -> ResolvedMediaTrackConstraints {
142 let Self {
143 mandatory,
144 advanced,
145 } = self;
146 ResolvedMediaTrackConstraints {
147 mandatory: mandatory.into_resolved(),
148 advanced: advanced.into_resolved(),
149 }
150 }
151}
152
153impl ResolvedMediaTrackConstraints {
154 pub fn to_sanitized(
155 &self,
156 supported_constraints: &MediaTrackSupportedConstraints,
157 ) -> SanitizedMediaTrackConstraints {
158 self.clone().into_sanitized(supported_constraints)
159 }
160
161 pub fn into_sanitized(
162 self,
163 supported_constraints: &MediaTrackSupportedConstraints,
164 ) -> SanitizedMediaTrackConstraints {
165 let mandatory = self.mandatory.into_sanitized(supported_constraints);
166 let advanced = self.advanced.into_sanitized(supported_constraints);
167 SanitizedMediaTrackConstraints {
168 mandatory,
169 advanced,
170 }
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use std::iter::FromIterator;
177
178 use crate::{
179 constraints::mandatory::MandatoryMediaTrackConstraints, property::all::name::*,
180 AdvancedMediaTrackConstraints, ResolvedAdvancedMediaTrackConstraints,
181 ResolvedMandatoryMediaTrackConstraints, ResolvedValueConstraint,
182 };
183
184 use super::*;
185
186 type Subject = BoolOrMediaTrackConstraints;
187
188 #[test]
189 fn default() {
190 let actual = Subject::default();
191 let expected = Subject::Bool(false);
192
193 assert_eq!(actual, expected);
194 }
195
196 mod from {
197 use super::*;
198
199 #[test]
200 fn bool() {
201 for value in [false, true] {
202 let actual = Subject::from(value);
203 let expected = Subject::Bool(value);
204
205 assert_eq!(actual, expected);
206 }
207 }
208
209 #[test]
210 fn constraints() {
211 let constraints = GenericMediaTrackConstraints {
212 mandatory: MandatoryMediaTrackConstraints::from_iter([(
213 &DEVICE_ID,
214 "microphone".into(),
215 )]),
216 advanced: AdvancedMediaTrackConstraints::new(vec![]),
217 };
218
219 let actual = Subject::from(constraints.clone());
220 let expected = Subject::Constraints(constraints);
221
222 assert_eq!(actual, expected);
223 }
224 }
225
226 mod to_constraints {
227 use super::*;
228
229 #[test]
230 fn bool_false() {
231 let subject = Subject::Bool(false);
232
233 let actual = subject.to_constraints();
234 let expected = None;
235
236 assert_eq!(actual, expected);
237 }
238
239 #[test]
240 fn bool_true() {
241 let subject = Subject::Bool(true);
242
243 let actual = subject.to_constraints();
244 let expected = Some(GenericMediaTrackConstraints::default());
245
246 assert_eq!(actual, expected);
247 }
248
249 #[test]
250 fn constraints() {
251 let constraints = GenericMediaTrackConstraints {
252 mandatory: MandatoryMediaTrackConstraints::from_iter([(
253 &DEVICE_ID,
254 "microphone".into(),
255 )]),
256 advanced: AdvancedMediaTrackConstraints::new(vec![]),
257 };
258
259 let subject = Subject::Constraints(constraints.clone());
260
261 let actual = subject.to_constraints();
262 let expected = Some(constraints);
263
264 assert_eq!(actual, expected);
265 }
266 }
267
268 #[test]
269 fn to_resolved() {
270 let subject = MediaTrackConstraints {
271 mandatory: MandatoryMediaTrackConstraints::from_iter([(
272 &DEVICE_ID,
273 "microphone".into(),
274 )]),
275 advanced: AdvancedMediaTrackConstraints::new(vec![]),
276 };
277
278 let actual = subject.to_resolved();
279 let expected = ResolvedMediaTrackConstraints {
280 mandatory: ResolvedMandatoryMediaTrackConstraints::from_iter([(
281 &DEVICE_ID,
282 ResolvedValueConstraint::default()
283 .ideal("microphone".to_owned())
284 .into(),
285 )]),
286 advanced: ResolvedAdvancedMediaTrackConstraints::new(vec![]),
287 };
288
289 assert_eq!(actual, expected);
290 }
291}
292
293#[cfg(feature = "serde")]
294#[cfg(test)]
295mod serde_tests {
296 use std::iter::FromIterator;
297
298 use crate::{
299 constraints::mandatory::MandatoryMediaTrackConstraints, macros::test_serde_symmetry,
300 property::all::name::*, AdvancedMediaTrackConstraints, MediaTrackConstraintSet,
301 };
302
303 use super::*;
304
305 type Subject = MediaTrackConstraints;
306
307 #[test]
308 fn default() {
309 let subject = Subject::default();
310 let json = serde_json::json!({});
311
312 test_serde_symmetry!(subject: subject, json: json);
313 }
314
315 #[test]
316 fn customized() {
317 let subject = Subject {
318 mandatory: MandatoryMediaTrackConstraints::from_iter([(
319 &DEVICE_ID,
320 "microphone".into(),
321 )]),
322 advanced: AdvancedMediaTrackConstraints::new(vec![
323 MediaTrackConstraintSet::from_iter([
324 (&AUTO_GAIN_CONTROL, true.into()),
325 (&CHANNEL_COUNT, 2.into()),
326 ]),
327 MediaTrackConstraintSet::from_iter([(&LATENCY, 0.123.into())]),
328 ]),
329 };
330 let json = serde_json::json!({
331 "deviceId": "microphone",
332 "advanced": [
333 {
334 "autoGainControl": true,
335 "channelCount": 2,
336 },
337 {
338 "latency": 0.123,
339 },
340 ]
341 });
342
343 test_serde_symmetry!(subject: subject, json: json);
344 }
345}