1 #[cfg(feature = "serde")]
2 use serde::{Deserialize, Serialize};
3 
4 /// A bare value or constraint specifying a sequence of accepted values.
5 ///
6 /// # W3C Spec Compliance
7 ///
8 /// There exists no direct corresponding type in the
9 /// W3C ["Media Capture and Streams"][media_capture_and_streams_spec] spec,
10 /// since the `BareOrValueConstraint<T>` type aims to be a generalization over
11 /// multiple types in the spec.
12 ///
13 /// | Rust                                     | W3C                                          |
14 /// | ---------------------------------------- | -------------------------------------------- |
15 /// | `BareOrValueSequenceConstraint<String>` | [`ConstrainDOMString`][constrain_dom_string] |
16 ///
17 /// [constrain_dom_string]: https://www.w3.org/TR/mediacapture-streams/#dom-constraindomstring
18 /// [media_capture_and_streams_spec]: https://www.w3.org/TR/mediacapture-streams/
19 #[derive(Debug, Clone, PartialEq)]
20 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21 #[cfg_attr(feature = "serde", serde(untagged))]
22 pub enum BareOrValueSequenceConstraint<T> {
23     Bare(Vec<T>),
24     Constraint(ValueSequenceConstraint<T>),
25 }
26 
27 impl<T> Default for BareOrValueSequenceConstraint<T> {
28     fn default() -> Self {
29         Self::Constraint(Default::default())
30     }
31 }
32 
33 impl<T> From<T> for BareOrValueSequenceConstraint<T> {
34     fn from(bare: T) -> Self {
35         Self::Bare(vec![bare])
36     }
37 }
38 
39 impl<T> From<Vec<T>> for BareOrValueSequenceConstraint<T> {
40     fn from(bare: Vec<T>) -> Self {
41         Self::Bare(bare)
42     }
43 }
44 
45 impl<T> From<ValueSequenceConstraint<T>> for BareOrValueSequenceConstraint<T> {
46     fn from(constraint: ValueSequenceConstraint<T>) -> Self {
47         Self::Constraint(constraint)
48     }
49 }
50 
51 /// A constraint specifying a sequence of accepted values.
52 ///
53 /// # W3C Spec Compliance
54 ///
55 /// There exists no direct corresponding type in the
56 /// W3C ["Media Capture and Streams"][media_capture_and_streams_spec] spec,
57 /// since the `BareOrValueSequenceConstraint<T>` type aims to be a
58 /// generalization over multiple types in the W3C spec:
59 ///
60 /// | Rust                              | W3C                                                               |
61 /// | --------------------------------- | ----------------------------------------------------------------- |
62 /// | `ValueSequenceConstraint<String>` | [`ConstrainDOMStringParameters`][constrain_dom_string_parameters] |
63 ///
64 /// [constrain_dom_string_parameters]: https://www.w3.org/TR/mediacapture-streams/#dom-constraindomstringparameters
65 /// [media_capture_and_streams_spec]: https://www.w3.org/TR/mediacapture-streams/
66 #[derive(Debug, Clone, PartialEq)]
67 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
68 #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
69 pub struct ValueSequenceConstraint<T> {
70     // See https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#constraindomstring
71     #[cfg_attr(
72         feature = "serde",
73         serde(skip_serializing_if = "core::option::Option::is_none")
74     )]
75     pub exact: Option<Vec<T>>,
76     #[cfg_attr(
77         feature = "serde",
78         serde(skip_serializing_if = "core::option::Option::is_none")
79     )]
80     pub ideal: Option<Vec<T>>,
81 }
82 
83 impl<T> ValueSequenceConstraint<T> {
84     pub fn exact_only(exact: Vec<T>) -> Self {
85         Self {
86             exact: Some(exact),
87             ideal: None,
88         }
89     }
90 
91     pub fn ideal_only(ideal: Vec<T>) -> Self {
92         Self {
93             exact: None,
94             ideal: Some(ideal),
95         }
96     }
97 
98     pub fn is_required(&self) -> bool {
99         self.exact.is_some()
100     }
101 }
102 
103 impl<T> Default for ValueSequenceConstraint<T> {
104     fn default() -> Self {
105         Self {
106             exact: None,
107             ideal: None,
108         }
109     }
110 }
111 
112 #[cfg(feature = "serde")]
113 #[cfg(test)]
114 mod serde_tests {
115     use crate::macros::test_serde_symmetry;
116 
117     use super::*;
118 
119     macro_rules! test_serde {
120         ($t:ty => {
121             values: [$($values:expr),*]
122         }) => {
123             type Subject = BareOrValueSequenceConstraint<$t>;
124 
125             #[test]
126             fn default() {
127                 let subject = Subject::default();
128                 let json = serde_json::json!({});
129 
130                 test_serde_symmetry!(subject: subject, json: json);
131             }
132 
133             #[test]
134             fn bare() {
135                 let subject = Subject::Bare(vec![$($values.to_owned()),*].into());
136                 let json = serde_json::json!([$($values),*]);
137 
138                 test_serde_symmetry!(subject: subject, json: json);
139             }
140 
141             #[test]
142             fn constraint() {
143                 let subject = Subject::Constraint(ValueSequenceConstraint::<String> {
144                     exact: Some(vec![$($values.to_owned()),*].into()),
145                     ideal: None,
146                 });
147                 let json = serde_json::json!({
148                     "exact": [$($values),*],
149                 });
150 
151                 test_serde_symmetry!(subject: subject, json: json);
152             }
153         };
154     }
155 
156     mod string {
157         use super::*;
158 
159         test_serde!(String => {
160             values: ["VALUE_0", "VALUE_1"]
161         });
162     }
163 }
164