diff --git a/gstreamer/Cargo.toml b/gstreamer/Cargo.toml index 1fed0b212..40da955f3 100644 --- a/gstreamer/Cargo.toml +++ b/gstreamer/Cargo.toml @@ -24,19 +24,26 @@ num-rational = { version = "0.2", default-features = false, features = [] } lazy_static = "1.0" futures-core-preview = { version = "0.2", optional = true } muldiv = "0.2" +serde = { version = "1.0", optional = true } +serde_derive = { version = "1.0", optional = true } [build-dependencies.rustdoc-stripper] version = "0.1" optional = true +[dev-dependencies] +ron = "0.2" +serde_json = "1.0" + [features] v1_10 = ["gstreamer-sys/v1_10"] v1_12 = ["gstreamer-sys/v1_12", "v1_10"] v1_14 = ["gstreamer-sys/v1_14", "v1_12"] embed-lgpl-docs = ["rustdoc-stripper"] purge-lgpl-docs = ["rustdoc-stripper"] -dox = ["gstreamer-sys/dox", "glib/dox", "futures"] +dox = ["gstreamer-sys/dox", "glib/dox", "futures", "ser_de"] futures = ["futures-core-preview"] +ser_de = ["serde", "serde_derive"] default-features = [] [badges] diff --git a/gstreamer/src/date_time.rs b/gstreamer/src/date_time.rs index 577aab7a2..0a394f0bf 100644 --- a/gstreamer/src/date_time.rs +++ b/gstreamer/src/date_time.rs @@ -18,3 +18,151 @@ impl fmt::Display for DateTime { ) } } + +#[cfg(feature = "ser_de")] +pub(crate) mod serde { + use serde::de::{Deserialize, Deserializer}; + use serde::ser::{Serialize, Serializer, SerializeStruct}; + use DateTime; + + impl<'a> Serialize for DateTime { + fn serialize(&self, serializer: S) -> Result { + let mut datetime = serializer.serialize_struct("DateTime", 8)?; + datetime.serialize_field("tz_offset", &self.get_time_zone_offset())?; + datetime.serialize_field("y", &self.get_year())?; + datetime.serialize_field("m", &self.get_month())?; + datetime.serialize_field("d", &self.get_day())?; + datetime.serialize_field("h", &self.get_hour())?; + datetime.serialize_field("mn", &self.get_minute())?; + datetime.serialize_field("s", &self.get_second())?; + datetime.serialize_field("us", &self.get_microsecond())?; + datetime.end() + } + } + + #[derive(Deserialize)] + struct DateTimeDe { + tz_offset: f32, + y: i32, + m: i32, + d: i32, + h: i32, + mn: i32, + s: i32, + us: i32, + } + + impl From for DateTime { + fn from(dt_de: DateTimeDe) -> Self { + ::DateTime::new( + dt_de.tz_offset, + dt_de.y, + dt_de.m, + dt_de.d, + dt_de.h, + dt_de.mn, + f64::from(dt_de.s) + f64::from(dt_de.us) / 1_000_000f64, + ) + } + } + + impl<'de> Deserialize<'de> for DateTime { + fn deserialize>(deserializer: D) -> Result { + DateTimeDe::deserialize(deserializer) + .and_then(|datetime_de| Ok(datetime_de.into())) + } + } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "ser_de")] + #[test] + fn test_serialize() { + extern crate ron; + extern crate serde_json; + + use DateTime; + + ::init().unwrap(); + + let datetime = DateTime::new(2f32, 2018, 5, 28, 16, 6, 42.841f64); + + // 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(&datetime, pretty_config); + assert_eq!( + Ok( + concat!( + "(", + " tz_offset: 2,", + " y: 2018,", + " m: 5,", + " d: 28,", + " h: 16,", + " mn: 6,", + " s: 42,", + " us: 841000,", + ")" + ) + .to_owned() + ), + res, + ); + + let res = serde_json::to_string(&datetime).unwrap(); + assert_eq!( + "{\"tz_offset\":2.0,\"y\":2018,\"m\":5,\"d\":28,\"h\":16,\"mn\":6,\"s\":42,\"us\":841000}" + .to_owned(), + res, + ); + } + + #[cfg(feature = "ser_de")] + #[test] + fn test_deserialize() { + extern crate ron; + extern crate serde_json; + + use DateTime; + + ::init().unwrap(); + + let datetime_ron = r#" + ( + tz_offset: 2, + y: 2018, + m: 5, + d: 28, + h: 16, + mn: 6, + s: 42, + us: 841000, + ) + "#; + let datetime: DateTime = ron::de::from_str(datetime_ron).unwrap(); + assert_eq!(datetime.get_time_zone_offset(), 2f32); + assert_eq!(datetime.get_year(), 2018); + assert_eq!(datetime.get_month(), 5); + assert_eq!(datetime.get_day(), 28); + assert_eq!(datetime.get_hour(), 16); + assert_eq!(datetime.get_minute(), 6); + assert_eq!(datetime.get_second(), 42); + assert_eq!(datetime.get_microsecond(), 841_000); + + let datetime_json = r#" + {"tz_offset":2.0,"y":2018,"m":5,"d":28,"h":16,"mn":6,"s":42,"us":841000} + "#; + let datetime: DateTime = serde_json::from_str(datetime_json).unwrap(); + assert_eq!(datetime.get_time_zone_offset(), 2f32); + assert_eq!(datetime.get_year(), 2018); + assert_eq!(datetime.get_month(), 5); + assert_eq!(datetime.get_day(), 28); + assert_eq!(datetime.get_hour(), 16); + assert_eq!(datetime.get_minute(), 6); + assert_eq!(datetime.get_second(), 42); + assert_eq!(datetime.get_microsecond(), 841_000); + } +} diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index 792a70256..6f43bef24 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -30,6 +30,12 @@ extern crate futures_core; extern crate muldiv; +#[cfg(feature = "ser_de")] +extern crate serde; +#[cfg(feature = "ser_de")] +#[macro_use] +extern crate serde_derive; + use glib::translate::{from_glib, from_glib_full}; macro_rules! assert_initialized_main_thread {