diff --git a/gstreamer/src/caps.rs b/gstreamer/src/caps.rs index a6e2ed860..9789dff5a 100644 --- a/gstreamer/src/caps.rs +++ b/gstreamer/src/caps.rs @@ -402,6 +402,67 @@ impl Builder { } } +#[cfg(feature = "ser_de")] +pub(crate) mod serde { + use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; + use serde::ser::{Serialize, Serializer, SerializeSeq}; + + use std::fmt; + + use Caps; + use CapsRef; + use Structure; + + impl<'a> Serialize for CapsRef { + fn serialize(&self, serializer: S) -> Result { + let iter = self.iter(); + let size = iter.size_hint().0; + if size > 0 { + let mut seq = serializer.serialize_seq(Some(size))?; + for structure in iter { + seq.serialize_element(structure)?; + } + seq.end() + } else { + let seq = serializer.serialize_seq(None)?; + seq.end() + } + } + } + + impl<'a> Serialize for Caps { + fn serialize(&self, serializer: S) -> Result { + self.as_ref().serialize(serializer) + } + } + + struct CapsVisitor; + impl<'de> Visitor<'de> for CapsVisitor { + type Value = Caps; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence of `Structure`s") + } + + fn visit_seq>(self, mut seq: A) -> Result { + let mut caps = Caps::new_empty(); + { + let caps = caps.get_mut().unwrap(); + while let Some(structure) = seq.next_element::()? { + caps.append_structure(structure); + } + } + Ok(caps) + } + } + + impl<'de> Deserialize<'de> for Caps { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_seq(CapsVisitor) + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -459,4 +520,83 @@ mod tests { "foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >" ); } + + #[cfg(feature = "ser_de")] + #[test] + fn test_serialize() { + extern crate ron; + + ::init().unwrap(); + + let caps = Caps::builder("foo/bar") + .field("int", &12) + .field("bool", &true) + .field("string", &"bla") + .field("fraction", &Fraction::new(1, 2)) + .field("array", &Array::new(&[&1, &2])) + .build(); + + // don't use newlines + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let res = ron::ser::to_string_pretty(&caps, pretty_config); + assert_eq!( + Ok( + concat!( + "[", + " (\"foo/bar\", [", + " (\"int\", \"i32\", 12),", + " (\"bool\", \"bool\", true),", + " (\"string\", \"String\", \"bla\"),", + " (\"fraction\", \"Fraction\", (1, 2)),", + " (\"array\", \"Array\", [", + " (\"i32\", 1),", + " (\"i32\", 2),", + " ]),", + " ]),", + "]" + ) + .to_owned() + ), + res, + ); + } + + #[cfg(feature = "ser_de")] + #[test] + fn test_deserialize() { + extern crate ron; + + ::init().unwrap(); + + let caps_ron = r#" + [ + ("foo/bar", [ + ("int", "i32", 12), + ("bool", "bool", true), + ("string", "String", "bla"), + ("fraction", "Fraction", (1, 2)), + ("array", "Array", [ + ("i32", 1), + ("i32", 2), + ]), + ]), + ]"#; + let caps: Caps = ron::de::from_str(caps_ron).unwrap(); + let s = caps.get_structure(0).unwrap(); + assert_eq!( + s, + Structure::new( + "foo/bar", + &[ + ("int", &12), + ("bool", &true), + ("string", &"bla"), + ("fraction", &Fraction::new(1, 2)), + ("array", &Array::new(&[&1, &2])), + ], + ).as_ref() + ); + } }