gstreamer/
caps_serde.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::fmt;
4
5use serde::{
6    de,
7    de::{Deserialize, Deserializer, EnumAccess, SeqAccess, VariantAccess, Visitor},
8    ser::{Serialize, SerializeSeq, SerializeTuple, Serializer},
9};
10
11use crate::{Caps, CapsFeatures, CapsFeaturesRef, CapsRef, Structure, StructureRef};
12
13enum CapsVariantKinds {
14    Any,
15    Empty,
16    Some,
17}
18
19const CAPS_VARIANT_ANY_ID: u32 = 0;
20const CAPS_VARIANT_ANY_STR: &str = "Any";
21const CAPS_VARIANT_EMPTY_ID: u32 = 1;
22const CAPS_VARIANT_EMPTY_STR: &str = "Empty";
23const CAPS_VARIANT_SOME_ID: u32 = 2;
24const CAPS_VARIANT_SOME_STR: &str = "Some";
25
26const CAPS_VARIANT_NAMES: &[&str] = &[
27    CAPS_VARIANT_ANY_STR,
28    CAPS_VARIANT_EMPTY_STR,
29    CAPS_VARIANT_SOME_STR,
30];
31
32struct CapsItemSe<'a>(&'a StructureRef, Option<&'a CapsFeaturesRef>);
33impl Serialize for CapsItemSe<'_> {
34    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
35        let mut tup = serializer.serialize_tuple(2)?;
36        tup.serialize_element(self.0)?;
37        tup.serialize_element(&self.1)?;
38        tup.end()
39    }
40}
41
42struct CapsForIterSe<'a>(&'a CapsRef);
43impl Serialize for CapsForIterSe<'_> {
44    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
45        let iter = self.0.iter_with_features();
46        let size = iter.size_hint().0;
47        if size > 0 {
48            let mut seq = serializer.serialize_seq(Some(size))?;
49            for (structure, features) in iter {
50                let features = if !features.is_any()
51                    && features.is_equal(crate::CAPS_FEATURES_MEMORY_SYSTEM_MEMORY.as_ref())
52                {
53                    None
54                } else {
55                    Some(features)
56                };
57                seq.serialize_element(&CapsItemSe(structure, features))?;
58            }
59            seq.end()
60        } else {
61            let seq = serializer.serialize_seq(None)?;
62            seq.end()
63        }
64    }
65}
66
67impl Serialize for CapsRef {
68    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
69        if self.is_any() {
70            serializer.serialize_unit_variant(
71                stringify!(Caps),
72                CAPS_VARIANT_ANY_ID,
73                CAPS_VARIANT_ANY_STR,
74            )
75        } else if self.is_empty() {
76            serializer.serialize_unit_variant(
77                stringify!(Caps),
78                CAPS_VARIANT_EMPTY_ID,
79                CAPS_VARIANT_EMPTY_STR,
80            )
81        } else {
82            serializer.serialize_newtype_variant(
83                stringify!(Caps),
84                CAPS_VARIANT_SOME_ID,
85                CAPS_VARIANT_SOME_STR,
86                &CapsForIterSe(self),
87            )
88        }
89    }
90}
91
92impl Serialize for Caps {
93    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
94        <CapsRef as Serialize>::serialize(self.as_ref(), serializer)
95    }
96}
97
98struct CapsItemDe(Structure, Option<CapsFeatures>);
99
100struct CapsItemVisitor;
101impl<'de> Visitor<'de> for CapsItemVisitor {
102    type Value = CapsItemDe;
103
104    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
105        formatter.write_str("a tuple `(Structure, Option<CapsFeature>)`")
106    }
107
108    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
109        let structure = seq
110            .next_element::<Structure>()?
111            .ok_or_else(|| de::Error::custom("Expected a `Structure` for `Caps` item"))?;
112        let features_option = seq.next_element::<Option<CapsFeatures>>()?.ok_or_else(|| {
113            de::Error::custom("Expected an `Option<CapsFeature>` for `Caps` item")
114        })?;
115
116        Ok(CapsItemDe(structure, features_option))
117    }
118}
119
120impl<'de> Deserialize<'de> for CapsItemDe {
121    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<CapsItemDe, D::Error> {
122        skip_assert_initialized!();
123        deserializer.deserialize_tuple(2, CapsItemVisitor)
124    }
125}
126
127struct CapsSome(Caps);
128
129struct CapsSomeVisitor;
130impl<'de> Visitor<'de> for CapsSomeVisitor {
131    type Value = CapsSome;
132
133    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
134        formatter.write_str("a sequence of `(Structure, Option<CapsFeature>)`")
135    }
136
137    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
138        let mut caps = Caps::new_empty();
139        {
140            let caps = caps.get_mut().unwrap();
141            while let Some(caps_item) = seq.next_element::<CapsItemDe>()? {
142                caps.append_structure_full(caps_item.0, caps_item.1);
143            }
144        }
145        Ok(CapsSome(caps))
146    }
147}
148
149impl<'de> Deserialize<'de> for CapsSome {
150    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<CapsSome, D::Error> {
151        skip_assert_initialized!();
152        deserializer.deserialize_seq(CapsSomeVisitor)
153    }
154}
155
156struct CapsVariantKindsVisitor;
157impl Visitor<'_> for CapsVariantKindsVisitor {
158    type Value = CapsVariantKinds;
159
160    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
161        formatter.write_str("a Caps variant kind (`Any`, `None` or `Some`)")
162    }
163
164    fn visit_u32<E: de::Error>(self, value: u32) -> Result<Self::Value, E> {
165        match value {
166            CAPS_VARIANT_ANY_ID => Ok(CapsVariantKinds::Any),
167            CAPS_VARIANT_EMPTY_ID => Ok(CapsVariantKinds::Empty),
168            CAPS_VARIANT_SOME_ID => Ok(CapsVariantKinds::Some),
169            _ => Err(de::Error::invalid_value(
170                de::Unexpected::Unsigned(u64::from(value)),
171                &self,
172            )),
173        }
174    }
175
176    fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
177        match value {
178            CAPS_VARIANT_ANY_STR => Ok(CapsVariantKinds::Any),
179            CAPS_VARIANT_EMPTY_STR => Ok(CapsVariantKinds::Empty),
180            CAPS_VARIANT_SOME_STR => Ok(CapsVariantKinds::Some),
181            _ => Err(de::Error::unknown_variant(value, CAPS_VARIANT_NAMES)),
182        }
183    }
184}
185
186impl<'de> Deserialize<'de> for CapsVariantKinds {
187    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
188        skip_assert_initialized!();
189        deserializer.deserialize_identifier(CapsVariantKindsVisitor)
190    }
191}
192
193struct CapsVisitor;
194impl<'de> Visitor<'de> for CapsVisitor {
195    type Value = Caps;
196
197    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
198        formatter.write_str("a Caps enum (`Any`, `None` or `Some()`)")
199    }
200
201    fn visit_enum<A: EnumAccess<'de>>(self, data: A) -> Result<Self::Value, A::Error> {
202        let res = match data.variant()? {
203            (CapsVariantKinds::Any, _v) => Caps::new_any(),
204            (CapsVariantKinds::Empty, _v) => Caps::new_empty(),
205            (CapsVariantKinds::Some, v) => v
206                .newtype_variant::<CapsSome>()
207                .map(|caps_some| caps_some.0)?,
208        };
209
210        Ok(res)
211    }
212}
213
214impl<'de> Deserialize<'de> for Caps {
215    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
216        skip_assert_initialized!();
217        deserializer.deserialize_enum(stringify!(Caps), CAPS_VARIANT_NAMES, CapsVisitor)
218    }
219}
220
221#[cfg(test)]
222mod tests {
223    use crate::{Array, Caps, CapsFeatures, Fraction};
224
225    #[test]
226    fn test_serialize() {
227        crate::init().unwrap();
228
229        let caps = Caps::builder("foo/bar")
230            .field("int", 12)
231            .field("bool", true)
232            .field("string", "bla")
233            .field("fraction", Fraction::new(1, 2))
234            .field("array", Array::new([1, 2]))
235            .build();
236
237        let pretty_config = ron::ser::PrettyConfig::new().new_line("".to_string());
238
239        let res = ron::ser::to_string_pretty(&caps, pretty_config);
240        assert_eq!(
241            Ok(concat!(
242                "r#Some([",
243                "    ((\"foo/bar\", [",
244                "        (\"int\", \"i32\", 12),",
245                "        (\"bool\", \"bool\", true),",
246                "        (\"string\", \"String\", Some(\"bla\")),",
247                "        (\"fraction\", \"Fraction\", (1, 2)),",
248                "        (\"array\", \"Array\", [",
249                "            (\"i32\", 1),",
250                "            (\"i32\", 2),",
251                "        ]),",
252                "    ]), None),",
253                "])"
254            )
255            .to_owned()),
256            res,
257        );
258
259        let caps = Caps::builder("foo/bar")
260            .field("int", 12)
261            .field("bool", true)
262            .field("string", "bla")
263            .field("fraction", Fraction::new(1, 2))
264            .field("array", Array::new([1, 2]))
265            .features(["foo:bar", "foo:baz"])
266            .build();
267
268        let pretty_config = ron::ser::PrettyConfig::new().new_line("".to_string());
269
270        let res = ron::ser::to_string_pretty(&caps, pretty_config);
271        assert_eq!(
272            Ok(concat!(
273                "r#Some([",
274                "    ((\"foo/bar\", [",
275                "        (\"int\", \"i32\", 12),",
276                "        (\"bool\", \"bool\", true),",
277                "        (\"string\", \"String\", Some(\"bla\")),",
278                "        (\"fraction\", \"Fraction\", (1, 2)),",
279                "        (\"array\", \"Array\", [",
280                "            (\"i32\", 1),",
281                "            (\"i32\", 2),",
282                "        ]),",
283                "    ]), Some(r#Some([",
284                "        \"foo:bar\",",
285                "        \"foo:baz\",",
286                "    ]))),",
287                "])"
288            )
289            .to_owned()),
290            res,
291        );
292
293        let caps = Caps::builder("foo/bar")
294            .field("int", 12)
295            .field("bool", true)
296            .field("string", "bla")
297            .field("fraction", Fraction::new(1, 2))
298            .field("array", Array::new([1, 2]))
299            .any_features()
300            .build();
301
302        let pretty_config = ron::ser::PrettyConfig::new().new_line("".to_string());
303
304        let res = ron::ser::to_string_pretty(&caps, pretty_config.clone());
305        assert_eq!(
306            Ok(concat!(
307                "r#Some([",
308                "    ((\"foo/bar\", [",
309                "        (\"int\", \"i32\", 12),",
310                "        (\"bool\", \"bool\", true),",
311                "        (\"string\", \"String\", Some(\"bla\")),",
312                "        (\"fraction\", \"Fraction\", (1, 2)),",
313                "        (\"array\", \"Array\", [",
314                "            (\"i32\", 1),",
315                "            (\"i32\", 2),",
316                "        ]),",
317                "    ]), Some(Any)),",
318                "])"
319            )
320            .to_owned()),
321            res,
322        );
323
324        let caps_any = Caps::new_any();
325        let res = ron::ser::to_string_pretty(&caps_any, pretty_config.clone());
326        assert_eq!(Ok("Any".to_owned()), res);
327
328        let caps_empty = Caps::new_empty();
329        let res = ron::ser::to_string_pretty(&caps_empty, pretty_config);
330        assert_eq!(Ok("Empty".to_owned()), res);
331    }
332
333    #[test]
334    fn test_deserialize() {
335        use crate::Structure;
336
337        crate::init().unwrap();
338
339        let caps_ron = "Any";
340        let caps: Caps = ron::de::from_str(caps_ron).unwrap();
341        assert!(caps.is_any());
342
343        let caps_ron = "Empty";
344        let caps: Caps = ron::de::from_str(caps_ron).unwrap();
345        assert!(caps.is_empty());
346
347        let caps_ron = r#"
348            Some([
349                (
350                    ("foo/bar", [
351                        ("int", "i32", 12),
352                        ("bool", "bool", true),
353                        ("string", "String", Some("bla")),
354                        ("fraction", "Fraction", (1, 2)),
355                        ("array", "Array", [
356                            ("i32", 1),
357                            ("i32", 2),
358                        ]),
359                    ]),
360                    None,
361                ),
362            ])"#;
363        let caps: Caps = ron::de::from_str(caps_ron).unwrap();
364        let s = caps.structure(0).unwrap();
365        assert_eq!(
366            s,
367            Structure::builder("foo/bar",)
368                .field("int", 12)
369                .field("bool", true)
370                .field("string", "bla")
371                .field("fraction", Fraction::new(1, 2))
372                .field("array", Array::new([1, 2]))
373                .build()
374                .as_ref()
375        );
376
377        let caps_ron = r#"
378            Some([
379                (
380                    ("foo/bar", [
381                        ("int", "i32", 12),
382                        ("bool", "bool", true),
383                        ("string", "String", None),
384                        ("fraction", "Fraction", (1, 2)),
385                        ("array", "Array", [
386                            ("i32", 1),
387                            ("i32", 2),
388                        ]),
389                    ]),
390                    Some(Some(["foo:bar", "foo:baz"])),
391                ),
392            ])"#;
393        let caps: Caps = ron::de::from_str(caps_ron).unwrap();
394        let s = caps.structure(0).unwrap();
395        let str_none: Option<&str> = None;
396        assert_eq!(
397            s,
398            Structure::builder("foo/bar",)
399                .field("int", 12)
400                .field("bool", true)
401                .field("string", str_none)
402                .field("fraction", Fraction::new(1, 2))
403                .field("array", Array::new([1, 2]))
404                .build()
405                .as_ref()
406        );
407        let f = caps.features(0).unwrap();
408        assert!(f.is_equal(CapsFeatures::new(["foo:bar", "foo:baz"]).as_ref()));
409
410        let caps_ron = r#"
411            Some([
412                (
413                    ("foo/bar", [
414                        ("int", "i32", 12),
415                        ("bool", "bool", true),
416                        ("string", "String", Some("bla")),
417                        ("fraction", "Fraction", (1, 2)),
418                        ("array", "Array", [
419                            ("i32", 1),
420                            ("i32", 2),
421                        ]),
422                    ]),
423                    Some(Any),
424                ),
425            ])"#;
426        let caps: Caps = ron::de::from_str(caps_ron).unwrap();
427        let s = caps.structure(0).unwrap();
428        assert_eq!(
429            s,
430            Structure::builder("foo/bar",)
431                .field("int", 12)
432                .field("bool", true)
433                .field("string", "bla")
434                .field("fraction", Fraction::new(1, 2))
435                .field("array", Array::new([1, 2]))
436                .build()
437                .as_ref()
438        );
439        let f = caps.features(0).unwrap();
440        assert!(f.is_any());
441    }
442
443    #[test]
444    fn test_serde_roundtrip() {
445        crate::init().unwrap();
446
447        let caps = Caps::new_any();
448        let caps_ser = ron::ser::to_string(&caps).unwrap();
449        let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
450        assert!(caps_de.is_any());
451
452        let caps = Caps::new_empty();
453        let caps_ser = ron::ser::to_string(&caps).unwrap();
454        let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
455        assert!(caps_de.is_empty());
456
457        let caps = Caps::builder("foo/bar")
458            .field("int", 12)
459            .field("bool", true)
460            .field("string", "bla")
461            .field("fraction", Fraction::new(1, 2))
462            .field("array", Array::new([1, 2]))
463            .build();
464        let caps_ser = ron::ser::to_string(&caps).unwrap();
465        let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
466        assert!(caps_de.is_strictly_equal(&caps));
467
468        let caps = Caps::builder("foo/bar")
469            .field("int", 12)
470            .field("bool", true)
471            .field("string", "bla")
472            .field("fraction", Fraction::new(1, 2))
473            .field("array", Array::new([1, 2]))
474            .features(["foo:bar", "foo:baz"])
475            .build();
476        let caps_ser = ron::ser::to_string(&caps).unwrap();
477        let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
478        assert!(caps_de.is_strictly_equal(&caps));
479
480        let caps = Caps::builder("foo/bar")
481            .field("int", 12)
482            .field("bool", true)
483            .field("string", "bla")
484            .field("fraction", Fraction::new(1, 2))
485            .field("array", Array::new([1, 2]))
486            .any_features()
487            .build();
488        let caps_ser = ron::ser::to_string(&caps).unwrap();
489        let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
490        assert!(caps_de.is_strictly_equal(&caps));
491    }
492}