diff --git a/gstreamer/src/buffer.rs b/gstreamer/src/buffer.rs index 023a0d732..fedb51deb 100644 --- a/gstreamer/src/buffer.rs +++ b/gstreamer/src/buffer.rs @@ -579,79 +579,6 @@ lazy_static! { *BUFFER_COPY_METADATA | ::BufferCopyFlags::MEMORY; } -#[cfg(feature = "ser_de")] -pub(crate) mod serde { - use serde::de::{Deserialize, Deserializer}; - use serde::ser::{Serialize, Serializer, SerializeStruct}; - use serde_bytes::{Bytes, ByteBuf}; - - use Buffer; - use BufferFlags; - use BufferRef; - use ClockTime; - - impl<'a> Serialize for BufferRef { - fn serialize(&self, serializer: S) -> Result { - let mut datetime = serializer.serialize_struct("Buffer", 6)?; - datetime.serialize_field("pts", &self.get_pts())?; - datetime.serialize_field("dts", &self.get_dts())?; - datetime.serialize_field("duration", &self.get_duration())?; - datetime.serialize_field("offset", &self.get_offset())?; - datetime.serialize_field("offset_end", &self.get_offset_end())?; - datetime.serialize_field("flags", &self.get_flags())?; - { - let data = self.map_readable().unwrap(); - datetime.serialize_field("buffer", &Bytes::new(data.as_slice()))?; - } - datetime.end() - } - } - - impl<'a> Serialize for Buffer { - fn serialize(&self, serializer: S) -> Result { - self.as_ref().serialize(serializer) - } - } - - #[derive(Deserialize)] - struct BufferDe { - pts: ClockTime, - dts: ClockTime, - duration: ClockTime, - offset: u64, - offset_end: u64, - flags: BufferFlags, - buffer: ByteBuf, - } - - impl From for Buffer { - fn from(mut buf_de: BufferDe) -> Self { - // Move the `ByteBuff`'s byte array into the `gst::Buffer` - // Are we really avoiding copies with that? - let drained_buffer: &mut Vec = buf_de.buffer.as_mut(); - let mut buffer = - Buffer::from_slice(drained_buffer.drain(..).collect::>()).unwrap(); - { - let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(buf_de.pts); - buffer.set_dts(buf_de.dts); - buffer.set_duration(buf_de.duration); - buffer.set_offset(buf_de.offset); - buffer.set_offset_end(buf_de.offset_end); - buffer.set_flags(buf_de.flags); - } - buffer - } - } - - impl<'de> Deserialize<'de> for Buffer { - fn deserialize>(deserializer: D) -> Result { - BufferDe::deserialize(deserializer) - .and_then(|buffer_de| Ok(buffer_de.into())) - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -723,165 +650,4 @@ mod tests { assert_eq!(data.as_slice(), vec![0, 2, 3, 4].as_slice()); } } - - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize() { - extern crate ron; - extern crate serde_json; - extern crate serde_pickle; - - use Buffer; - use BufferFlags; - - ::init().unwrap(); - - let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); - { - let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); - buffer.set_offset(3); - buffer.set_offset_end(4); - buffer.set_duration(5.into()); - buffer.set_flags(BufferFlags::LIVE | BufferFlags::LAST); - } - - // 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(&buffer, pretty_config); - assert_eq!( - Ok( - concat!( - "(", - " pts: Some(1),", - " dts: None,", - " duration: Some(5),", - " offset: 3,", - " offset_end: 4,", - " flags: (", - " bits: 1048592,", - " ),", - " buffer: \"AQIDBA==\",", - ")" - ) - .to_owned() - ), - res - ); - - let res = serde_json::to_string(&buffer).unwrap(); - assert_eq!( - concat!( - "{", - "\"pts\":1,", - "\"dts\":null,", - "\"duration\":5,", - "\"offset\":3,", - "\"offset_end\":4,", - "\"flags\":{\"bits\":1048592},", - "\"buffer\":[1,2,3,4]", - "}" - ) - .to_owned(), - res - ); - - let res = serde_pickle::to_vec(&buffer, true).unwrap(); - assert_eq!( - vec![ - 128, 3, 125, 40, 88, 3, 0, 0, 0, 112, 116, 115, 74, 1, 0, 0, 0, 88, 3, 0, 0, 0, 100, - 116, 115, 78, 88, 8, 0, 0, 0, 100, 117, 114, 97, 116, 105, 111, 110, 74, 5, 0, 0, 0, - 88, 6, 0, 0, 0, 111, 102, 102, 115, 101, 116, 74, 3, 0, 0, 0, 88, 10, 0, 0, 0, 111, - 102, 102, 115, 101, 116, 95, 101, 110, 100, 74, 4, 0, 0, 0, 88, 5, 0, 0, 0, 102, 108, - 97, 103, 115, 125, 40, 88, 4, 0, 0, 0, 98, 105, 116, 115, 74, 16, 0, 16, 0, 117, 88, - 6, 0, 0, 0, 98, 117, 102, 102, 101, 114, 67, - 4, 1, 2, 3, 4, 117, 46 - ], - res - ); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize() { - extern crate ron; - extern crate serde_json; - extern crate serde_pickle; - - use Buffer; - use BufferFlags; - - ::init().unwrap(); - - let buffer_ron = r#" - ( - pts: Some(1), - dts: None, - duration: Some(5), - offset: 3, - offset_end: 4, - flags: ( - bits: 1048592, - ), - buffer: "AQIDBA==", - ) - "#; - let buffer: Buffer = ron::de::from_str(buffer_ron).unwrap(); - assert_eq!(buffer.get_pts(), 1.into()); - assert_eq!(buffer.get_dts(), None.into()); - assert_eq!(buffer.get_offset(), 3); - assert_eq!(buffer.get_offset_end(), 4); - assert_eq!(buffer.get_duration(), 5.into()); - assert_eq!(buffer.get_flags(), BufferFlags::LIVE | BufferFlags::LAST); - { - let data = buffer.map_readable().unwrap(); - assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); - } - - let buffer_json = r#" - { - "pts":1, - "dts":null, - "duration":5, - "offset":3, - "offset_end":4, - "flags":{"bits":1048592}, - "buffer":[1,2,3,4] - } - "#; - let buffer: Buffer = serde_json::from_str(buffer_json).unwrap(); - assert_eq!(buffer.get_pts(), 1.into()); - assert_eq!(buffer.get_dts(), None.into()); - assert_eq!(buffer.get_offset(), 3); - assert_eq!(buffer.get_offset_end(), 4); - assert_eq!(buffer.get_duration(), 5.into()); - assert_eq!(buffer.get_flags(), BufferFlags::LIVE | BufferFlags::LAST); - { - let data = buffer.map_readable().unwrap(); - assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); - } - - let buffer_pickle: &[u8] = &[ - 128, 3, 125, 40, 88, 3, 0, 0, 0, 112, 116, 115, 74, 1, 0, 0, 0, 88, 3, 0, 0, 0, 100, - 116, 115, 78, 88, 8, 0, 0, 0, 100, 117, 114, 97, 116, 105, 111, 110, 74, 5, 0, 0, 0, - 88, 6, 0, 0, 0, 111, 102, 102, 115, 101, 116, 74, 3, 0, 0, 0, 88, 10, 0, 0, 0, 111, - 102, 102, 115, 101, 116, 95, 101, 110, 100, 74, 4, 0, 0, 0, 88, 5, 0, 0, 0, 102, 108, - 97, 103, 115, 125, 40, 88, 4, 0, 0, 0, 98, 105, 116, 115, 74, 16, 0, 16, 0, 117, 88, - 6, 0, 0, 0, 98, 117, 102, 102, 101, 114, 67, - 4, 1, 2, 3, 4, 117, 46 - ]; - let buffer: Buffer = serde_pickle::from_slice(buffer_pickle).unwrap(); - assert_eq!(buffer.get_pts(), 1.into()); - assert_eq!(buffer.get_dts(), None.into()); - assert_eq!(buffer.get_offset(), 3); - assert_eq!(buffer.get_offset_end(), 4); - assert_eq!(buffer.get_duration(), 5.into()); - assert_eq!(buffer.get_flags(), BufferFlags::LIVE | BufferFlags::LAST); - { - let data = buffer.map_readable().unwrap(); - assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); - } - } } diff --git a/gstreamer/src/buffer_serde.rs b/gstreamer/src/buffer_serde.rs new file mode 100644 index 000000000..5d4d90c5d --- /dev/null +++ b/gstreamer/src/buffer_serde.rs @@ -0,0 +1,231 @@ +// Copyright (C) 2018 François Laignel +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use serde::de::{Deserialize, Deserializer}; +use serde::ser::{Serialize, Serializer, SerializeStruct}; +use serde_bytes::{Bytes, ByteBuf}; + +use Buffer; +use BufferFlags; +use BufferRef; +use ClockTime; + +impl<'a> Serialize for BufferRef { + fn serialize(&self, serializer: S) -> Result { + let mut buffer = serializer.serialize_struct("Buffer", 6)?; + buffer.serialize_field("pts", &self.get_pts())?; + buffer.serialize_field("dts", &self.get_dts())?; + buffer.serialize_field("duration", &self.get_duration())?; + buffer.serialize_field("offset", &self.get_offset())?; + buffer.serialize_field("offset_end", &self.get_offset_end())?; + buffer.serialize_field("flags", &self.get_flags())?; + { + let data = self.map_readable().unwrap(); + buffer.serialize_field("buffer", &Bytes::new(data.as_slice()))?; + } + buffer.end() + } +} + +impl<'a> Serialize for Buffer { + fn serialize(&self, serializer: S) -> Result { + self.as_ref().serialize(serializer) + } +} + +#[derive(Deserialize)] +struct BufferDe { + pts: ClockTime, + dts: ClockTime, + duration: ClockTime, + offset: u64, + offset_end: u64, + flags: BufferFlags, + buffer: ByteBuf, +} + +impl From for Buffer { + fn from(mut buf_de: BufferDe) -> Self { + // Move the `ByteBuff`'s byte array into the `gst::Buffer` + // Are we really avoiding copies with that? + let drained_buffer: &mut Vec = buf_de.buffer.as_mut(); + let mut buffer = + Buffer::from_slice(drained_buffer.drain(..).collect::>()).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(buf_de.pts); + buffer.set_dts(buf_de.dts); + buffer.set_duration(buf_de.duration); + buffer.set_offset(buf_de.offset); + buffer.set_offset_end(buf_de.offset_end); + buffer.set_flags(buf_de.flags); + } + buffer + } +} + +impl<'de> Deserialize<'de> for Buffer { + fn deserialize>(deserializer: D) -> Result { + BufferDe::deserialize(deserializer) + .and_then(|buffer_de| Ok(buffer_de.into())) + } +} + +#[cfg(test)] +mod tests { + extern crate ron; + extern crate serde_json; + extern crate serde_pickle; + + use Buffer; + use BufferFlags; + + #[test] + fn test_serialize() { + ::init().unwrap(); + + let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(1.into()); + buffer.set_offset(3); + buffer.set_offset_end(4); + buffer.set_duration(5.into()); + buffer.set_flags(BufferFlags::LIVE | BufferFlags::LAST); + } + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let res = ron::ser::to_string_pretty(&buffer, pretty_config); + assert_eq!( + Ok( + concat!( + "(", + " pts: Some(1),", + " dts: None,", + " duration: Some(5),", + " offset: 3,", + " offset_end: 4,", + " flags: (", + " bits: 1048592,", + " ),", + " buffer: \"AQIDBA==\",", + ")" + ) + .to_owned() + ), + res + ); + + let res = serde_json::to_string(&buffer).unwrap(); + assert_eq!( + concat!( + "{", + "\"pts\":1,", + "\"dts\":null,", + "\"duration\":5,", + "\"offset\":3,", + "\"offset_end\":4,", + "\"flags\":{\"bits\":1048592},", + "\"buffer\":[1,2,3,4]", + "}" + ) + .to_owned(), + res + ); + + let res = serde_pickle::to_vec(&buffer, true).unwrap(); + assert_eq!( + vec![ + 128, 3, 125, 40, 88, 3, 0, 0, 0, 112, 116, 115, 74, 1, 0, 0, 0, 88, 3, 0, 0, 0, 100, + 116, 115, 78, 88, 8, 0, 0, 0, 100, 117, 114, 97, 116, 105, 111, 110, 74, 5, 0, 0, 0, + 88, 6, 0, 0, 0, 111, 102, 102, 115, 101, 116, 74, 3, 0, 0, 0, 88, 10, 0, 0, 0, 111, + 102, 102, 115, 101, 116, 95, 101, 110, 100, 74, 4, 0, 0, 0, 88, 5, 0, 0, 0, 102, 108, + 97, 103, 115, 125, 40, 88, 4, 0, 0, 0, 98, 105, 116, 115, 74, 16, 0, 16, 0, 117, 88, + 6, 0, 0, 0, 98, 117, 102, 102, 101, 114, 67, + 4, 1, 2, 3, 4, 117, 46 + ], + res + ); + } + + #[test] + fn test_deserialize() { + ::init().unwrap(); + + let buffer_ron = r#" + ( + pts: Some(1), + dts: None, + duration: Some(5), + offset: 3, + offset_end: 4, + flags: ( + bits: 1048592, + ), + buffer: "AQIDBA==", + ) + "#; + let buffer: Buffer = ron::de::from_str(buffer_ron).unwrap(); + assert_eq!(buffer.get_pts(), 1.into()); + assert_eq!(buffer.get_dts(), None.into()); + assert_eq!(buffer.get_offset(), 3); + assert_eq!(buffer.get_offset_end(), 4); + assert_eq!(buffer.get_duration(), 5.into()); + assert_eq!(buffer.get_flags(), BufferFlags::LIVE | BufferFlags::LAST); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + + let buffer_json = r#" + { + "pts":1, + "dts":null, + "duration":5, + "offset":3, + "offset_end":4, + "flags":{"bits":1048592}, + "buffer":[1,2,3,4] + } + "#; + let buffer: Buffer = serde_json::from_str(buffer_json).unwrap(); + assert_eq!(buffer.get_pts(), 1.into()); + assert_eq!(buffer.get_dts(), None.into()); + assert_eq!(buffer.get_offset(), 3); + assert_eq!(buffer.get_offset_end(), 4); + assert_eq!(buffer.get_duration(), 5.into()); + assert_eq!(buffer.get_flags(), BufferFlags::LIVE | BufferFlags::LAST); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + + let buffer_pickle: &[u8] = &[ + 128, 3, 125, 40, 88, 3, 0, 0, 0, 112, 116, 115, 74, 1, 0, 0, 0, 88, 3, 0, 0, 0, 100, + 116, 115, 78, 88, 8, 0, 0, 0, 100, 117, 114, 97, 116, 105, 111, 110, 74, 5, 0, 0, 0, + 88, 6, 0, 0, 0, 111, 102, 102, 115, 101, 116, 74, 3, 0, 0, 0, 88, 10, 0, 0, 0, 111, + 102, 102, 115, 101, 116, 95, 101, 110, 100, 74, 4, 0, 0, 0, 88, 5, 0, 0, 0, 102, 108, + 97, 103, 115, 125, 40, 88, 4, 0, 0, 0, 98, 105, 116, 115, 74, 16, 0, 16, 0, 117, 88, + 6, 0, 0, 0, 98, 117, 102, 102, 101, 114, 67, + 4, 1, 2, 3, 4, 117, 46 + ]; + let buffer: Buffer = serde_pickle::from_slice(buffer_pickle).unwrap(); + assert_eq!(buffer.get_pts(), 1.into()); + assert_eq!(buffer.get_dts(), None.into()); + assert_eq!(buffer.get_offset(), 3); + assert_eq!(buffer.get_offset_end(), 4); + assert_eq!(buffer.get_duration(), 5.into()); + assert_eq!(buffer.get_flags(), BufferFlags::LIVE | BufferFlags::LAST); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + } +} diff --git a/gstreamer/src/bufferlist.rs b/gstreamer/src/bufferlist.rs index f5e9599fc..af5efe7f3 100644 --- a/gstreamer/src/bufferlist.rs +++ b/gstreamer/src/bufferlist.rs @@ -193,195 +193,3 @@ impl<'a> DoubleEndedIterator for Iter<'a> { } impl<'a> ExactSizeIterator for Iter<'a> {} - -#[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 Buffer; - use BufferList; - use BufferListRef; - - impl Serialize for BufferListRef { - fn serialize(&self, serializer: S) -> Result { - let mut iter = self.iter(); - let (remaining, _) = iter.size_hint(); - if remaining > 0 { - let mut seq = serializer.serialize_seq(Some(remaining))?; - while let Some(ref buffer) = iter.next() { - seq.serialize_element(buffer)?; - } - seq.end() - } else { - let seq = serializer.serialize_seq(None)?; - seq.end() - } - } - } - - impl Serialize for BufferList { - fn serialize(&self, serializer: S) -> Result { - self.as_ref().serialize(serializer) - } - } - - struct BufferListVisitor; - impl<'de> Visitor<'de> for BufferListVisitor { - type Value = BufferList; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a sequence of Buffers") - } - - fn visit_seq>(self, mut seq: A) -> Result { - let mut buffer_list = BufferList::new(); - { - let buffer_list = buffer_list.get_mut().unwrap(); - while let Some(buffer) = seq.next_element::()? { - buffer_list.add(buffer); - } - } - Ok(buffer_list) - } - } - - impl<'de> Deserialize<'de> for BufferList { - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_seq(BufferListVisitor) - } - } -} - -#[cfg(test)] -mod tests { - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize() { - extern crate ron; - - use Buffer; - use BufferList; - - ::init().unwrap(); - - let mut buffer_list = BufferList::new(); - { - let buffer_list = buffer_list.get_mut().unwrap(); - - let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); - { - let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); - buffer.set_offset(0); - buffer.set_offset_end(4); - buffer.set_duration(4.into()); - } - buffer_list.add(buffer); - - let mut buffer = Buffer::from_slice(vec![5, 6]).unwrap(); - { - let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(5.into()); - buffer.set_offset(4); - buffer.set_offset_end(6); - buffer.set_duration(2.into()); - } - buffer_list.add(buffer); - } - - // 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(&buffer_list, pretty_config); - assert_eq!( - Ok( - concat!( - "[", - " (", - " pts: Some(1),", - " dts: None,", - " duration: Some(4),", - " offset: 0,", - " offset_end: 4,", - " flags: (", - " bits: 0,", - " ),", - " buffer: \"AQIDBA==\",", - " ),", - " (", - " pts: Some(5),", - " dts: None,", - " duration: Some(2),", - " offset: 4,", - " offset_end: 6,", - " flags: (", - " bits: 0,", - " ),", - " buffer: \"BQY=\",", - " ),", - "]" - ) - .to_owned() - ), - res, - ); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize() { - extern crate ron; - - use BufferList; - - ::init().unwrap(); - - let buffer_list_ron = r#" - [ - ( - pts: Some(1), - dts: None, - duration: Some(4), - offset: 0, - offset_end: 4, - flags: ( - bits: 0, - ), - buffer: "AQIDBA==", - ), - ( - pts: Some(5), - dts: None, - duration: Some(2), - offset: 4, - offset_end: 6, - flags: ( - bits: 0, - ), - buffer: "BQY=", - ), - ] - "#; - - let buffer_list: BufferList = ron::de::from_str(buffer_list_ron).unwrap(); - let mut iter = buffer_list.iter(); - let buffer = iter.next().unwrap(); - assert_eq!(buffer.get_pts(), 1.into()); - assert_eq!(buffer.get_dts(), None.into()); - { - let data = buffer.map_readable().unwrap(); - assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); - } - - let buffer = iter.next().unwrap(); - assert_eq!(buffer.get_pts(), 5.into()); - { - let data = buffer.map_readable().unwrap(); - assert_eq!(data.as_slice(), vec![5, 6].as_slice()); - } - } -} diff --git a/gstreamer/src/bufferlist_serde.rs b/gstreamer/src/bufferlist_serde.rs new file mode 100644 index 000000000..10dc16243 --- /dev/null +++ b/gstreamer/src/bufferlist_serde.rs @@ -0,0 +1,190 @@ +// Copyright (C) 2018 François Laignel +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; +use serde::ser::{Serialize, Serializer, SerializeSeq}; + +use std::fmt; + +use Buffer; +use BufferList; +use BufferListRef; + +impl Serialize for BufferListRef { + fn serialize(&self, serializer: S) -> Result { + let mut iter = self.iter(); + let (remaining, _) = iter.size_hint(); + if remaining > 0 { + let mut seq = serializer.serialize_seq(Some(remaining))?; + while let Some(ref buffer) = iter.next() { + seq.serialize_element(buffer)?; + } + seq.end() + } else { + let seq = serializer.serialize_seq(None)?; + seq.end() + } + } +} + +impl Serialize for BufferList { + fn serialize(&self, serializer: S) -> Result { + self.as_ref().serialize(serializer) + } +} + +struct BufferListVisitor; +impl<'de> Visitor<'de> for BufferListVisitor { + type Value = BufferList; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence of Buffers") + } + + fn visit_seq>(self, mut seq: A) -> Result { + let mut buffer_list = BufferList::new(); + { + let buffer_list = buffer_list.get_mut().unwrap(); + while let Some(buffer) = seq.next_element::()? { + buffer_list.add(buffer); + } + } + Ok(buffer_list) + } +} + +impl<'de> Deserialize<'de> for BufferList { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_seq(BufferListVisitor) + } +} + +#[cfg(test)] +mod tests { + extern crate ron; + + use BufferList; + + #[test] + fn test_serialize() { + use Buffer; + + ::init().unwrap(); + + let mut buffer_list = BufferList::new(); + { + let buffer_list = buffer_list.get_mut().unwrap(); + + let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(1.into()); + buffer.set_offset(0); + buffer.set_offset_end(4); + buffer.set_duration(4.into()); + } + buffer_list.add(buffer); + + let mut buffer = Buffer::from_slice(vec![5, 6]).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(5.into()); + buffer.set_offset(4); + buffer.set_offset_end(6); + buffer.set_duration(2.into()); + } + buffer_list.add(buffer); + } + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let res = ron::ser::to_string_pretty(&buffer_list, pretty_config); + assert_eq!( + Ok( + concat!( + "[", + " (", + " pts: Some(1),", + " dts: None,", + " duration: Some(4),", + " offset: 0,", + " offset_end: 4,", + " flags: (", + " bits: 0,", + " ),", + " buffer: \"AQIDBA==\",", + " ),", + " (", + " pts: Some(5),", + " dts: None,", + " duration: Some(2),", + " offset: 4,", + " offset_end: 6,", + " flags: (", + " bits: 0,", + " ),", + " buffer: \"BQY=\",", + " ),", + "]" + ) + .to_owned() + ), + res, + ); + } + + #[test] + fn test_deserialize() { + ::init().unwrap(); + + let buffer_list_ron = r#" + [ + ( + pts: Some(1), + dts: None, + duration: Some(4), + offset: 0, + offset_end: 4, + flags: ( + bits: 0, + ), + buffer: "AQIDBA==", + ), + ( + pts: Some(5), + dts: None, + duration: Some(2), + offset: 4, + offset_end: 6, + flags: ( + bits: 0, + ), + buffer: "BQY=", + ), + ] + "#; + + let buffer_list: BufferList = ron::de::from_str(buffer_list_ron).unwrap(); + let mut iter = buffer_list.iter(); + let buffer = iter.next().unwrap(); + assert_eq!(buffer.get_pts(), 1.into()); + assert_eq!(buffer.get_dts(), None.into()); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + + let buffer = iter.next().unwrap(); + assert_eq!(buffer.get_pts(), 5.into()); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![5, 6].as_slice()); + } + } +} diff --git a/gstreamer/src/caps.rs b/gstreamer/src/caps.rs index 9789dff5a..a6e2ed860 100644 --- a/gstreamer/src/caps.rs +++ b/gstreamer/src/caps.rs @@ -402,67 +402,6 @@ 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::*; @@ -520,83 +459,4 @@ 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() - ); - } } diff --git a/gstreamer/src/caps_serde.rs b/gstreamer/src/caps_serde.rs new file mode 100644 index 000000000..a297b6588 --- /dev/null +++ b/gstreamer/src/caps_serde.rs @@ -0,0 +1,148 @@ +// Copyright (C) 2018 François Laignel +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +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 { + extern crate ron; + + use Array; + use Caps; + use Fraction; + + #[test] + fn test_serialize() { + ::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(); + + 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, + ); + } + + #[test] + fn test_deserialize() { + use Structure; + + ::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() + ); + } +} diff --git a/gstreamer/src/clock_time.rs b/gstreamer/src/clock_time.rs index 24400e105..158393534 100644 --- a/gstreamer/src/clock_time.rs +++ b/gstreamer/src/clock_time.rs @@ -105,53 +105,6 @@ impl fmt::Display for ClockTime { } } -#[cfg(feature = "ser_de")] -pub(crate) mod serde { - use serde::de; - use serde::de::{Deserialize, Deserializer, Visitor}; - use serde::ser::{Serialize, Serializer}; - - use std::fmt; - - use ClockTime; - - impl<'a> Serialize for ClockTime { - fn serialize(&self, serializer: S) -> Result { - match self.nanoseconds() { - Some(ref value) => serializer.serialize_some(value), - None => serializer.serialize_none(), - } - } - } - - struct ClockTimeVisitor; - impl<'de> Visitor<'de> for ClockTimeVisitor { - type Value = ClockTime; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("an optional u64 ClockTime with ns precision") - } - - fn visit_some(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - u64::deserialize(deserializer) - .and_then(|value| Ok(ClockTime::from_nseconds(value))) - } - - fn visit_none(self) -> Result { - Ok(ClockTime(None)) - } - } - - impl<'de> Deserialize<'de> for ClockTime { - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_option(ClockTimeVisitor) - } - } -} - #[doc(hidden)] impl ToGlib for ClockTime { type GlibType = ffi::GstClockTime; @@ -203,74 +156,3 @@ impl glib::StaticType for ClockTime { ::static_type() } } - -#[cfg(test)] -mod tests { - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize() { - extern crate ron; - extern crate serde_json; - - use ClockTime; - - ::init().unwrap(); - - // Some - let clocktime = ClockTime::from_nseconds(42_123_456_789); - - // 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(&clocktime, pretty_config.clone()); - assert_eq!(Ok("Some(42123456789)".to_owned()), res); - - let res = serde_json::to_string(&clocktime).unwrap(); - assert_eq!("42123456789".to_owned(), res); - - // None - let clocktime = ClockTime(None); - - let res = ron::ser::to_string_pretty(&clocktime, pretty_config); - assert_eq!(Ok("None".to_owned()), res); - - let res = serde_json::to_string(&clocktime).unwrap(); - assert_eq!("null".to_owned(), res); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize() { - extern crate ron; - extern crate serde_json; - - use ClockTime; - - ::init().unwrap(); - - // Some - let clocktime_ron = "Some(42123456789)"; - let clocktime: ClockTime = ron::de::from_str(clocktime_ron).unwrap(); - assert_eq!(clocktime.seconds(), Some(42)); - assert_eq!(clocktime.mseconds(), Some(42_123)); - assert_eq!(clocktime.useconds(), Some(42_123_456)); - assert_eq!(clocktime.nseconds(), Some(42_123_456_789)); - - let clocktime_json = "42123456789"; - let clocktime: ClockTime = serde_json::from_str(clocktime_json).unwrap(); - assert_eq!(clocktime.seconds(), Some(42)); - assert_eq!(clocktime.mseconds(), Some(42_123)); - assert_eq!(clocktime.useconds(), Some(42_123_456)); - assert_eq!(clocktime.nseconds(), Some(42_123_456_789)); - - // None - let clocktime_ron = "None"; - let clocktime: ClockTime = ron::de::from_str(clocktime_ron).unwrap(); - assert_eq!(clocktime.nseconds(), None); - - let clocktime_json = "null"; - let clocktime: ClockTime = serde_json::from_str(clocktime_json).unwrap(); - assert_eq!(clocktime.nseconds(), None); - } -} diff --git a/gstreamer/src/clock_time_serde.rs b/gstreamer/src/clock_time_serde.rs new file mode 100644 index 000000000..996f2d2c1 --- /dev/null +++ b/gstreamer/src/clock_time_serde.rs @@ -0,0 +1,114 @@ +// Copyright (C) 2018 François Laignel +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use serde::de; +use serde::de::{Deserialize, Deserializer, Visitor}; +use serde::ser::{Serialize, Serializer}; + +use std::fmt; + +use ClockTime; + +impl<'a> Serialize for ClockTime { + fn serialize(&self, serializer: S) -> Result { + match self.nanoseconds() { + Some(ref value) => serializer.serialize_some(value), + None => serializer.serialize_none(), + } + } +} + +struct ClockTimeVisitor; +impl<'de> Visitor<'de> for ClockTimeVisitor { + type Value = ClockTime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an optional u64 ClockTime with ns precision") + } + + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + u64::deserialize(deserializer) + .and_then(|value| Ok(ClockTime::from_nseconds(value))) + } + + fn visit_none(self) -> Result { + Ok(ClockTime(None)) + } +} + +impl<'de> Deserialize<'de> for ClockTime { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_option(ClockTimeVisitor) + } +} + +#[cfg(test)] +mod tests { + extern crate ron; + extern crate serde_json; + + use ClockTime; + + #[test] + fn test_serialize() { + ::init().unwrap(); + + // Some + let clocktime = ClockTime::from_nseconds(42_123_456_789); + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let res = ron::ser::to_string_pretty(&clocktime, pretty_config.clone()); + assert_eq!(Ok("Some(42123456789)".to_owned()), res); + + let res = serde_json::to_string(&clocktime).unwrap(); + assert_eq!("42123456789".to_owned(), res); + + // None + let clocktime = ClockTime(None); + + let res = ron::ser::to_string_pretty(&clocktime, pretty_config); + assert_eq!(Ok("None".to_owned()), res); + + let res = serde_json::to_string(&clocktime).unwrap(); + assert_eq!("null".to_owned(), res); + } + + #[test] + fn test_deserialize() { + ::init().unwrap(); + + // Some + let clocktime_ron = "Some(42123456789)"; + let clocktime: ClockTime = ron::de::from_str(clocktime_ron).unwrap(); + assert_eq!(clocktime.seconds(), Some(42)); + assert_eq!(clocktime.mseconds(), Some(42_123)); + assert_eq!(clocktime.useconds(), Some(42_123_456)); + assert_eq!(clocktime.nseconds(), Some(42_123_456_789)); + + let clocktime_json = "42123456789"; + let clocktime: ClockTime = serde_json::from_str(clocktime_json).unwrap(); + assert_eq!(clocktime.seconds(), Some(42)); + assert_eq!(clocktime.mseconds(), Some(42_123)); + assert_eq!(clocktime.useconds(), Some(42_123_456)); + assert_eq!(clocktime.nseconds(), Some(42_123_456_789)); + + // None + let clocktime_ron = "None"; + let clocktime: ClockTime = ron::de::from_str(clocktime_ron).unwrap(); + assert_eq!(clocktime.nseconds(), None); + + let clocktime_json = "null"; + let clocktime: ClockTime = serde_json::from_str(clocktime_json).unwrap(); + assert_eq!(clocktime.nseconds(), None); + } +} diff --git a/gstreamer/src/date_time.rs b/gstreamer/src/date_time.rs index 0a394f0bf..577aab7a2 100644 --- a/gstreamer/src/date_time.rs +++ b/gstreamer/src/date_time.rs @@ -18,151 +18,3 @@ 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/date_time_serde.rs b/gstreamer/src/date_time_serde.rs new file mode 100644 index 000000000..13ce2906f --- /dev/null +++ b/gstreamer/src/date_time_serde.rs @@ -0,0 +1,144 @@ +// Copyright (C) 2018 François Laignel +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +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 { + extern crate ron; + extern crate serde_json; + + use DateTime; + + #[test] + fn test_serialize() { + ::init().unwrap(); + + let datetime = DateTime::new(2f32, 2018, 5, 28, 16, 6, 42.841f64); + + 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, + ); + } + + #[test] + fn test_deserialize() { + ::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/format.rs b/gstreamer/src/format.rs index 641b187a3..6d0343352 100644 --- a/gstreamer/src/format.rs +++ b/gstreamer/src/format.rs @@ -504,7 +504,6 @@ mod tests { ::init().unwrap(); - // don't use newlines let mut pretty_config = ron::ser::PrettyConfig::default(); pretty_config.new_line = "".to_string(); diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index fd342b87c..c1b6a1051 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -75,23 +75,45 @@ pub mod miniobject; pub use miniobject::{GstRc, MiniObject}; pub mod message; pub use message::{Message, MessageErrorDomain, MessageRef, MessageView}; -#[macro_use] + mod value; pub use value::*; +#[cfg(feature = "ser_de")] +#[macro_use] +pub(crate) mod value_serde; + pub mod structure; pub use structure::{Structure, StructureRef}; +#[cfg(feature = "ser_de")] +pub(crate) mod structure_serde; + pub mod caps; pub use caps::{Caps, CapsRef}; +#[cfg(feature = "ser_de")] +pub(crate) mod caps_serde; + pub mod tags; pub use tags::{Tag, TagList, TagListRef}; +#[cfg(feature = "ser_de")] +pub(crate) mod tags_serde; + pub mod buffer; pub use buffer::{ Buffer, BufferMap, BufferRef, MappedBuffer, BUFFER_COPY_ALL, BUFFER_COPY_METADATA, }; +#[cfg(feature = "ser_de")] +pub(crate) mod buffer_serde; + pub mod sample; pub use sample::{Sample, SampleRef}; +#[cfg(feature = "ser_de")] +pub(crate) mod sample_serde; + pub mod bufferlist; pub use bufferlist::{BufferList, BufferListRef}; +#[cfg(feature = "ser_de")] +pub(crate) mod bufferlist_serde; + pub mod query; pub use query::{Query, QueryRef, QueryView}; pub mod event; @@ -128,7 +150,11 @@ cfg_if! { mod child_proxy; mod clock_time; +#[cfg(feature = "ser_de")] +pub(crate) mod clock_time_serde; mod date_time; +#[cfg(feature = "ser_de")] +mod date_time_serde; mod device_monitor; mod device_provider; mod enums; @@ -191,9 +217,13 @@ pub use format::{FormattedValue, GenericFormattedValue, SpecificFormattedValue}; mod segment; pub use segment::*; +#[cfg(feature = "ser_de")] +pub(crate) mod segment_serde; pub mod toc; pub use toc::{Toc, TocEntry, TocEntryRef, TocRef}; +#[cfg(feature = "ser_de")] +pub(crate) mod toc_serde; mod clock; pub use clock::{ClockExtManual, ClockId}; diff --git a/gstreamer/src/sample.rs b/gstreamer/src/sample.rs index 18ef48a1f..c443e0bbe 100644 --- a/gstreamer/src/sample.rs +++ b/gstreamer/src/sample.rs @@ -127,75 +127,6 @@ impl fmt::Debug for SampleRef { unsafe impl Sync for SampleRef {} unsafe impl Send for SampleRef {} -#[cfg(feature = "ser_de")] -pub(crate) mod serde { - use serde::de::{Deserialize, Deserializer}; - use serde::ser::{Serialize, Serializer, SerializeStruct}; - - use Buffer; - use BufferList; - use Caps; - use GenericFormattedValue; - use Sample; - use SampleRef; - use Segment; - use Structure; - - impl<'a> Serialize for SampleRef { - fn serialize(&self, serializer: S) -> Result { - let mut sample = serializer.serialize_struct("Sample", 5)?; - sample.serialize_field("buffer", &self.get_buffer())?; - sample.serialize_field("buffer_list", &self.get_buffer_list())?; - sample.serialize_field("caps", &self.get_caps())?; - sample.serialize_field("segment", &self.get_segment())?; - sample.serialize_field("info", &self.get_info())?; - sample.end() - } - } - - impl<'a> Serialize for Sample { - fn serialize(&self, serializer: S) -> Result { - self.as_ref().serialize(serializer) - } - } - - #[derive(Deserialize)] - struct SampleDe { - buffer: Option, - buffer_list: Option, - caps: Option, - segment: Option, - info: Option, - } - - impl From for Sample { - fn from(mut buf_de: SampleDe) -> Self { - if buf_de.buffer.is_some() { - Sample::new::( - buf_de.buffer.as_ref(), - buf_de.caps.as_ref(), - buf_de.segment.as_ref(), - buf_de.info.take(), - ) - } else { - Sample::with_buffer_list::( - buf_de.buffer_list.as_ref(), - buf_de.caps.as_ref(), - buf_de.segment.as_ref(), - buf_de.info.take(), - ) - } - } - } - - impl<'de> Deserialize<'de> for Sample { - fn deserialize>(deserializer: D) -> Result { - SampleDe::deserialize(deserializer) - .and_then(|sample_de| Ok(sample_de.into())) - } - } -} - #[cfg(test)] mod tests { @@ -214,258 +145,4 @@ mod tests { assert!(sample.get_info().is_some()); } - - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize() { - extern crate ron; - - use Buffer; - use Caps; - use ClockTime; - use Format; - use GenericFormattedValue; - use Sample; - use Segment; - use SegmentFlags; - use Structure; - - ::init().unwrap(); - - let mut pretty_config = ron::ser::PrettyConfig::default(); - pretty_config.new_line = "".to_string(); - - let sample = { - let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); - { - let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); - buffer.set_offset(0); - buffer.set_offset_end(4); - buffer.set_duration(4.into()); - } - - let caps = Caps::builder("sample/caps") - .field("int", &12) - .field("bool", &true) - .build(); - - let mut segment = Segment::new(); - segment.set_flags(SegmentFlags::RESET | SegmentFlags::SEGMENT); - segment.set_rate(1f64); - segment.set_applied_rate(0.9f64); - segment.set_format(Format::Time); - segment.set_base(GenericFormattedValue::Time(ClockTime::from_nseconds(123))); - segment.set_offset(GenericFormattedValue::Time(ClockTime::from_nseconds(42))); - segment.set_start(GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); - segment.set_stop(GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); - segment.set_time(GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); - segment.set_position(GenericFormattedValue::Time(ClockTime::from_nseconds(256))); - segment.set_duration(GenericFormattedValue::Time(ClockTime::none())); - - let info = Structure::builder("sample.info") - .field("f3", &123i32) - .build(); - - Sample::new::( - Some(&buffer), - Some(&caps), - Some(&segment), - Some(info), - ) - }; - - let res = ron::ser::to_string_pretty(&sample, pretty_config.clone()); - assert_eq!( - Ok( - concat!( - "(", - " buffer: Some((", - " pts: Some(1),", - " dts: None,", - " duration: Some(4),", - " offset: 0,", - " offset_end: 4,", - " flags: (", - " bits: 0,", - " ),", - " buffer: \"AQIDBA==\",", - " )),", - " buffer_list: None,", - " caps: Some([", - " (\"sample/caps\", [", - " (\"int\", \"i32\", 12),", - " (\"bool\", \"bool\", true),", - " ]),", - " ]),", - " segment: Some((", - " flags: (", - " bits: 9,", - " ),", - " rate: 1,", - " applied_rate: 0.9,", - " format: Time,", - " base: 123,", - " offset: 42,", - " start: 1024,", - " stop: 2048,", - " time: 1042,", - " position: 256,", - " duration: -1,", - " )),", - " info: Some((\"sample.info\", [", - " (\"f3\", \"i32\", 123),", - " ])),", - ")" - ) - .to_owned() - ), - res - ); - - let sample = { - let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); - { - let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); - buffer.set_offset(0); - buffer.set_offset_end(4); - buffer.set_duration(4.into()); - } - Sample::new::(Some(&buffer), None, None, None) - }; - - // `Sample`'s `Segment` is allocated in GStreamer 1.x, should be fixed in version 2.0 - - let res = ron::ser::to_string_pretty(&sample, pretty_config); - assert_eq!( - Ok( - concat!( - "(", - " buffer: Some((", - " pts: Some(1),", - " dts: None,", - " duration: Some(4),", - " offset: 0,", - " offset_end: 4,", - " flags: (", - " bits: 0,", - " ),", - " buffer: \"AQIDBA==\",", - " )),", - " buffer_list: None,", - " caps: None,", - " segment: Some((", - " flags: (", - " bits: 0,", - " ),", - " rate: 1,", - " applied_rate: 1,", - " format: Time,", - " base: 0,", - " offset: 0,", - " start: 0,", - " stop: -1,", - " time: 0,", - " position: 0,", - " duration: -1,", - " )),", - " info: None,", - ")" - ) - .to_owned() - ), - res - ); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize() { - extern crate ron; - - use Sample; - - ::init().unwrap(); - - let buffer_ron = r#" - ( - buffer: Some(( - pts: Some(1), - dts: None, - duration: Some(4), - offset: 0, - offset_end: 4, - flags: ( - bits: 0, - ), - buffer: "AQIDBA==", - )), - buffer_list: None, - caps: Some([ - ("sample/caps", [ - ("int", "i32", 12), - ("bool", "bool", true), - ]), - ]), - segment: Some(( - flags: ( - bits: 0, - ), - rate: 1, - applied_rate: 0.9, - format: Time, - base: 123, - offset: 42, - start: 1024, - stop: 2048, - time: 1042, - position: 256, - duration: -1, - )), - info: Some(("sample.info", [ - ("f3", "i32", 123), - ])), - )"#; - let sample: Sample = ron::de::from_str(buffer_ron).unwrap(); - let buffer = sample.get_buffer().unwrap(); - assert_eq!(buffer.get_pts(), 1.into()); - assert_eq!(buffer.get_offset_end(), 4); - { - let data = buffer.map_readable().unwrap(); - assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); - } - assert!(sample.get_buffer_list().is_none()); - assert!(sample.get_caps().is_some()); - assert!(sample.get_segment().is_some()); - assert!(sample.get_info().is_some()); - - let buffer_ron = r#" - ( - buffer: None, - buffer_list: Some([ - ( - pts: Some(1), - dts: None, - duration: Some(4), - offset: 0, - offset_end: 4, - flags: ( - bits: 0, - ), - buffer: "AQIDBA==", - ), - ]), - caps: None, - segment: None, - info: None, - )"#; - let sample: Sample = ron::de::from_str(buffer_ron).unwrap(); - assert!(sample.get_buffer().is_none()); - assert!(sample.get_buffer_list().is_some()); - assert!(sample.get_caps().is_none()); - // Not true in GStreamer 1.x, should be fixed in version 2.0 - //assert!(sample.get_segment().is_none()); - assert!(sample.get_info().is_none()); - } } diff --git a/gstreamer/src/sample_serde.rs b/gstreamer/src/sample_serde.rs new file mode 100644 index 000000000..e92c132d0 --- /dev/null +++ b/gstreamer/src/sample_serde.rs @@ -0,0 +1,325 @@ +// Copyright (C) 2018 François Laignel +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use serde::de::{Deserialize, Deserializer}; +use serde::ser::{Serialize, Serializer, SerializeStruct}; + +use Buffer; +use BufferList; +use Caps; +use GenericFormattedValue; +use Sample; +use SampleRef; +use Segment; +use Structure; + +impl<'a> Serialize for SampleRef { + fn serialize(&self, serializer: S) -> Result { + let mut sample = serializer.serialize_struct("Sample", 5)?; + sample.serialize_field("buffer", &self.get_buffer())?; + sample.serialize_field("buffer_list", &self.get_buffer_list())?; + sample.serialize_field("caps", &self.get_caps())?; + sample.serialize_field("segment", &self.get_segment())?; + sample.serialize_field("info", &self.get_info())?; + sample.end() + } +} + +impl<'a> Serialize for Sample { + fn serialize(&self, serializer: S) -> Result { + self.as_ref().serialize(serializer) + } +} + +#[derive(Deserialize)] +struct SampleDe { + buffer: Option, + buffer_list: Option, + caps: Option, + segment: Option, + info: Option, +} + +impl From for Sample { + fn from(mut buf_de: SampleDe) -> Self { + if buf_de.buffer.is_some() { + Sample::new::( + buf_de.buffer.as_ref(), + buf_de.caps.as_ref(), + buf_de.segment.as_ref(), + buf_de.info.take(), + ) + } else { + Sample::with_buffer_list::( + buf_de.buffer_list.as_ref(), + buf_de.caps.as_ref(), + buf_de.segment.as_ref(), + buf_de.info.take(), + ) + } + } +} + +impl<'de> Deserialize<'de> for Sample { + fn deserialize>(deserializer: D) -> Result { + SampleDe::deserialize(deserializer) + .and_then(|sample_de| Ok(sample_de.into())) + } +} + +#[cfg(test)] +mod tests { + extern crate ron; + + use Sample; + + #[test] + fn test_serialize() { + use Buffer; + use Caps; + use ClockTime; + use Format; + use GenericFormattedValue; + use Segment; + use SegmentFlags; + use Structure; + + ::init().unwrap(); + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let sample = { + let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(1.into()); + buffer.set_offset(0); + buffer.set_offset_end(4); + buffer.set_duration(4.into()); + } + + let caps = Caps::builder("sample/caps") + .field("int", &12) + .field("bool", &true) + .build(); + + let mut segment = Segment::new(); + segment.set_flags(SegmentFlags::RESET | SegmentFlags::SEGMENT); + segment.set_rate(1f64); + segment.set_applied_rate(0.9f64); + segment.set_format(Format::Time); + segment.set_base(GenericFormattedValue::Time(ClockTime::from_nseconds(123))); + segment.set_offset(GenericFormattedValue::Time(ClockTime::from_nseconds(42))); + segment.set_start(GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); + segment.set_stop(GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); + segment.set_time(GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); + segment.set_position(GenericFormattedValue::Time(ClockTime::from_nseconds(256))); + segment.set_duration(GenericFormattedValue::Time(ClockTime::none())); + + let info = Structure::builder("sample.info") + .field("f3", &123i32) + .build(); + + Sample::new::( + Some(&buffer), + Some(&caps), + Some(&segment), + Some(info), + ) + }; + + let res = ron::ser::to_string_pretty(&sample, pretty_config.clone()); + assert_eq!( + Ok( + concat!( + "(", + " buffer: Some((", + " pts: Some(1),", + " dts: None,", + " duration: Some(4),", + " offset: 0,", + " offset_end: 4,", + " flags: (", + " bits: 0,", + " ),", + " buffer: \"AQIDBA==\",", + " )),", + " buffer_list: None,", + " caps: Some([", + " (\"sample/caps\", [", + " (\"int\", \"i32\", 12),", + " (\"bool\", \"bool\", true),", + " ]),", + " ]),", + " segment: Some((", + " flags: (", + " bits: 9,", + " ),", + " rate: 1,", + " applied_rate: 0.9,", + " format: Time,", + " base: 123,", + " offset: 42,", + " start: 1024,", + " stop: 2048,", + " time: 1042,", + " position: 256,", + " duration: -1,", + " )),", + " info: Some((\"sample.info\", [", + " (\"f3\", \"i32\", 123),", + " ])),", + ")" + ) + .to_owned() + ), + res + ); + + let sample = { + let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(1.into()); + buffer.set_offset(0); + buffer.set_offset_end(4); + buffer.set_duration(4.into()); + } + Sample::new::(Some(&buffer), None, None, None) + }; + + // `Sample`'s `Segment` is allocated in GStreamer 1.x, should be fixed in version 2.0 + + let res = ron::ser::to_string_pretty(&sample, pretty_config); + assert_eq!( + Ok( + concat!( + "(", + " buffer: Some((", + " pts: Some(1),", + " dts: None,", + " duration: Some(4),", + " offset: 0,", + " offset_end: 4,", + " flags: (", + " bits: 0,", + " ),", + " buffer: \"AQIDBA==\",", + " )),", + " buffer_list: None,", + " caps: None,", + " segment: Some((", + " flags: (", + " bits: 0,", + " ),", + " rate: 1,", + " applied_rate: 1,", + " format: Time,", + " base: 0,", + " offset: 0,", + " start: 0,", + " stop: -1,", + " time: 0,", + " position: 0,", + " duration: -1,", + " )),", + " info: None,", + ")" + ) + .to_owned() + ), + res + ); + } + + #[test] + fn test_deserialize() { + ::init().unwrap(); + + let buffer_ron = r#" + ( + buffer: Some(( + pts: Some(1), + dts: None, + duration: Some(4), + offset: 0, + offset_end: 4, + flags: ( + bits: 0, + ), + buffer: "AQIDBA==", + )), + buffer_list: None, + caps: Some([ + ("sample/caps", [ + ("int", "i32", 12), + ("bool", "bool", true), + ]), + ]), + segment: Some(( + flags: ( + bits: 0, + ), + rate: 1, + applied_rate: 0.9, + format: Time, + base: 123, + offset: 42, + start: 1024, + stop: 2048, + time: 1042, + position: 256, + duration: -1, + )), + info: Some(("sample.info", [ + ("f3", "i32", 123), + ])), + )"#; + let sample: Sample = ron::de::from_str(buffer_ron).unwrap(); + let buffer = sample.get_buffer().unwrap(); + assert_eq!(buffer.get_pts(), 1.into()); + assert_eq!(buffer.get_offset_end(), 4); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + assert!(sample.get_buffer_list().is_none()); + assert!(sample.get_caps().is_some()); + assert!(sample.get_segment().is_some()); + assert!(sample.get_info().is_some()); + + let buffer_ron = r#" + ( + buffer: None, + buffer_list: Some([ + ( + pts: Some(1), + dts: None, + duration: Some(4), + offset: 0, + offset_end: 4, + flags: ( + bits: 0, + ), + buffer: "AQIDBA==", + ), + ]), + caps: None, + segment: None, + info: None, + )"#; + let sample: Sample = ron::de::from_str(buffer_ron).unwrap(); + assert!(sample.get_buffer().is_none()); + assert!(sample.get_buffer_list().is_some()); + assert!(sample.get_caps().is_none()); + // Not true in GStreamer 1.x, should be fixed in version 2.0 + //assert!(sample.get_segment().is_none()); + assert!(sample.get_info().is_none()); + } +} diff --git a/gstreamer/src/segment.rs b/gstreamer/src/segment.rs index 9d7775bcc..13e1a936e 100644 --- a/gstreamer/src/segment.rs +++ b/gstreamer/src/segment.rs @@ -655,176 +655,3 @@ impl glib::translate::FromGlibPtrFull<*mut ffi::GstSegment> for Segment { segment } } - -#[cfg(feature = "ser_de")] -pub(crate) mod serde { - use serde::de::{Deserialize, Deserializer}; - use serde::ser::{Serialize, Serializer, SerializeStruct}; - - use Format; - use GenericFormattedValue; - use Segment; - use SegmentFlags; - - impl<'a> Serialize for Segment { - fn serialize(&self, serializer: S) -> Result { - let mut datetime = serializer.serialize_struct("Segment", 11)?; - datetime.serialize_field("flags", &self.get_flags())?; - datetime.serialize_field("rate", &self.get_rate())?; - datetime.serialize_field("applied_rate", &self.get_applied_rate())?; - datetime.serialize_field("format", &self.get_format())?; - datetime.serialize_field("base", &self.get_base().get_value())?; - datetime.serialize_field("offset", &self.get_offset().get_value())?; - datetime.serialize_field("start", &self.get_start().get_value())?; - datetime.serialize_field("stop", &self.get_stop().get_value())?; - datetime.serialize_field("time", &self.get_time().get_value())?; - datetime.serialize_field("position", &self.get_position().get_value())?; - datetime.serialize_field("duration", &self.get_duration().get_value())?; - datetime.end() - } - } - - #[derive(Deserialize)] - struct SegmentDe { - flags: SegmentFlags, - rate: f64, - applied_rate: f64, - format: Format, - base: i64, - offset: i64, - start: i64, - stop: i64, - time: i64, - position: i64, - duration: i64, - } - - impl From for Segment { - fn from(segment_de: SegmentDe) -> Self { - let mut segment = Segment::new(); - segment.set_flags(segment_de.flags); - segment.set_rate(segment_de.rate); - segment.set_applied_rate(segment_de.applied_rate); - segment.set_format(segment_de.format); - segment.set_base(GenericFormattedValue::new(segment_de.format, segment_de.base)); - segment.set_offset(GenericFormattedValue::new(segment_de.format, segment_de.offset)); - segment.set_start(GenericFormattedValue::new(segment_de.format, segment_de.start)); - segment.set_stop(GenericFormattedValue::new(segment_de.format, segment_de.stop)); - segment.set_time(GenericFormattedValue::new(segment_de.format, segment_de.time)); - segment.set_position(GenericFormattedValue::new(segment_de.format, segment_de.position)); - segment.set_duration(GenericFormattedValue::new(segment_de.format, segment_de.duration)); - - segment - } - } - - impl<'de> Deserialize<'de> for Segment { - fn deserialize>(deserializer: D) -> Result { - SegmentDe::deserialize(deserializer) - .and_then(|segment_de| Ok(segment_de.into())) - } - } -} - -#[cfg(test)] -mod tests { - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize() { - extern crate ron; - - use ClockTime; - use Format; - use GenericFormattedValue; - use Segment; - use SegmentFlags; - - ::init().unwrap(); - - let mut segment = Segment::new(); - segment.set_flags(SegmentFlags::RESET | SegmentFlags::SEGMENT); - segment.set_rate(1f64); - segment.set_applied_rate(0.9f64); - segment.set_format(Format::Time); - segment.set_base(GenericFormattedValue::Time(ClockTime::from_nseconds(123))); - segment.set_offset(GenericFormattedValue::Time(ClockTime::from_nseconds(42))); - segment.set_start(GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); - segment.set_stop(GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); - segment.set_time(GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); - segment.set_position(GenericFormattedValue::Time(ClockTime::from_nseconds(256))); - segment.set_duration(GenericFormattedValue::Time(ClockTime::none())); - - let mut pretty_config = ron::ser::PrettyConfig::default(); - pretty_config.new_line = "".to_string(); - - let res = ron::ser::to_string_pretty(&segment, pretty_config); - assert_eq!( - Ok( - concat!( - "(", - " flags: (", - " bits: 9,", - " ),", - " rate: 1,", - " applied_rate: 0.9,", - " format: Time,", - " base: 123,", - " offset: 42,", - " start: 1024,", - " stop: 2048,", - " time: 1042,", - " position: 256,", - " duration: -1,", - ")" - ) - .to_owned() - ), - res, - ); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize() { - extern crate ron; - - use ClockTime; - use Format; - use GenericFormattedValue; - use Segment; - use SegmentFlags; - - ::init().unwrap(); - - let segment_ron = r#" - ( - flags: ( - bits: 9, - ), - rate: 1, - applied_rate: 0.9, - format: Time, - base: 123, - offset: 42, - start: 1024, - stop: 2048, - time: 1042, - position: 256, - duration: -1, - ) - "#; - - let segment: Segment = ron::de::from_str(segment_ron).unwrap(); - assert_eq!(segment.get_flags(), SegmentFlags::RESET | SegmentFlags::SEGMENT); - assert_eq!(segment.get_rate(), 1f64); - assert_eq!(segment.get_applied_rate(), 0.9f64); - assert_eq!(segment.get_format(), Format::Time); - assert_eq!(segment.get_base(), GenericFormattedValue::Time(ClockTime::from_nseconds(123))); - assert_eq!(segment.get_offset(), GenericFormattedValue::Time(ClockTime::from_nseconds(42))); - assert_eq!(segment.get_start(), GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); - assert_eq!(segment.get_stop(), GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); - assert_eq!(segment.get_time(), GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); - assert_eq!(segment.get_position(), GenericFormattedValue::Time(ClockTime::from_nseconds(256))); - assert_eq!(segment.get_duration(), GenericFormattedValue::Time(ClockTime::none())); - } -} diff --git a/gstreamer/src/segment_serde.rs b/gstreamer/src/segment_serde.rs new file mode 100644 index 000000000..f87aa8c8f --- /dev/null +++ b/gstreamer/src/segment_serde.rs @@ -0,0 +1,167 @@ +// Copyright (C) 2018 François Laignel +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use serde::de::{Deserialize, Deserializer}; +use serde::ser::{Serialize, Serializer, SerializeStruct}; + +use Format; +use GenericFormattedValue; +use Segment; +use SegmentFlags; + +impl<'a> Serialize for Segment { + fn serialize(&self, serializer: S) -> Result { + let mut datetime = serializer.serialize_struct("Segment", 11)?; + datetime.serialize_field("flags", &self.get_flags())?; + datetime.serialize_field("rate", &self.get_rate())?; + datetime.serialize_field("applied_rate", &self.get_applied_rate())?; + datetime.serialize_field("format", &self.get_format())?; + datetime.serialize_field("base", &self.get_base().get_value())?; + datetime.serialize_field("offset", &self.get_offset().get_value())?; + datetime.serialize_field("start", &self.get_start().get_value())?; + datetime.serialize_field("stop", &self.get_stop().get_value())?; + datetime.serialize_field("time", &self.get_time().get_value())?; + datetime.serialize_field("position", &self.get_position().get_value())?; + datetime.serialize_field("duration", &self.get_duration().get_value())?; + datetime.end() + } +} + +#[derive(Deserialize)] +struct SegmentDe { + flags: SegmentFlags, + rate: f64, + applied_rate: f64, + format: Format, + base: i64, + offset: i64, + start: i64, + stop: i64, + time: i64, + position: i64, + duration: i64, +} + +impl From for Segment { + fn from(segment_de: SegmentDe) -> Self { + let mut segment = Segment::new(); + segment.set_flags(segment_de.flags); + segment.set_rate(segment_de.rate); + segment.set_applied_rate(segment_de.applied_rate); + segment.set_format(segment_de.format); + segment.set_base(GenericFormattedValue::new(segment_de.format, segment_de.base)); + segment.set_offset(GenericFormattedValue::new(segment_de.format, segment_de.offset)); + segment.set_start(GenericFormattedValue::new(segment_de.format, segment_de.start)); + segment.set_stop(GenericFormattedValue::new(segment_de.format, segment_de.stop)); + segment.set_time(GenericFormattedValue::new(segment_de.format, segment_de.time)); + segment.set_position(GenericFormattedValue::new(segment_de.format, segment_de.position)); + segment.set_duration(GenericFormattedValue::new(segment_de.format, segment_de.duration)); + + segment + } +} + +impl<'de> Deserialize<'de> for Segment { + fn deserialize>(deserializer: D) -> Result { + SegmentDe::deserialize(deserializer) + .and_then(|segment_de| Ok(segment_de.into())) + } +} + +#[cfg(test)] +mod tests { + extern crate ron; + + use ClockTime; + use Format; + use GenericFormattedValue; + use Segment; + use SegmentFlags; + + #[test] + fn test_serialize() { + ::init().unwrap(); + + let mut segment = Segment::new(); + segment.set_flags(SegmentFlags::RESET | SegmentFlags::SEGMENT); + segment.set_rate(1f64); + segment.set_applied_rate(0.9f64); + segment.set_format(Format::Time); + segment.set_base(GenericFormattedValue::Time(ClockTime::from_nseconds(123))); + segment.set_offset(GenericFormattedValue::Time(ClockTime::from_nseconds(42))); + segment.set_start(GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); + segment.set_stop(GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); + segment.set_time(GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); + segment.set_position(GenericFormattedValue::Time(ClockTime::from_nseconds(256))); + segment.set_duration(GenericFormattedValue::Time(ClockTime::none())); + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let res = ron::ser::to_string_pretty(&segment, pretty_config); + assert_eq!( + Ok( + concat!( + "(", + " flags: (", + " bits: 9,", + " ),", + " rate: 1,", + " applied_rate: 0.9,", + " format: Time,", + " base: 123,", + " offset: 42,", + " start: 1024,", + " stop: 2048,", + " time: 1042,", + " position: 256,", + " duration: -1,", + ")" + ) + .to_owned() + ), + res, + ); + } + + #[test] + fn test_deserialize() { + ::init().unwrap(); + + let segment_ron = r#" + ( + flags: ( + bits: 9, + ), + rate: 1, + applied_rate: 0.9, + format: Time, + base: 123, + offset: 42, + start: 1024, + stop: 2048, + time: 1042, + position: 256, + duration: -1, + ) + "#; + + let segment: Segment = ron::de::from_str(segment_ron).unwrap(); + assert_eq!(segment.get_flags(), SegmentFlags::RESET | SegmentFlags::SEGMENT); + assert_eq!(segment.get_rate(), 1f64); + assert_eq!(segment.get_applied_rate(), 0.9f64); + assert_eq!(segment.get_format(), Format::Time); + assert_eq!(segment.get_base(), GenericFormattedValue::Time(ClockTime::from_nseconds(123))); + assert_eq!(segment.get_offset(), GenericFormattedValue::Time(ClockTime::from_nseconds(42))); + assert_eq!(segment.get_start(), GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); + assert_eq!(segment.get_stop(), GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); + assert_eq!(segment.get_time(), GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); + assert_eq!(segment.get_position(), GenericFormattedValue::Time(ClockTime::from_nseconds(256))); + assert_eq!(segment.get_duration(), GenericFormattedValue::Time(ClockTime::none())); + } +} diff --git a/gstreamer/src/structure.rs b/gstreamer/src/structure.rs index 273fc465c..092575b7e 100644 --- a/gstreamer/src/structure.rs +++ b/gstreamer/src/structure.rs @@ -655,171 +655,6 @@ impl Builder { } } -#[cfg(feature = "ser_de")] -pub(crate) mod serde { - use glib; - use glib::ToValue; - - use serde::de; - use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; - use serde::ser; - use serde::ser::{Serialize, Serializer, SerializeSeq, SerializeTuple}; - - use std::fmt; - - use DateTime; - use Sample; - - use value::*; - use value::serde::*; - - use Structure; - use StructureRef; - - struct FieldSe<'a>(&'a str, &'a glib::SendValue); - impl<'a> Serialize for FieldSe<'a> { - fn serialize(&self, serializer: S) -> Result { - ser_value!(self.1, |type_, value| { - let mut tup = serializer.serialize_tuple(3)?; - tup.serialize_element(self.0)?; - tup.serialize_element(type_)?; - tup.serialize_element(&value)?; - tup.end() - }) - } - } - - struct StructureForIter<'a>(&'a StructureRef); - impl<'a> Serialize for StructureForIter<'a> { - fn serialize(&self, serializer: S) -> Result { - let iter = self.0.iter(); - let size = iter.size_hint().0; - if size > 0 { - let mut seq = serializer.serialize_seq(Some(size))?; - for field in iter { - seq.serialize_element(&FieldSe(field.0, field.1))?; - } - seq.end() - } else { - let seq = serializer.serialize_seq(None)?; - seq.end() - } - } - } - - impl Serialize for StructureRef { - fn serialize(&self, serializer: S) -> Result { - let mut tup = serializer.serialize_tuple(2)?; - tup.serialize_element(self.get_name())?; - tup.serialize_element(&StructureForIter(self))?; - tup.end() - } - } - - impl Serialize for Structure { - fn serialize(&self, serializer: S) -> Result { - self.as_ref().serialize(serializer) - } - } - - struct FieldDe(String, SendValue); - impl From for (String, glib::SendValue) { - fn from(field_de: FieldDe) -> Self { - (field_de.0, field_de.1.into()) - } - } - - struct FieldVisitor; - impl<'de> Visitor<'de> for FieldVisitor { - type Value = FieldDe; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str( - "a tuple of 3 elements (name: `String`, type name: `String`, value: `Value`)" - ) - } - - fn visit_seq>(self, mut seq: A) -> Result { - let name = seq.next_element::()? - .ok_or(de::Error::custom("Expected a value for `Value` name, found `None`"))?; - let type_name = seq.next_element::()? - .ok_or(de::Error::custom("Expected a value for `Value` type, found `None`"))?; - Ok(FieldDe(name, de_send_value!(type_name, seq))) - } - } - - impl<'de> Deserialize<'de> for FieldDe { - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_tuple(3, FieldVisitor) - } - } - - // Use `NamelessStructure` to deserialize the `Field`s and - // to add them to the `Structure` at the same time. - struct NamelessStructure(Structure); - impl From for Structure { - fn from(nameless_structure: NamelessStructure) -> Self { - nameless_structure.0 - } - } - - struct NamelessStructureVisitor; - impl<'de> Visitor<'de> for NamelessStructureVisitor { - type Value = NamelessStructure; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a nameless `Structure` consisting of a sequence of `Field`s)") - } - - fn visit_seq>(self, mut seq: A) -> Result { - // Can't build a `Structure` with an empty name - let mut structure = Structure::new_empty("None"); - while let Some(field) = seq.next_element::()? { - let (name, value): (String, glib::SendValue) = field.into(); - structure.as_mut().set_value(name.as_str(), value); - } - - Ok(NamelessStructure(structure)) - } - } - - impl<'de> Deserialize<'de> for NamelessStructure { - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_seq(NamelessStructureVisitor) - } - } - - struct StructureVisitor; - impl<'de> Visitor<'de> for StructureVisitor { - type Value = Structure; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a `Structure`: (name: `String`, fields: sequence of `Field`s)") - } - - fn visit_seq>(self, mut seq: A) -> Result { - let name = seq.next_element::()? - .ok_or(de::Error::custom( - "Expected a name for the `Structure`, found `None`" - ))?; - let mut structure: Structure = seq.next_element::()? - .ok_or(de::Error::custom( - "Expected a sequence of `Field`s, found `None`" - ))? - .into(); - structure.set_name(name.as_str()); - - Ok(structure) - } - } - - impl<'de> Deserialize<'de> for Structure { - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_tuple(2, StructureVisitor) - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -880,82 +715,4 @@ mod tests { assert_eq!(a, s.to_string()); } - - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize() { - extern crate ron; - - use Array; - - ::init().unwrap(); - - let s = Structure::builder("test") - .field("f1", &"abc") - .field("f2", &String::from("bcd")) - .field("f3", &123i32) - .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(&s, pretty_config); - assert_eq!( - Ok( - concat!( - "(\"test\", [", - " (\"f1\", \"String\", \"abc\"),", - " (\"f2\", \"String\", \"bcd\"),", - " (\"f3\", \"i32\", 123),", - " (\"fraction\", \"Fraction\", (1, 2)),", - " (\"array\", \"Array\", [", - " (\"i32\", 1),", - " (\"i32\", 2),", - " ]),", - "])" - ) - .to_owned() - ), - res, - ); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize() { - extern crate ron; - - use Array; - - ::init().unwrap(); - - let s_ron = r#" - ("test", [ - ("f1", "String", "abc"), - ("f2", "String", "bcd"), - ("f3", "i32", 123), - ("fraction", "Fraction", (1, 2)), - ("array", "Array", [ - ("i32", 1), - ("i32", 2), - ]), - ])"#; - let s: Structure = ron::de::from_str(s_ron).unwrap(); - assert_eq!( - s.as_ref(), - Structure::new( - "test", - &[ - ("f1", &"abc"), - ("f2", &"bcd"), - ("f3", &123), - ("fraction", &Fraction::new(1, 2)), - ("array", &Array::new(&[&1, &2])), - ], - ).as_ref() - ); - } } diff --git a/gstreamer/src/structure_serde.rs b/gstreamer/src/structure_serde.rs new file mode 100644 index 000000000..1f2def2e1 --- /dev/null +++ b/gstreamer/src/structure_serde.rs @@ -0,0 +1,245 @@ +// Copyright (C) 2018 François Laignel +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use glib; +use glib::ToValue; + +use serde::de; +use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; +use serde::ser; +use serde::ser::{Serialize, Serializer, SerializeSeq, SerializeTuple}; + +use std::fmt; + +use DateTime; +use Sample; + +use value::*; +use value_serde::*; + +use Structure; +use StructureRef; + +struct FieldSe<'a>(&'a str, &'a glib::SendValue); +impl<'a> Serialize for FieldSe<'a> { + fn serialize(&self, serializer: S) -> Result { + ser_value!(self.1, |type_, value| { + let mut tup = serializer.serialize_tuple(3)?; + tup.serialize_element(self.0)?; + tup.serialize_element(type_)?; + tup.serialize_element(&value)?; + tup.end() + }) + } +} + +struct StructureForIter<'a>(&'a StructureRef); +impl<'a> Serialize for StructureForIter<'a> { + fn serialize(&self, serializer: S) -> Result { + let iter = self.0.iter(); + let size = iter.size_hint().0; + if size > 0 { + let mut seq = serializer.serialize_seq(Some(size))?; + for field in iter { + seq.serialize_element(&FieldSe(field.0, field.1))?; + } + seq.end() + } else { + let seq = serializer.serialize_seq(None)?; + seq.end() + } + } +} + +impl Serialize for StructureRef { + fn serialize(&self, serializer: S) -> Result { + let mut tup = serializer.serialize_tuple(2)?; + tup.serialize_element(self.get_name())?; + tup.serialize_element(&StructureForIter(self))?; + tup.end() + } +} + +impl Serialize for Structure { + fn serialize(&self, serializer: S) -> Result { + self.as_ref().serialize(serializer) + } +} + +struct FieldDe(String, SendValue); +impl From for (String, glib::SendValue) { + fn from(field_de: FieldDe) -> Self { + (field_de.0, field_de.1.into()) + } +} + +struct FieldVisitor; +impl<'de> Visitor<'de> for FieldVisitor { + type Value = FieldDe; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str( + "a tuple of 3 elements (name: `String`, type name: `String`, value: `Value`)" + ) + } + + fn visit_seq>(self, mut seq: A) -> Result { + let name = seq.next_element::()? + .ok_or(de::Error::custom("Expected a value for `Value` name"))?; + let type_name = seq.next_element::()? + .ok_or(de::Error::custom("Expected a value for `Value` type"))?; + Ok(FieldDe(name, de_send_value!(type_name, seq))) + } +} + +impl<'de> Deserialize<'de> for FieldDe { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_tuple(3, FieldVisitor) + } +} + +// Use `NamelessStructure` to deserialize the `Field`s and +// to add them to the `Structure` at the same time. +struct NamelessStructure(Structure); +impl From for Structure { + fn from(nameless_structure: NamelessStructure) -> Self { + nameless_structure.0 + } +} + +struct NamelessStructureVisitor; +impl<'de> Visitor<'de> for NamelessStructureVisitor { + type Value = NamelessStructure; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a nameless `Structure` consisting of a sequence of `Field`s)") + } + + fn visit_seq>(self, mut seq: A) -> Result { + // Can't build a `Structure` with an empty name + let mut structure = Structure::new_empty("None"); + while let Some(field) = seq.next_element::()? { + let (name, value): (String, glib::SendValue) = field.into(); + structure.as_mut().set_value(name.as_str(), value); + } + + Ok(NamelessStructure(structure)) + } +} + +impl<'de> Deserialize<'de> for NamelessStructure { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_seq(NamelessStructureVisitor) + } +} + +struct StructureVisitor; +impl<'de> Visitor<'de> for StructureVisitor { + type Value = Structure; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a `Structure`: (name: `String`, fields: sequence of `Field`s)") + } + + fn visit_seq>(self, mut seq: A) -> Result { + let name = seq.next_element::()? + .ok_or(de::Error::custom("Expected a name for the `Structure`"))?; + let mut structure: Structure = seq.next_element::()? + .ok_or(de::Error::custom("Expected a sequence of `Field`s"))? + .into(); + structure.set_name(name.as_str()); + + Ok(structure) + } +} + +impl<'de> Deserialize<'de> for Structure { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_tuple(2, StructureVisitor) + } +} + +#[cfg(test)] +mod tests { + extern crate ron; + + use Structure; + + #[test] + fn test_serialize() { + use Array; + use Fraction; + + ::init().unwrap(); + + let s = Structure::builder("test") + .field("f1", &"abc") + .field("f2", &String::from("bcd")) + .field("f3", &123i32) + .field("fraction", &Fraction::new(1, 2)) + .field("array", &Array::new(&[&1, &2])) + .build(); + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let res = ron::ser::to_string_pretty(&s, pretty_config); + assert_eq!( + Ok( + concat!( + "(\"test\", [", + " (\"f1\", \"String\", \"abc\"),", + " (\"f2\", \"String\", \"bcd\"),", + " (\"f3\", \"i32\", 123),", + " (\"fraction\", \"Fraction\", (1, 2)),", + " (\"array\", \"Array\", [", + " (\"i32\", 1),", + " (\"i32\", 2),", + " ]),", + "])" + ) + .to_owned() + ), + res, + ); + } + + #[test] + fn test_deserialize() { + use Array; + use Fraction; + + ::init().unwrap(); + + let s_ron = r#" + ("test", [ + ("f1", "String", "abc"), + ("f2", "String", "bcd"), + ("f3", "i32", 123), + ("fraction", "Fraction", (1, 2)), + ("array", "Array", [ + ("i32", 1), + ("i32", 2), + ]), + ])"#; + let s: Structure = ron::de::from_str(s_ron).unwrap(); + assert_eq!( + s.as_ref(), + Structure::new( + "test", + &[ + ("f1", &"abc"), + ("f2", &"bcd"), + ("f3", &123), + ("fraction", &Fraction::new(1, 2)), + ("array", &Array::new(&[&1, &2])), + ], + ).as_ref() + ); + } +} diff --git a/gstreamer/src/tags.rs b/gstreamer/src/tags.rs index 58ff76c04..15098c9aa 100644 --- a/gstreamer/src/tags.rs +++ b/gstreamer/src/tags.rs @@ -522,232 +522,6 @@ impl StaticType for TagListRef { } } -#[cfg(feature = "ser_de")] -mod serde { - use glib::translate::from_glib_none; - use glib::{ToValue, Value}; - use gobject_ffi; - - use serde::de; - use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; - use serde::ser; - use serde::ser::{Serialize, Serializer, SerializeSeq, SerializeTuple}; - - use super::*; - use std::ffi::CString; - - use DateTime; - use Sample; - use value::serde::{DATE_TIME_OTHER_TYPE_ID, SAMPLE_OTHER_TYPE_ID}; - - struct TagSer<'a>(&'a str, Value); - - macro_rules! ser_tag ( - ($tag_ser:ident, $ser:ident, $t:ty) => ( - ser_value!($tag_ser.1, $tag_ser.0, $t, |tag_name, value| { - let mut tup = $ser.serialize_tuple(2)?; - tup.serialize_element(tag_name)?; - tup.serialize_element(&value)?; - tup.end() - }) - ); - ); - - impl<'a> Serialize for TagSer<'a> { - fn serialize(&self, serializer: S) -> Result { - match self.1.type_() { - glib::Type::F64 => ser_tag!(self, serializer, f64), - glib::Type::String => ser_tag!(self, serializer, String), - glib::Type::U32 => ser_tag!(self, serializer, u32), - glib::Type::U64 => ser_tag!(self, serializer, u64), - glib::Type::Other(type_id) => { - if *DATE_TIME_OTHER_TYPE_ID == type_id { - ser_tag!(self, serializer, DateTime) - } else if *SAMPLE_OTHER_TYPE_ID == type_id { - ser_tag!(self, serializer, Sample) - } else { - Err( - ser::Error::custom( - format!("unimplemented Tag serialization for type {}", - glib::Type::Other(type_id), - ) - ) - ) - } - } - type_ => { - Err( - ser::Error::custom( - format!("unimplemented Tag serialization for type {}", type_) - ) - ) - } - } - } - } - - impl Serialize for TagListRef { - fn serialize(&self, serializer: S) -> Result { - let tag_count = unsafe { ffi::gst_tag_list_n_tags(self.as_ptr()) }; - if tag_count > 0 { - let mut seq = serializer.serialize_seq(Some(tag_count as usize))?; - for name_index in 0..tag_count { - unsafe { - let tag_name = ffi::gst_tag_list_nth_tag_name(self.as_ptr(), name_index as u32); - let tag_size = ffi::gst_tag_list_get_tag_size(self.as_ptr(), tag_name); - for tag_index in 0..tag_size { - let value = ffi::gst_tag_list_get_value_index( - self.as_ptr(), - tag_name, - tag_index, - ); - - if !value.is_null() { - let tag_name = CStr::from_ptr(tag_name) - .to_str() - .map_err(|_| { - ser::Error::custom( - format!( - "invalid UTF-8 characters in Tag name {:?}", - tag_name, - ) - ) - })?; - seq.serialize_element( - &TagSer( - tag_name, - from_glib_none(value as *mut gobject_ffi::GValue), - ) - )? - } - } - } - } - seq.end() - } else if tag_count == 0 { - let seq = serializer.serialize_seq(None)?; - seq.end() - } else { - Err(ser::Error::custom("tag count < 0")) - } - } - } - - impl Serialize for TagList { - fn serialize(&self, serializer: S) -> Result { - self.as_ref().serialize(serializer) - } - } - - struct TagDe(CString, Value); - struct TagVisitor; - - macro_rules! de_tag_value( - ($tag_name:expr, $seq:expr, $t:ty) => ( - { - let value = de_value!("Tag", $tag_name, $seq, $t); - TagDe($tag_name, value) - } - ); - ); - - impl<'de> Visitor<'de> for TagVisitor { - type Value = TagDe; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a tuple of 2 elements (name: String, value: Tag value type)") - } - - fn visit_seq>(self, mut seq: A) -> Result { - let name = CString::new( - seq - .next_element::() - .map_err(|err| de::Error::custom( - format!("Error reading Tag name. {:?}", err) - ))? - .ok_or(de::Error::custom("Expected a value for Tag name, found `None`"))? - .as_str() - ).unwrap(); - - unsafe { - let type_: glib::Type = from_glib(ffi::gst_tag_get_type(name.as_ptr() as *const i8)); - let tag_de = match type_ { - glib::Type::F64 => de_tag_value!(name, seq, f64), - glib::Type::String => de_tag_value!(name, seq, String), - glib::Type::U32 => de_tag_value!(name, seq, u32), - glib::Type::U64 => de_tag_value!(name, seq, u64), - glib::Type::Other(type_id) => { - if *DATE_TIME_OTHER_TYPE_ID == type_id { - de_tag_value!(name, seq, DateTime) - } else if *SAMPLE_OTHER_TYPE_ID == type_id { - de_tag_value!(name, seq, Sample) - } else { - return Err( - de::Error::custom( - format!( - "unimplemented deserialization for Tag {:?} with type `{}`", - name, - glib::Type::Other(type_id), - ), - ) - ); - } - } - type_ => { - return Err( - de::Error::custom( - format!( - "unimplemented deserialization for Tag {:?} with type `{}`", - name, - type_, - ), - ) - ); - } - }; - - Ok(tag_de) - } - } - } - - impl<'de> Deserialize<'de> for TagDe { - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_tuple(2, TagVisitor{}) // 2 items in the tuple: (name, value) - } - } - - struct TagListVisitor; - impl<'de> Visitor<'de> for TagListVisitor { - type Value = TagList; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a sequence of Tags") - } - - fn visit_seq>(self, mut seq: A) -> Result { - let tag_list = TagList::new(); - while let Some(tag_de) = seq.next_element::()? { - unsafe { - ffi::gst_tag_list_add_value( - tag_list.as_mut_ptr(), - ffi::GST_TAG_MERGE_APPEND, - tag_de.0.as_ptr(), - tag_de.1.to_glib_none().0, - ); - } - } - Ok(tag_list) - } - } - - impl<'de> Deserialize<'de> for TagList { - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_seq(TagListVisitor) - } - } -} - unsafe impl Sync for TagListRef {} unsafe impl Send for TagListRef {} @@ -1073,193 +847,4 @@ mod tests { assert_eq!(first_duration.get(), Some(::SECOND * 120)); assert!(tag_iter.next().is_none()); } - - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize() { - extern crate ron; - - use Buffer; - use GenericFormattedValue; - - ::init().unwrap(); - - let mut tags = TagList::new(); - assert_eq!(tags.to_string(), "taglist;"); - { - let tags = tags.get_mut().unwrap(); - tags.add::(&"a title", TagMergeMode::Append); // String - tags.add::<Title>(&"another title", TagMergeMode::Append); // String - tags.add::<Duration>(&(::SECOND * 120).into(), TagMergeMode::Append); // u64 - tags.add::<Bitrate>(&96_000, TagMergeMode::Append); // u32 - tags.add::<TrackGain>(&1f64, TagMergeMode::Append); // f64 - tags.add::<DateTime>( - &::DateTime::new(2f32, 2018, 5, 28, 16, 6, 42.841f64), - TagMergeMode::Append, - ); // DateTime - - let sample = { - let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); - { - let buffer = buffer.get_mut().unwrap(); - buffer.set_offset(0); - buffer.set_offset_end(0); - } - Sample::new::<GenericFormattedValue>( - Some(&buffer), - None, - None, - None, - ) - }; - tags.add::<Image>(&sample, TagMergeMode::Append); // Sample - } - - let mut pretty_config = ron::ser::PrettyConfig::default(); - pretty_config.new_line = "".to_string(); - - let res = ron::ser::to_string_pretty(&tags, pretty_config); - assert_eq!( - Ok( - concat!( - "[", - " (\"title\", \"a title\"),", - " (\"title\", \"another title\"),", - " (\"duration\", 120000000000),", - " (\"bitrate\", 96000),", - " (\"replaygain-track-gain\", 1),", - " (\"datetime\", (", - " tz_offset: 2,", - " y: 2018,", - " m: 5,", - " d: 28,", - " h: 16,", - " mn: 6,", - " s: 42,", - " us: 841000,", - " )),", - " (\"image\", (", - " buffer: Some((", - " pts: None,", - " dts: None,", - " duration: None,", - " offset: 0,", - " offset_end: 0,", - " flags: (", - " bits: 0,", - " ),", - " buffer: \"AQIDBA==\",", - " )),", - " buffer_list: None,", - " caps: None,", - " segment: Some((", - " flags: (", - " bits: 0,", - " ),", - " rate: 1,", - " applied_rate: 1,", - " format: Time,", - " base: 0,", - " offset: 0,", - " start: 0,", - " stop: -1,", - " time: 0,", - " position: 0,", - " duration: -1,", - " )),", - " info: None,", - " )),", - "]", - ).to_owned() - ), - res, - ); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize() { - extern crate ron; - extern crate serde_json; - - ::init().unwrap(); - - let tag_list_ron = r#" - [ - ("title", "a title"), - ("title", "another title"), - ("duration", 120000000000), - ("bitrate", 96000), - ("replaygain-track-gain", 1), - ("datetime", ( - tz_offset: 2, - y: 2018, - m: 5, - d: 28, - h: 16, - mn: 6, - s: 42, - us: 841000, - )), - ("image", ( - buffer: Some(( - pts: None, - dts: None, - duration: None, - offset: 0, - offset_end: 0, - flags: ( - bits: 0, - ), - buffer: "AQIDBA==", - )), - buffer_list: None, - caps: None, - segment: None, - info: None, - )) - ] - "#; - let tags: TagList = ron::de::from_str(tag_list_ron).unwrap(); - assert_eq!(tags.get_index::<Title>(0).unwrap().get(), Some("a title")); - assert_eq!(tags.get_index::<Title>(1).unwrap().get(), Some("another title")); - assert_eq!(tags.get_index::<Duration>(0).unwrap().get(), Some(::SECOND * 120)); - assert_eq!(tags.get_index::<Bitrate>(0).unwrap().get(), Some(96_000)); - assert_eq!(tags.get_index::<TrackGain>(0).unwrap().get(), Some(1f64)); - let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap(); - assert_eq!(datetime.get_year(), 2018); - assert_eq!(datetime.get_microsecond(), 841_000); - let sample = tags.get_index::<Image>(0).unwrap().get().unwrap(); - let buffer = sample.get_buffer().unwrap(); - { - let data = buffer.map_readable().unwrap(); - assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); - } - - let tag_json = r#" - [ - ["title", "a title"], - ["title", "another title"], - ["duration", 120000000000], - ["bitrate", 96000], - ["replaygain-track-gain", 1.0], - ["datetime",{"tz_offset":2.0,"y":2018,"m":5,"d":28,"h":16,"mn":6,"s":42,"us":841000}], - ["image",{"buffer":{"pts":null,"dts":null,"duration":null,"offset":0,"offset_end":0,"flags":{"bits":0},"buffer":[1,2,3,4]},"buffer_list":null,"caps":null,"segment":null,"info":null}] - ] - "#; - let tags: TagList = serde_json::from_str(tag_json).unwrap(); - assert_eq!(tags.get_index::<Title>(0).unwrap().get(), Some("a title")); - assert_eq!(tags.get_index::<Title>(1).unwrap().get(), Some("another title")); - assert_eq!(tags.get_index::<Bitrate>(0).unwrap().get(), Some(96_000)); - assert_eq!(tags.get_index::<TrackGain>(0).unwrap().get(), Some(1f64)); - let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap(); - assert_eq!(datetime.get_month(), 5); - assert_eq!(datetime.get_hour(), 16); - let sample = tags.get_index::<Image>(0).unwrap().get().unwrap(); - let buffer = sample.get_buffer().unwrap(); - { - let data = buffer.map_readable().unwrap(); - assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); - } - } } diff --git a/gstreamer/src/tags_serde.rs b/gstreamer/src/tags_serde.rs new file mode 100644 index 000000000..e7760590d --- /dev/null +++ b/gstreamer/src/tags_serde.rs @@ -0,0 +1,429 @@ +// Copyright (C) 2018 François Laignel <fengalin@free.fr> +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi; +use glib; +use glib::translate::{ToGlibPtr, from_glib, from_glib_none}; +use glib::{ToValue, Value}; +use gobject_ffi; + +use serde::de; +use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; +use serde::ser; +use serde::ser::{Serialize, Serializer, SerializeSeq, SerializeTuple}; + +use std::ffi::CStr; +use std::ffi::CString; +use std::fmt; + +use DateTime; +use Sample; +use miniobject::MiniObject; +use tags::*; +use value_serde::{DATE_TIME_OTHER_TYPE_ID, SAMPLE_OTHER_TYPE_ID}; + +struct TagSer<'a>(&'a str, Value); + +macro_rules! ser_tag ( + ($tag_ser:ident, $ser:ident, $t:ty) => ( + ser_value!($tag_ser.1, $tag_ser.0, $t, |tag_name, value| { + let mut tup = $ser.serialize_tuple(2)?; + tup.serialize_element(tag_name)?; + tup.serialize_element(&value)?; + tup.end() + }) + ); +); + +impl<'a> Serialize for TagSer<'a> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match self.1.type_() { + glib::Type::F64 => ser_tag!(self, serializer, f64), + glib::Type::String => ser_tag!(self, serializer, String), + glib::Type::U32 => ser_tag!(self, serializer, u32), + glib::Type::U64 => ser_tag!(self, serializer, u64), + glib::Type::Other(type_id) => { + if *DATE_TIME_OTHER_TYPE_ID == type_id { + ser_tag!(self, serializer, DateTime) + } else if *SAMPLE_OTHER_TYPE_ID == type_id { + ser_tag!(self, serializer, Sample) + } else { + Err( + ser::Error::custom( + format!("unimplemented Tag serialization for type {}", + glib::Type::Other(type_id), + ) + ) + ) + } + } + type_ => { + Err( + ser::Error::custom( + format!("unimplemented Tag serialization for type {}", type_) + ) + ) + } + } + } +} + +impl Serialize for TagListRef { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let tag_count = unsafe { ffi::gst_tag_list_n_tags(self.as_ptr()) }; + if tag_count > 0 { + let mut seq = serializer.serialize_seq(Some(tag_count as usize))?; + for name_index in 0..tag_count { + unsafe { + let tag_name = ffi::gst_tag_list_nth_tag_name(self.as_ptr(), name_index as u32); + let tag_size = ffi::gst_tag_list_get_tag_size(self.as_ptr(), tag_name); + for tag_index in 0..tag_size { + let value = ffi::gst_tag_list_get_value_index( + self.as_ptr(), + tag_name, + tag_index, + ); + + if !value.is_null() { + let tag_name = CStr::from_ptr(tag_name) + .to_str() + .map_err(|_| { + ser::Error::custom( + format!( + "invalid UTF-8 characters in Tag name {:?}", + tag_name, + ) + ) + })?; + seq.serialize_element( + &TagSer( + tag_name, + from_glib_none(value as *mut gobject_ffi::GValue), + ) + )? + } + } + } + } + seq.end() + } else if tag_count == 0 { + let seq = serializer.serialize_seq(None)?; + seq.end() + } else { + Err(ser::Error::custom("tag count < 0")) + } + } +} + +impl Serialize for TagList { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + self.as_ref().serialize(serializer) + } +} + +struct TagDe(CString, Value); +struct TagVisitor; + +macro_rules! de_tag_value( + ($tag_name:expr, $seq:expr, $t:ty) => ( + { + let value = de_value!("Tag", $tag_name, $seq, $t); + TagDe($tag_name, value) + } + ); +); + +impl<'de> Visitor<'de> for TagVisitor { + type Value = TagDe; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a tuple of 2 elements (name: String, value: Tag value type)") + } + + fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> { + let name = CString::new( + seq + .next_element::<String>() + .map_err(|err| de::Error::custom( + format!("Error reading Tag name. {:?}", err) + ))? + .ok_or(de::Error::custom("Expected a value for Tag name"))? + .as_str() + ).unwrap(); + + unsafe { + let type_: glib::Type = from_glib(ffi::gst_tag_get_type(name.as_ptr() as *const i8)); + let tag_de = match type_ { + glib::Type::F64 => de_tag_value!(name, seq, f64), + glib::Type::String => de_tag_value!(name, seq, String), + glib::Type::U32 => de_tag_value!(name, seq, u32), + glib::Type::U64 => de_tag_value!(name, seq, u64), + glib::Type::Other(type_id) => { + if *DATE_TIME_OTHER_TYPE_ID == type_id { + de_tag_value!(name, seq, DateTime) + } else if *SAMPLE_OTHER_TYPE_ID == type_id { + de_tag_value!(name, seq, Sample) + } else { + return Err( + de::Error::custom( + format!( + "unimplemented deserialization for Tag {:?} with type `{}`", + name, + glib::Type::Other(type_id), + ), + ) + ); + } + } + type_ => { + return Err( + de::Error::custom( + format!( + "unimplemented deserialization for Tag {:?} with type `{}`", + name, + type_, + ), + ) + ); + } + }; + + Ok(tag_de) + } + } +} + +impl<'de> Deserialize<'de> for TagDe { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + deserializer.deserialize_tuple(2, TagVisitor{}) // 2 items in the tuple: (name, value) + } +} + +struct TagListVisitor; +impl<'de> Visitor<'de> for TagListVisitor { + type Value = TagList; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence of Tags") + } + + fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> { + let tag_list = TagList::new(); + while let Some(tag_de) = seq.next_element::<TagDe>()? { + unsafe { + ffi::gst_tag_list_add_value( + tag_list.as_mut_ptr(), + ffi::GST_TAG_MERGE_APPEND, + tag_de.0.as_ptr(), + tag_de.1.to_glib_none().0, + ); + } + } + Ok(tag_list) + } +} + +impl<'de> Deserialize<'de> for TagList { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + deserializer.deserialize_seq(TagListVisitor) + } +} + + +#[cfg(test)] +mod tests { + extern crate ron; + + use tags::*; + + #[test] + fn test_serialize() { + use Buffer; + use GenericFormattedValue; + use TagMergeMode; + use Sample; + + ::init().unwrap(); + + let mut tags = TagList::new(); + assert_eq!(tags.to_string(), "taglist;"); + { + let tags = tags.get_mut().unwrap(); + tags.add::<Title>(&"a title", TagMergeMode::Append); // String + tags.add::<Title>(&"another title", TagMergeMode::Append); // String + tags.add::<Duration>(&(::SECOND * 120).into(), TagMergeMode::Append); // u64 + tags.add::<Bitrate>(&96_000, TagMergeMode::Append); // u32 + tags.add::<TrackGain>(&1f64, TagMergeMode::Append); // f64 + tags.add::<DateTime>( + &::DateTime::new(2f32, 2018, 5, 28, 16, 6, 42.841f64), + TagMergeMode::Append, + ); // DateTime + + let sample = { + let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_offset(0); + buffer.set_offset_end(0); + } + Sample::new::<GenericFormattedValue>( + Some(&buffer), + None, + None, + None, + ) + }; + tags.add::<Image>(&sample, TagMergeMode::Append); // Sample + } + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let res = ron::ser::to_string_pretty(&tags, pretty_config); + assert_eq!( + Ok( + concat!( + "[", + " (\"title\", \"a title\"),", + " (\"title\", \"another title\"),", + " (\"duration\", 120000000000),", + " (\"bitrate\", 96000),", + " (\"replaygain-track-gain\", 1),", + " (\"datetime\", (", + " tz_offset: 2,", + " y: 2018,", + " m: 5,", + " d: 28,", + " h: 16,", + " mn: 6,", + " s: 42,", + " us: 841000,", + " )),", + " (\"image\", (", + " buffer: Some((", + " pts: None,", + " dts: None,", + " duration: None,", + " offset: 0,", + " offset_end: 0,", + " flags: (", + " bits: 0,", + " ),", + " buffer: \"AQIDBA==\",", + " )),", + " buffer_list: None,", + " caps: None,", + " segment: Some((", + " flags: (", + " bits: 0,", + " ),", + " rate: 1,", + " applied_rate: 1,", + " format: Time,", + " base: 0,", + " offset: 0,", + " start: 0,", + " stop: -1,", + " time: 0,", + " position: 0,", + " duration: -1,", + " )),", + " info: None,", + " )),", + "]", + ).to_owned() + ), + res, + ); + } + + #[test] + fn test_deserialize() { + extern crate serde_json; + + ::init().unwrap(); + + let tag_list_ron = r#" + [ + ("title", "a title"), + ("title", "another title"), + ("duration", 120000000000), + ("bitrate", 96000), + ("replaygain-track-gain", 1), + ("datetime", ( + tz_offset: 2, + y: 2018, + m: 5, + d: 28, + h: 16, + mn: 6, + s: 42, + us: 841000, + )), + ("image", ( + buffer: Some(( + pts: None, + dts: None, + duration: None, + offset: 0, + offset_end: 0, + flags: ( + bits: 0, + ), + buffer: "AQIDBA==", + )), + buffer_list: None, + caps: None, + segment: None, + info: None, + )) + ] + "#; + let tags: TagList = ron::de::from_str(tag_list_ron).unwrap(); + assert_eq!(tags.get_index::<Title>(0).unwrap().get(), Some("a title")); + assert_eq!(tags.get_index::<Title>(1).unwrap().get(), Some("another title")); + assert_eq!(tags.get_index::<Duration>(0).unwrap().get(), Some(::SECOND * 120)); + assert_eq!(tags.get_index::<Bitrate>(0).unwrap().get(), Some(96_000)); + assert_eq!(tags.get_index::<TrackGain>(0).unwrap().get(), Some(1f64)); + let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap(); + assert_eq!(datetime.get_year(), 2018); + assert_eq!(datetime.get_microsecond(), 841_000); + let sample = tags.get_index::<Image>(0).unwrap().get().unwrap(); + let buffer = sample.get_buffer().unwrap(); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + + let tag_json = r#" + [ + ["title", "a title"], + ["title", "another title"], + ["duration", 120000000000], + ["bitrate", 96000], + ["replaygain-track-gain", 1.0], + ["datetime",{"tz_offset":2.0,"y":2018,"m":5,"d":28,"h":16,"mn":6,"s":42,"us":841000}], + ["image",{"buffer":{"pts":null,"dts":null,"duration":null,"offset":0,"offset_end":0,"flags":{"bits":0},"buffer":[1,2,3,4]},"buffer_list":null,"caps":null,"segment":null,"info":null}] + ] + "#; + let tags: TagList = serde_json::from_str(tag_json).unwrap(); + assert_eq!(tags.get_index::<Title>(0).unwrap().get(), Some("a title")); + assert_eq!(tags.get_index::<Title>(1).unwrap().get(), Some("another title")); + assert_eq!(tags.get_index::<Bitrate>(0).unwrap().get(), Some(96_000)); + assert_eq!(tags.get_index::<TrackGain>(0).unwrap().get(), Some(1f64)); + let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap(); + assert_eq!(datetime.get_month(), 5); + assert_eq!(datetime.get_hour(), 16); + let sample = tags.get_index::<Image>(0).unwrap().get().unwrap(); + let buffer = sample.get_buffer().unwrap(); + { + let data = buffer.map_readable().unwrap(); + assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); + } + } +} diff --git a/gstreamer/src/toc.rs b/gstreamer/src/toc.rs index c87a75a70..5ae0f28c2 100644 --- a/gstreamer/src/toc.rs +++ b/gstreamer/src/toc.rs @@ -263,122 +263,6 @@ impl fmt::Debug for TocEntryRef { unsafe impl Sync for TocEntryRef {} unsafe impl Send for TocEntryRef {} -#[cfg(feature = "ser_de")] -mod serde { - use serde::de::{Deserialize, Deserializer}; - use serde::ser::{Serialize, Serializer, SerializeStruct}; - - use tags::*; - use super::*; - - impl Serialize for TocRef { - fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - let mut toc = serializer.serialize_struct("Toc", 3)?; - toc.serialize_field("scope", &self.get_scope())?; - toc.serialize_field("tags", &self.get_tags())?; - toc.serialize_field("entries", &self.get_entries())?; - toc.end() - } - } - - impl Serialize for Toc { - fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - self.as_ref().serialize(serializer) - } - } - - impl Serialize for TocEntryRef { - fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - let mut toc_entry = serializer.serialize_struct("TocEntry", 6)?; - toc_entry.serialize_field("entry_type", &self.get_entry_type())?; - toc_entry.serialize_field("uid", &self.get_uid())?; - toc_entry.serialize_field("start_stop", &self.get_start_stop_times())?; - toc_entry.serialize_field("tags", &self.get_tags())?; - toc_entry.serialize_field("loop_", &self.get_loop())?; - toc_entry.serialize_field("sub_entries", &self.get_sub_entries())?; - toc_entry.end() - } - } - - impl Serialize for TocEntry { - fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - self.as_ref().serialize(serializer) - } - } - - #[derive(Deserialize)] - struct TocDe { - scope: TocScope, - tags: Option<TagList>, - entries: Vec<TocEntry>, - } - - impl From<TocDe> for Toc { - fn from(mut toc_de: TocDe) -> Self { - let mut toc = Toc::new(toc_de.scope); - { - let toc = toc.get_mut().unwrap(); - if let Some(tags) = toc_de.tags.take() { - toc.set_tags(tags); - } - let entry_iter = toc_de.entries.drain(..); - for entry in entry_iter { - toc.append_entry(entry); - } - } - toc - } - } - - impl<'de> Deserialize<'de> for Toc { - fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { - TocDe::deserialize(deserializer) - .and_then(|toc_de| Ok(toc_de.into())) - } - } - - #[derive(Deserialize)] - struct TocEntryDe { - entry_type: TocEntryType, - uid: String, - start_stop: Option<(i64, i64)>, - tags: Option<TagList>, - loop_: Option<(TocLoopType, i32)>, - sub_entries: Vec<TocEntry>, - } - - impl From<TocEntryDe> for TocEntry { - fn from(mut toc_entry_de: TocEntryDe) -> Self { - let mut toc_entry = TocEntry::new(toc_entry_de.entry_type, toc_entry_de.uid.as_str()); - { - let toc_entry = toc_entry.get_mut().unwrap(); - if let Some(start_stop) = toc_entry_de.start_stop.take() { - toc_entry.set_start_stop_times(start_stop.0, start_stop.1); - } - if let Some(tags) = toc_entry_de.tags.take() { - toc_entry.set_tags(tags); - } - if let Some(loop_) = toc_entry_de.loop_.take() { - toc_entry.set_loop(loop_.0, loop_.1); - } - - let entry_iter = toc_entry_de.sub_entries.drain(..); - for sub_entries in entry_iter { - toc_entry.append_sub_entry(sub_entries); - } - } - toc_entry - } - } - - impl<'de> Deserialize<'de> for TocEntry { - fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { - TocEntryDe::deserialize(deserializer) - .and_then(|toc_entry_de| Ok(toc_entry_de.into())) - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -427,257 +311,4 @@ mod tests { assert!(parent.is_some()); assert_eq!(parent.unwrap().get_entry_type(), TocEntryType::Chapter); } - - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize() { - extern crate ron; - - use tags::Title; - use super::*; - - ::init().unwrap(); - - let mut toc = Toc::new(TocScope::Global); - { - let toc = toc.get_mut().unwrap(); - let mut tags = TagList::new(); - tags.get_mut().unwrap().add::<Title>(&"toc", TagMergeMode::Append); - toc.set_tags(tags); - - let mut toc_edition = TocEntry::new(TocEntryType::Edition, "edition"); - { - let toc_edition = toc_edition.get_mut().unwrap(); - toc_edition.set_start_stop_times(0, 15); - - let mut toc_chap_1 = TocEntry::new(TocEntryType::Chapter, "chapter1"); - { - let toc_chap_1 = toc_chap_1.get_mut().unwrap(); - toc_chap_1.set_start_stop_times(0, 10); - let mut toc_chap_1_1 = TocEntry::new(TocEntryType::Chapter, "chapter1.1"); - { - let toc_chap_1_1 = toc_chap_1_1.get_mut().unwrap(); - toc_chap_1_1.set_start_stop_times(0, 4); - let mut tags = TagList::new(); - tags.get_mut().unwrap().add::<Title>(&"chapter 1.1", TagMergeMode::Append); - toc_chap_1_1.set_tags(tags); - } - toc_chap_1.append_sub_entry(toc_chap_1_1); - - let mut toc_chap_1_2 = TocEntry::new(TocEntryType::Chapter, "chapter1.2"); - { - let toc_chap_1_2 = toc_chap_1_2.get_mut().unwrap(); - toc_chap_1_2.set_start_stop_times(4, 10); - let mut tags = TagList::new(); - tags.get_mut().unwrap().add::<Title>(&"chapter 1.2", TagMergeMode::Append); - toc_chap_1_2.set_tags(tags); - } - toc_chap_1.append_sub_entry(toc_chap_1_2); - } - toc_edition.append_sub_entry(toc_chap_1); - - let mut toc_chap_2 = TocEntry::new(TocEntryType::Chapter, "chapter2"); - { - let toc_chap_2 = toc_chap_2.get_mut().unwrap(); - toc_chap_2.set_start_stop_times(10, 15); - let mut tags = TagList::new(); - tags.get_mut().unwrap().add::<Title>(&"chapter 2", TagMergeMode::Append); - toc_chap_2.set_tags(tags); - } - toc_edition.append_sub_entry(toc_chap_2); - } - toc.append_entry(toc_edition); - } - - // 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(&toc, pretty_config); - assert_eq!( - Ok( - concat!( - "(", - " scope: Global,", - " tags: Some([", - " (\"title\", \"toc\"),", - " ]),", - " entries: [", - " (", - " entry_type: Edition,", - " uid: \"edition\",", - " start_stop: Some((0, 15)),", - " tags: None,", - " loop_: Some((None, 0)),", - " sub_entries: [", - " (", - " entry_type: Chapter,", - " uid: \"chapter1\",", - " start_stop: Some((0, 10)),", - " tags: None,", - " loop_: Some((None, 0)),", - " sub_entries: [", - " (", - " entry_type: Chapter,", - " uid: \"chapter1.1\",", - " start_stop: Some((0, 4)),", - " tags: Some([", - " (\"title\", \"chapter 1.1\"),", - " ]),", - " loop_: Some((None, 0)),", - " sub_entries: [", - " ],", - " ),", - " (", - " entry_type: Chapter,", - " uid: \"chapter1.2\",", - " start_stop: Some((4, 10)),", - " tags: Some([", - " (\"title\", \"chapter 1.2\"),", - " ]),", - " loop_: Some((None, 0)),", - " sub_entries: [", - " ],", - " ),", - " ],", - " ),", - " (", - " entry_type: Chapter,", - " uid: \"chapter2\",", - " start_stop: Some((10, 15)),", - " tags: Some([", - " (\"title\", \"chapter 2\"),", - " ]),", - " loop_: Some((None, 0)),", - " sub_entries: [", - " ],", - " ),", - " ],", - " ),", - " ],", - ")", - ).to_owned() - ), - res, - ); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize() { - extern crate ron; - - use tags::Title; - - ::init().unwrap(); - - let toc_ron = r#" - ( - scope: Global, - tags: Some([ - ("title", "toc"), - ]), - entries: [ - ( - entry_type: Edition, - uid: "edition", - start_stop: Some((0, 15)), - tags: None, - loop_: Some((None, 0)), - sub_entries: [ - ( - entry_type: Chapter, - uid: "chapter1", - start_stop: Some((0, 10)), - tags: None, - loop_: Some((None, 0)), - sub_entries: [ - ( - entry_type: Chapter, - uid: "chapter1.1", - start_stop: Some((0, 4)), - tags: Some([ - ("title", "chapter 1.1"), - ]), - loop_: Some((None, 0)), - sub_entries: [ - ], - ), - ( - entry_type: Chapter, - uid: "chapter1.2", - start_stop: Some((4, 10)), - tags: Some([ - ("title", "chapter 1.2"), - ]), - loop_: Some((None, 0)), - sub_entries: [ - ], - ), - ], - ), - ( - entry_type: Chapter, - uid: "chapter2", - start_stop: Some((10, 15)), - tags: Some([ - ("title", "chapter 2"), - ]), - loop_: Some((None, 0)), - sub_entries: [ - ], - ), - ], - ), - ], - ) - "#; - let toc: Toc = ron::de::from_str(toc_ron).unwrap(); - assert_eq!(toc.get_scope(), TocScope::Global); - - let entries = toc.get_entries(); - assert_eq!(1, entries.len()); - - let edition = &entries[0]; - assert_eq!(TocEntryType::Edition, edition.get_entry_type()); - assert_eq!("edition", edition.get_uid()); - assert!(edition.get_tags().is_none()); - assert_eq!(Some((0, 15)), edition.get_start_stop_times()); - - let sub_entries = edition.get_sub_entries(); - assert_eq!(2, sub_entries.len()); - - let chapter1 = &sub_entries[0]; - assert_eq!(TocEntryType::Chapter, chapter1.get_entry_type()); - assert_eq!("chapter1", chapter1.get_uid()); - assert!(chapter1.get_tags().is_none()); - assert_eq!(Some((0, 10)), chapter1.get_start_stop_times()); - - let chap1_sub_entries = chapter1.get_sub_entries(); - assert_eq!(2, sub_entries.len()); - - let chapter1_1 = &chap1_sub_entries[0]; - assert_eq!(TocEntryType::Chapter, chapter1_1.get_entry_type()); - assert_eq!("chapter1.1", chapter1_1.get_uid()); - assert_eq!(Some((0, 4)), chapter1_1.get_start_stop_times()); - let tags = chapter1_1.get_tags().unwrap(); - assert_eq!(Some("chapter 1.1"), tags.get_index::<Title>(0).unwrap().get()); - assert_eq!(0, chapter1_1.get_sub_entries().len()); - - let chapter1_2 = &chap1_sub_entries[1]; - assert_eq!(TocEntryType::Chapter, chapter1_2.get_entry_type()); - assert_eq!("chapter1.2", chapter1_2.get_uid()); - assert_eq!(Some((4, 10)), chapter1_2.get_start_stop_times()); - let tags = chapter1_2.get_tags().unwrap(); - assert_eq!(Some("chapter 1.2"), tags.get_index::<Title>(0).unwrap().get()); - assert_eq!(0, chapter1_2.get_sub_entries().len()); - - let chapter2 = &sub_entries[1]; - assert_eq!(TocEntryType::Chapter, chapter2.get_entry_type()); - assert_eq!("chapter2", chapter2.get_uid()); - let tags = chapter2.get_tags().unwrap(); - assert_eq!(Some("chapter 2"), tags.get_index::<Title>(0).unwrap().get()); - assert_eq!(Some((10, 15)), chapter2.get_start_stop_times()); - assert_eq!(0, chapter2.get_sub_entries().len()); - } } diff --git a/gstreamer/src/toc_serde.rs b/gstreamer/src/toc_serde.rs new file mode 100644 index 000000000..5f0838727 --- /dev/null +++ b/gstreamer/src/toc_serde.rs @@ -0,0 +1,379 @@ +// Copyright (C) 2018 François Laignel <fengalin@free.fr> +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use serde::de::{Deserialize, Deserializer}; +use serde::ser::{Serialize, Serializer, SerializeStruct}; + +use toc::*; +use TagList; +use TocEntryType; +use TocScope; +use TocLoopType; + +impl Serialize for TocRef { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut toc = serializer.serialize_struct("Toc", 3)?; + toc.serialize_field("scope", &self.get_scope())?; + toc.serialize_field("tags", &self.get_tags())?; + toc.serialize_field("entries", &self.get_entries())?; + toc.end() + } +} + +impl Serialize for Toc { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + self.as_ref().serialize(serializer) + } +} + +impl Serialize for TocEntryRef { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut toc_entry = serializer.serialize_struct("TocEntry", 6)?; + toc_entry.serialize_field("entry_type", &self.get_entry_type())?; + toc_entry.serialize_field("uid", &self.get_uid())?; + toc_entry.serialize_field("start_stop", &self.get_start_stop_times())?; + toc_entry.serialize_field("tags", &self.get_tags())?; + toc_entry.serialize_field("loop_", &self.get_loop())?; + toc_entry.serialize_field("sub_entries", &self.get_sub_entries())?; + toc_entry.end() + } +} + +impl Serialize for TocEntry { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + self.as_ref().serialize(serializer) + } +} + +#[derive(Deserialize)] +struct TocDe { + scope: TocScope, + tags: Option<TagList>, + entries: Vec<TocEntry>, +} + +impl From<TocDe> for Toc { + fn from(mut toc_de: TocDe) -> Self { + let mut toc = Toc::new(toc_de.scope); + { + let toc = toc.get_mut().unwrap(); + if let Some(tags) = toc_de.tags.take() { + toc.set_tags(tags); + } + let entry_iter = toc_de.entries.drain(..); + for entry in entry_iter { + toc.append_entry(entry); + } + } + toc + } +} + +impl<'de> Deserialize<'de> for Toc { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + TocDe::deserialize(deserializer) + .and_then(|toc_de| Ok(toc_de.into())) + } +} + +#[derive(Deserialize)] +struct TocEntryDe { + entry_type: TocEntryType, + uid: String, + start_stop: Option<(i64, i64)>, + tags: Option<TagList>, + loop_: Option<(TocLoopType, i32)>, + sub_entries: Vec<TocEntry>, +} + +impl From<TocEntryDe> for TocEntry { + fn from(mut toc_entry_de: TocEntryDe) -> Self { + let mut toc_entry = TocEntry::new(toc_entry_de.entry_type, toc_entry_de.uid.as_str()); + { + let toc_entry = toc_entry.get_mut().unwrap(); + if let Some(start_stop) = toc_entry_de.start_stop.take() { + toc_entry.set_start_stop_times(start_stop.0, start_stop.1); + } + if let Some(tags) = toc_entry_de.tags.take() { + toc_entry.set_tags(tags); + } + if let Some(loop_) = toc_entry_de.loop_.take() { + toc_entry.set_loop(loop_.0, loop_.1); + } + + let entry_iter = toc_entry_de.sub_entries.drain(..); + for sub_entries in entry_iter { + toc_entry.append_sub_entry(sub_entries); + } + } + toc_entry + } +} + +impl<'de> Deserialize<'de> for TocEntry { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + TocEntryDe::deserialize(deserializer) + .and_then(|toc_entry_de| Ok(toc_entry_de.into())) + } +} + +#[cfg(test)] +mod tests { + extern crate ron; + + use TocEntryType; + use TocScope; + use toc::*; + + #[test] + fn test_serialize() { + use TagMergeMode; + use TagList; + use tags::Title; + + ::init().unwrap(); + + let mut toc = Toc::new(TocScope::Global); + { + let toc = toc.get_mut().unwrap(); + let mut tags = TagList::new(); + tags.get_mut().unwrap().add::<Title>(&"toc", TagMergeMode::Append); + toc.set_tags(tags); + + let mut toc_edition = TocEntry::new(TocEntryType::Edition, "edition"); + { + let toc_edition = toc_edition.get_mut().unwrap(); + toc_edition.set_start_stop_times(0, 15); + + let mut toc_chap_1 = TocEntry::new(TocEntryType::Chapter, "chapter1"); + { + let toc_chap_1 = toc_chap_1.get_mut().unwrap(); + toc_chap_1.set_start_stop_times(0, 10); + let mut toc_chap_1_1 = TocEntry::new(TocEntryType::Chapter, "chapter1.1"); + { + let toc_chap_1_1 = toc_chap_1_1.get_mut().unwrap(); + toc_chap_1_1.set_start_stop_times(0, 4); + let mut tags = TagList::new(); + tags.get_mut().unwrap().add::<Title>(&"chapter 1.1", TagMergeMode::Append); + toc_chap_1_1.set_tags(tags); + } + toc_chap_1.append_sub_entry(toc_chap_1_1); + + let mut toc_chap_1_2 = TocEntry::new(TocEntryType::Chapter, "chapter1.2"); + { + let toc_chap_1_2 = toc_chap_1_2.get_mut().unwrap(); + toc_chap_1_2.set_start_stop_times(4, 10); + let mut tags = TagList::new(); + tags.get_mut().unwrap().add::<Title>(&"chapter 1.2", TagMergeMode::Append); + toc_chap_1_2.set_tags(tags); + } + toc_chap_1.append_sub_entry(toc_chap_1_2); + } + toc_edition.append_sub_entry(toc_chap_1); + + let mut toc_chap_2 = TocEntry::new(TocEntryType::Chapter, "chapter2"); + { + let toc_chap_2 = toc_chap_2.get_mut().unwrap(); + toc_chap_2.set_start_stop_times(10, 15); + let mut tags = TagList::new(); + tags.get_mut().unwrap().add::<Title>(&"chapter 2", TagMergeMode::Append); + toc_chap_2.set_tags(tags); + } + toc_edition.append_sub_entry(toc_chap_2); + } + toc.append_entry(toc_edition); + } + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + let res = ron::ser::to_string_pretty(&toc, pretty_config); + assert_eq!( + Ok( + concat!( + "(", + " scope: Global,", + " tags: Some([", + " (\"title\", \"toc\"),", + " ]),", + " entries: [", + " (", + " entry_type: Edition,", + " uid: \"edition\",", + " start_stop: Some((0, 15)),", + " tags: None,", + " loop_: Some((None, 0)),", + " sub_entries: [", + " (", + " entry_type: Chapter,", + " uid: \"chapter1\",", + " start_stop: Some((0, 10)),", + " tags: None,", + " loop_: Some((None, 0)),", + " sub_entries: [", + " (", + " entry_type: Chapter,", + " uid: \"chapter1.1\",", + " start_stop: Some((0, 4)),", + " tags: Some([", + " (\"title\", \"chapter 1.1\"),", + " ]),", + " loop_: Some((None, 0)),", + " sub_entries: [", + " ],", + " ),", + " (", + " entry_type: Chapter,", + " uid: \"chapter1.2\",", + " start_stop: Some((4, 10)),", + " tags: Some([", + " (\"title\", \"chapter 1.2\"),", + " ]),", + " loop_: Some((None, 0)),", + " sub_entries: [", + " ],", + " ),", + " ],", + " ),", + " (", + " entry_type: Chapter,", + " uid: \"chapter2\",", + " start_stop: Some((10, 15)),", + " tags: Some([", + " (\"title\", \"chapter 2\"),", + " ]),", + " loop_: Some((None, 0)),", + " sub_entries: [", + " ],", + " ),", + " ],", + " ),", + " ],", + ")", + ).to_owned() + ), + res, + ); + } + + #[test] + fn test_deserialize() { + use tags::Title; + + ::init().unwrap(); + + let toc_ron = r#" + ( + scope: Global, + tags: Some([ + ("title", "toc"), + ]), + entries: [ + ( + entry_type: Edition, + uid: "edition", + start_stop: Some((0, 15)), + tags: None, + loop_: Some((None, 0)), + sub_entries: [ + ( + entry_type: Chapter, + uid: "chapter1", + start_stop: Some((0, 10)), + tags: None, + loop_: Some((None, 0)), + sub_entries: [ + ( + entry_type: Chapter, + uid: "chapter1.1", + start_stop: Some((0, 4)), + tags: Some([ + ("title", "chapter 1.1"), + ]), + loop_: Some((None, 0)), + sub_entries: [ + ], + ), + ( + entry_type: Chapter, + uid: "chapter1.2", + start_stop: Some((4, 10)), + tags: Some([ + ("title", "chapter 1.2"), + ]), + loop_: Some((None, 0)), + sub_entries: [ + ], + ), + ], + ), + ( + entry_type: Chapter, + uid: "chapter2", + start_stop: Some((10, 15)), + tags: Some([ + ("title", "chapter 2"), + ]), + loop_: Some((None, 0)), + sub_entries: [ + ], + ), + ], + ), + ], + ) + "#; + let toc: Toc = ron::de::from_str(toc_ron).unwrap(); + assert_eq!(toc.get_scope(), TocScope::Global); + + let entries = toc.get_entries(); + assert_eq!(1, entries.len()); + + let edition = &entries[0]; + assert_eq!(TocEntryType::Edition, edition.get_entry_type()); + assert_eq!("edition", edition.get_uid()); + assert!(edition.get_tags().is_none()); + assert_eq!(Some((0, 15)), edition.get_start_stop_times()); + + let sub_entries = edition.get_sub_entries(); + assert_eq!(2, sub_entries.len()); + + let chapter1 = &sub_entries[0]; + assert_eq!(TocEntryType::Chapter, chapter1.get_entry_type()); + assert_eq!("chapter1", chapter1.get_uid()); + assert!(chapter1.get_tags().is_none()); + assert_eq!(Some((0, 10)), chapter1.get_start_stop_times()); + + let chap1_sub_entries = chapter1.get_sub_entries(); + assert_eq!(2, sub_entries.len()); + + let chapter1_1 = &chap1_sub_entries[0]; + assert_eq!(TocEntryType::Chapter, chapter1_1.get_entry_type()); + assert_eq!("chapter1.1", chapter1_1.get_uid()); + assert_eq!(Some((0, 4)), chapter1_1.get_start_stop_times()); + let tags = chapter1_1.get_tags().unwrap(); + assert_eq!(Some("chapter 1.1"), tags.get_index::<Title>(0).unwrap().get()); + assert_eq!(0, chapter1_1.get_sub_entries().len()); + + let chapter1_2 = &chap1_sub_entries[1]; + assert_eq!(TocEntryType::Chapter, chapter1_2.get_entry_type()); + assert_eq!("chapter1.2", chapter1_2.get_uid()); + assert_eq!(Some((4, 10)), chapter1_2.get_start_stop_times()); + let tags = chapter1_2.get_tags().unwrap(); + assert_eq!(Some("chapter 1.2"), tags.get_index::<Title>(0).unwrap().get()); + assert_eq!(0, chapter1_2.get_sub_entries().len()); + + let chapter2 = &sub_entries[1]; + assert_eq!(TocEntryType::Chapter, chapter2.get_entry_type()); + assert_eq!("chapter2", chapter2.get_uid()); + let tags = chapter2.get_tags().unwrap(); + assert_eq!(Some("chapter 2"), tags.get_index::<Title>(0).unwrap().get()); + assert_eq!(Some((10, 15)), chapter2.get_start_stop_times()); + assert_eq!(0, chapter2.get_sub_entries().len()); + } +} diff --git a/gstreamer/src/value.rs b/gstreamer/src/value.rs index 4402a8ede..c370f355c 100644 --- a/gstreamer/src/value.rs +++ b/gstreamer/src/value.rs @@ -529,6 +529,12 @@ impl<'a> Array<'a> { Array(values.iter().map(|v| v.to_send_value()).collect()) } + pub fn from_owned(values: Vec<glib::SendValue>) -> Self { + assert_initialized_main_thread!(); + + Array(Cow::Owned(values)) + } + pub fn into_owned(self) -> Array<'static> { Array(self.0.into_owned().into()) } @@ -601,6 +607,12 @@ impl<'a> List<'a> { List(values.iter().map(|v| v.to_send_value()).collect()) } + pub fn from_owned(values: Vec<glib::SendValue>) -> Self { + assert_initialized_main_thread!(); + + List(Cow::Owned(values)) + } + pub fn into_owned(self) -> List<'static> { List(self.0.into_owned().into()) } @@ -857,540 +869,3 @@ impl GstValueExt for glib::Value { } } } - -#[cfg(feature = "ser_de")] -#[macro_use] -pub(crate) mod serde { - use glib; - use glib::{StaticType, ToValue}; - - use num_rational::Rational32; - - use serde::de; - use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; - use serde::ser; - use serde::ser::{Serialize, Serializer, SerializeTuple}; - - use std::mem; - - use DateTime; - use Sample; - - use super::*; - - pub const ARRAY_TYPE_NAME: &'static str = "Array"; - pub const LIST_TYPE_NAME: &'static str = "List"; - - fn get_other_type_id<T: StaticType>() -> usize { - match T::static_type() { - glib::Type::Other(type_id) => type_id, - type_ => panic!("Expecting `Other` variant, found `{}`", type_), - } - } - - lazy_static! { - pub(crate) static ref ARRAY_OTHER_TYPE_ID: usize = get_other_type_id::<Array>(); - pub(crate) static ref BITMASK_OTHER_TYPE_ID: usize = get_other_type_id::<Bitmask>(); - pub(crate) static ref DATE_TIME_OTHER_TYPE_ID: usize = get_other_type_id::<DateTime>(); - pub(crate) static ref FRACTION_OTHER_TYPE_ID: usize = get_other_type_id::<Fraction>(); - pub(crate) static ref FRACTION_RANGE_OTHER_TYPE_ID: usize = - get_other_type_id::<FractionRange>(); - pub(crate) static ref INT_RANGE_I32_OTHER_TYPE_ID: usize = - get_other_type_id::<IntRange<i32>>(); - pub(crate) static ref INT_RANGE_I64_OTHER_TYPE_ID: usize = - get_other_type_id::<IntRange<i64>>(); - pub(crate) static ref LIST_OTHER_TYPE_ID: usize = get_other_type_id::<List>(); - pub(crate) static ref SAMPLE_OTHER_TYPE_ID: usize = get_other_type_id::<Sample>(); - } - - impl<'a> Serialize for Fraction { - fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - self.0.serialize(serializer) - } - } - - impl<'de> Deserialize<'de> for Fraction { - fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { - Rational32::deserialize(deserializer) - .and_then(|rational| Ok(Fraction::new(*rational.numer(), *rational.denom()))) - } - } - - macro_rules! ser_value ( - ($value:expr, $t_str:expr, $t:ty, $ser_closure:expr) => ( - { - let value = $value.get::<$t>().unwrap(); - $ser_closure($t_str, value) - } - ); - ($value:expr, $ser_closure:expr) => ( - match $value.type_() { - glib::Type::I8 => ser_value!($value, "i8", i8, $ser_closure), - glib::Type::U8 => ser_value!($value, "ui8", u8, $ser_closure), - glib::Type::Bool => ser_value!($value, "bool", bool, $ser_closure), - glib::Type::I32 => ser_value!($value, "i32", i32, $ser_closure), - glib::Type::U32 => ser_value!($value, "u32", u32, $ser_closure), - glib::Type::ILong => ser_value!($value, "ilong", i32, $ser_closure), - glib::Type::ULong => ser_value!($value, "ulong", u32, $ser_closure), - glib::Type::I64 => ser_value!($value, "i64", i64, $ser_closure), - glib::Type::U64 => ser_value!($value, "u64", u64, $ser_closure), - glib::Type::F32 => ser_value!($value, "f32", f32, $ser_closure), - glib::Type::F64 => ser_value!($value, "f64", f64, $ser_closure), - glib::Type::String => ser_value!($value, "String", String, $ser_closure), - glib::Type::Other(type_id) => { - if *ARRAY_OTHER_TYPE_ID == type_id { - ser_value!($value, ARRAY_TYPE_NAME, Array, $ser_closure) - } else if *BITMASK_OTHER_TYPE_ID == type_id { - ser_value!($value, "Bitmask", Bitmask, $ser_closure) - } else if *DATE_TIME_OTHER_TYPE_ID == type_id { - ser_value!($value, "DateTime", DateTime, $ser_closure) - } else if *FRACTION_OTHER_TYPE_ID == type_id { - ser_value!($value, "Fraction", Fraction, $ser_closure) - } else if *FRACTION_RANGE_OTHER_TYPE_ID == type_id { - ser_value!($value, "FractionRange", FractionRange, $ser_closure) - } else if *INT_RANGE_I32_OTHER_TYPE_ID == type_id { - ser_value!($value, "IntRange<i32>", IntRange<i32>, $ser_closure) - } else if *INT_RANGE_I64_OTHER_TYPE_ID == type_id { - ser_value!($value, "IntRange<i64>", IntRange<i64>, $ser_closure) - } else if *LIST_OTHER_TYPE_ID == type_id { - ser_value!($value, LIST_TYPE_NAME, List, $ser_closure) - } else if *SAMPLE_OTHER_TYPE_ID == type_id { - ser_value!($value, "Sample", Sample, $ser_closure) - } else { - Err( - ser::Error::custom( - format!("unimplemented `Value` serialization for type {}", - glib::Type::Other(type_id), - ) - ) - ) - } - } - type_ => { - Err( - ser::Error::custom( - format!("unimplemented `Value` serialization for type {}", type_) - ) - ) - } - } - ) - ); - - pub(crate) struct SendValue(glib::SendValue); - impl SendValue { - pub(crate) fn from(send_value: glib::SendValue) -> Self { - SendValue(send_value) - } - } - - impl From<SendValue> for glib::SendValue { - fn from(send_value: SendValue) -> Self { - send_value.0 - } - } - - impl Serialize for SendValue { - fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - ser_value!(self.0, |type_, value| { - let mut tup = serializer.serialize_tuple(2)?; - tup.serialize_element(type_)?; - tup.serialize_element(&value)?; - tup.end() - }) - } - } - - macro_rules! impl_ser_send_value_collection ( - ($t:ident) => ( - impl<'a> Serialize for $t<'a> { - fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - let send_value_vec = unsafe { - mem::transmute::<&[glib::SendValue], &[SendValue]>( - self.as_slice() - ) - }; - send_value_vec.serialize(serializer) - } - } - ); - ); - - impl_ser_send_value_collection!(Array); - impl_ser_send_value_collection!(List); - - macro_rules! de_value( - ($outer_type:expr, $type_name:expr, $seq:expr, $t:ty) => ( - $seq - .next_element::<$t>()? - .ok_or_else(|| - de::Error::custom(format!( - "Expected a value for `{}` with type {:?}, found `None`", - $outer_type, - $type_name, - )) - )? - .to_value() - ); - ); - - macro_rules! de_send_value( - ($type_name:expr, $seq:expr, $t:ty) => ( - SendValue::from( - de_value!("Value", $type_name, $seq, $t) - .try_into_send_value::<$t>() - .map_err(|_| - de::Error::custom(format!( - "Failed to convert `Value` with type {:?} to `SendValue`", - $type_name, - )) - )? - ) - ); - ($type_name:expr, $seq:expr) => ( - match $type_name.as_str() { - "i8" => de_send_value!($type_name, $seq, i8), - "u8" => de_send_value!($type_name, $seq, u8), - "bool" => de_send_value!($type_name, $seq, bool), - "i32" => de_send_value!($type_name, $seq, i32), - "u32" => de_send_value!($type_name, $seq, u32), - "ilong" => de_send_value!($type_name, $seq, i32), - "ulong" => de_send_value!($type_name, $seq, u32), - "i64" => de_send_value!($type_name, $seq, i64), - "u64" => de_send_value!($type_name, $seq, u64), - "f32" => de_send_value!($type_name, $seq, f32), - "f64" => de_send_value!($type_name, $seq, f64), - "String" => de_send_value!($type_name, $seq, String), - "Array" => de_send_value!($type_name, $seq, Array), - "Bitmask" => de_send_value!($type_name, $seq, Bitmask), - "DateTime" => de_send_value!($type_name, $seq, DateTime), - "Fraction" => de_send_value!($type_name, $seq, Fraction), - "FractionRange" => de_send_value!($type_name, $seq, FractionRange), - "IntRange<i32>" => de_send_value!($type_name, $seq, IntRange<i32>), - "IntRange<i64>" => de_send_value!($type_name, $seq, IntRange<i64>), - "Sample" => de_send_value!($type_name, $seq, Sample), - _ => return Err( - de::Error::custom( - format!( - "unimplemented deserialization for `Value` with type `{}`", - $type_name, - ), - ) - ), - } - ); - ); - - struct SendValueVisitor; - impl<'de> Visitor<'de> for SendValueVisitor { - type Value = SendValue; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a tuple of 2 elements (type name: String, value: Value type)") - } - - fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> { - let type_name = seq.next_element::<String>()? - .ok_or(de::Error::custom("Expected a value for `Value` type, found `None`"))?; - Ok(de_send_value!(type_name, seq)) - } - } - - impl<'de> Deserialize<'de> for SendValue { - fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { - deserializer.deserialize_tuple(2, SendValueVisitor{}) - } - } - - macro_rules! impl_de_send_value_collection ( - ($t:ident) => { - impl<'a, 'de> Deserialize<'de> for $t<'a> { - fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { - let send_value_vec = Vec::<SendValue>::deserialize(deserializer)?; - Ok($t(Cow::Owned(unsafe{ - mem::transmute::<Vec<SendValue>, Vec<glib::SendValue>>(send_value_vec) - }))) - } - } - } - ); - - impl_de_send_value_collection!(Array); - impl_de_send_value_collection!(List); -} - -#[cfg(test)] -mod tests { - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize_simple() { - extern crate ron; - extern crate serde_json; - - use Fraction; - use FractionRange; - use IntRange; - use Bitmask; - - ::init().unwrap(); - - let mut pretty_config = ron::ser::PrettyConfig::default(); - pretty_config.new_line = "".to_string(); - - // Fraction - let fraction = Fraction::new(1, 3); - - let res = ron::ser::to_string_pretty(&fraction, pretty_config.clone()); - assert_eq!(Ok("(1, 3)".to_owned()), res); - - let res = serde_json::to_string(&fraction).unwrap(); - assert_eq!("[1,3]".to_owned(), res); - - // FractionRange - let fraction_range = FractionRange::new(Fraction::new(1, 3), Fraction::new(1, 2)); - - let res = ron::ser::to_string_pretty(&fraction_range, pretty_config.clone()); - assert_eq!( - Ok( - concat!( - "(", - " min: (1, 3),", - " max: (1, 2),", - ")" - ) - .to_owned() - ), - res, - ); - - let res = serde_json::to_string(&fraction_range).unwrap(); - assert_eq!("{\"min\":[1,3],\"max\":[1,2]}".to_owned(), res); - - // IntRange - let int_range = IntRange::<i32>::new_with_step(0, 42, 21); - let res = ron::ser::to_string_pretty(&int_range, pretty_config.clone()); - assert_eq!( - Ok( - concat!( - "(", - " min: 0,", - " max: 42,", - " step: 21,", - ")" - ) - .to_owned() - ), - res, - ); - - let res = serde_json::to_string(&int_range).unwrap(); - assert_eq!("{\"min\":0,\"max\":42,\"step\":21}".to_owned(), res); - - // Bitmask - let bitmask = Bitmask::new(1024 + 128 + 32); - - let res = ron::ser::to_string_pretty(&bitmask, pretty_config.clone()); - assert_eq!(Ok("(1184)".to_owned()), res); - - let res = serde_json::to_string(&bitmask).unwrap(); - assert_eq!("1184".to_owned(), res); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_serialize_collections() { - extern crate ron; - extern crate serde_json; - - use glib::value::ToValue; - - use Array; - use Fraction; - use List; - - ::init().unwrap(); - - let mut pretty_config = ron::ser::PrettyConfig::default(); - pretty_config.new_line = "".to_string(); - - // Array - let value_13 = Fraction::new(1, 3).to_value(); - let send_value_13 = value_13.try_into_send_value::<Fraction>().unwrap(); - - let value_12 = Fraction::new(1, 2).to_value(); - let send_value_12 = value_12.try_into_send_value::<Fraction>().unwrap(); - - let value_str = "test str".to_value(); - let send_value_str = value_str.try_into_send_value::<String>().unwrap(); - - let array = Array::new(&[&send_value_13, &send_value_12, &send_value_str]); - - let res = ron::ser::to_string_pretty(&array, pretty_config.clone()); - assert_eq!( - Ok( - concat!( - "[", - " (\"Fraction\", (1, 3)),", - " (\"Fraction\", (1, 2)),", - " (\"String\", \"test str\"),", - "]" - ) - .to_owned() - ), - res, - ); - - let res = serde_json::to_string(&array).unwrap(); - assert_eq!( - "[[\"Fraction\",[1,3]],[\"Fraction\",[1,2]],[\"String\",\"test str\"]]" - .to_owned(), - res - ); - - // List - let value_12 = Fraction::new(1, 2).to_value(); - let send_value_12 = value_12.try_into_send_value::<Fraction>().unwrap(); - - let value_str = "test str".to_value(); - let send_value_str = value_str.try_into_send_value::<String>().unwrap(); - - let list = List::new(&[&send_value_12, &send_value_str]); - - let res = ron::ser::to_string_pretty(&list, pretty_config.clone()); - assert_eq!( - Ok( - concat!( - "[", - " (\"Fraction\", (1, 2)),", - " (\"String\", \"test str\"),", - "]" - ) - .to_owned() - ), - res, - ); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize_simple() { - extern crate ron; - extern crate serde_json; - - use Fraction; - use FractionRange; - use IntRange; - use Bitmask; - - ::init().unwrap(); - - // Fraction - let fraction_ron = "(1, 3)"; - let fraction: Fraction = ron::de::from_str(fraction_ron).unwrap(); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &3); - - let fraction_json = "[1,3]"; - let fraction: Fraction = serde_json::from_str(fraction_json).unwrap(); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &3); - - // FractionRange - let fraction_range_ron = "(min: (1, 3), max: (1, 2))"; - let fraction_range: FractionRange = ron::de::from_str(fraction_range_ron).unwrap(); - assert_eq!(fraction_range.min().0.denom(), &3); - assert_eq!(fraction_range.max().0.denom(), &2); - - let fraction_range_json = "{\"min\":[1,3],\"max\":[1,2]}"; - let fraction_range: FractionRange = serde_json::from_str(fraction_range_json).unwrap(); - assert_eq!(fraction_range.min().0.denom(), &3); - assert_eq!(fraction_range.max().0.denom(), &2); - - // IntRange - let int_range_ron = "(min: 0, max: 42, step: 21)"; - let int_range: IntRange<i32> = ron::de::from_str(int_range_ron).unwrap(); - assert_eq!(int_range.min(), 0); - assert_eq!(int_range.max(), 42); - assert_eq!(int_range.step(), 21); - - let int_range_json = "{\"min\":0,\"max\":42,\"step\":21}"; - let int_range: IntRange<i32> = serde_json::from_str(int_range_json).unwrap(); - assert_eq!(int_range.min(), 0); - assert_eq!(int_range.max(), 42); - assert_eq!(int_range.step(), 21); - - // Bitmask - let bitmask_ref = Bitmask::new(1024 + 128 + 32); - - let bitmask_ron = "(1184)"; - let bitmask: Bitmask = ron::de::from_str(bitmask_ron).unwrap(); - assert_eq!(bitmask_ref, bitmask); - - let bitmask_json = "1184"; - let bitmask: Bitmask = serde_json::from_str(bitmask_json).unwrap(); - assert_eq!(bitmask_ref, bitmask); - } - - #[cfg(feature = "ser_de")] - #[test] - fn test_deserialize_collections() { - extern crate ron; - extern crate serde_json; - - use Array; - use Fraction; - use List; - - ::init().unwrap(); - - // Array - let array_ron = - r#"[ - ("Fraction", (1, 3)), - ("Fraction", (1, 2)), - ("String", "test str"), - ]"#; - let array: Array = ron::de::from_str(array_ron).unwrap(); - assert_eq!(3, array.0.len()); - - let fraction = array.0[0].get::<Fraction>().unwrap(); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &3); - - let fraction = array.0[1].get::<Fraction>().unwrap(); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &2); - - assert_eq!("test str".to_owned(), array.0[2].get::<String>().unwrap()); - - let array_json = - r#"[["Fraction",[1,3]],["Fraction",[1,2]],["String","test str"]]"#; - let array: Array = serde_json::from_str(array_json).unwrap(); - assert_eq!(3, array.0.len()); - - let fraction = array.0[0].get::<Fraction>().unwrap(); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &3); - - let fraction = array.0[1].get::<Fraction>().unwrap(); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &2); - - assert_eq!("test str".to_owned(), array.0[2].get::<String>().unwrap()); - - // List - let list_ron = - r#"[ - ("Fraction", (1, 2)), - ("String", "test str"), - ]"#; - let list: List = ron::de::from_str(list_ron).unwrap(); - assert_eq!(2, list.0.len()); - - let fraction = list.0[0].get::<Fraction>().unwrap(); - assert_eq!(fraction.0.numer(), &1); - assert_eq!(fraction.0.denom(), &2); - - assert_eq!("test str".to_owned(), list.0[1].get::<String>().unwrap()); - } -} diff --git a/gstreamer/src/value_serde.rs b/gstreamer/src/value_serde.rs new file mode 100644 index 000000000..5dd20a86c --- /dev/null +++ b/gstreamer/src/value_serde.rs @@ -0,0 +1,534 @@ +// Copyright (C) 2018 François Laignel <fengalin@free.fr> +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use glib; +use glib::{StaticType, ToValue}; + +use num_rational::Rational32; + +use serde::de; +use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; +use serde::ser; +use serde::ser::{Serialize, Serializer, SerializeTuple}; + +use std::{fmt, mem}; + +use DateTime; +use Sample; + +use value::*; + +pub const ARRAY_TYPE_NAME: &'static str = "Array"; +pub const LIST_TYPE_NAME: &'static str = "List"; + +fn get_other_type_id<T: StaticType>() -> usize { + match T::static_type() { + glib::Type::Other(type_id) => type_id, + type_ => panic!("Expecting `Other` variant, found `{}`", type_), + } +} + +lazy_static! { + pub(crate) static ref ARRAY_OTHER_TYPE_ID: usize = get_other_type_id::<Array>(); + pub(crate) static ref BITMASK_OTHER_TYPE_ID: usize = get_other_type_id::<Bitmask>(); + pub(crate) static ref DATE_TIME_OTHER_TYPE_ID: usize = get_other_type_id::<DateTime>(); + pub(crate) static ref FRACTION_OTHER_TYPE_ID: usize = get_other_type_id::<Fraction>(); + pub(crate) static ref FRACTION_RANGE_OTHER_TYPE_ID: usize = + get_other_type_id::<FractionRange>(); + pub(crate) static ref INT_RANGE_I32_OTHER_TYPE_ID: usize = + get_other_type_id::<IntRange<i32>>(); + pub(crate) static ref INT_RANGE_I64_OTHER_TYPE_ID: usize = + get_other_type_id::<IntRange<i64>>(); + pub(crate) static ref LIST_OTHER_TYPE_ID: usize = get_other_type_id::<List>(); + pub(crate) static ref SAMPLE_OTHER_TYPE_ID: usize = get_other_type_id::<Sample>(); +} + +impl<'a> Serialize for Fraction { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + self.0.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for Fraction { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + Rational32::deserialize(deserializer) + .and_then(|rational| Ok(Fraction::new(*rational.numer(), *rational.denom()))) + } +} + +macro_rules! ser_value ( + ($value:expr, $t_str:expr, $t:ty, $ser_closure:expr) => ( + { + let value = $value.get::<$t>().unwrap(); + $ser_closure($t_str, value) + } + ); + ($value:expr, $ser_closure:expr) => ( + match $value.type_() { + glib::Type::I8 => ser_value!($value, "i8", i8, $ser_closure), + glib::Type::U8 => ser_value!($value, "ui8", u8, $ser_closure), + glib::Type::Bool => ser_value!($value, "bool", bool, $ser_closure), + glib::Type::I32 => ser_value!($value, "i32", i32, $ser_closure), + glib::Type::U32 => ser_value!($value, "u32", u32, $ser_closure), + glib::Type::I64 => ser_value!($value, "i64", i64, $ser_closure), + glib::Type::U64 => ser_value!($value, "u64", u64, $ser_closure), + glib::Type::F32 => ser_value!($value, "f32", f32, $ser_closure), + glib::Type::F64 => ser_value!($value, "f64", f64, $ser_closure), + glib::Type::String => ser_value!($value, "String", String, $ser_closure), + glib::Type::Other(type_id) => { + if *ARRAY_OTHER_TYPE_ID == type_id { + ser_value!($value, ARRAY_TYPE_NAME, Array, $ser_closure) + } else if *BITMASK_OTHER_TYPE_ID == type_id { + ser_value!($value, "Bitmask", Bitmask, $ser_closure) + } else if *DATE_TIME_OTHER_TYPE_ID == type_id { + ser_value!($value, "DateTime", DateTime, $ser_closure) + } else if *FRACTION_OTHER_TYPE_ID == type_id { + ser_value!($value, "Fraction", Fraction, $ser_closure) + } else if *FRACTION_RANGE_OTHER_TYPE_ID == type_id { + ser_value!($value, "FractionRange", FractionRange, $ser_closure) + } else if *INT_RANGE_I32_OTHER_TYPE_ID == type_id { + ser_value!($value, "IntRange<i32>", IntRange<i32>, $ser_closure) + } else if *INT_RANGE_I64_OTHER_TYPE_ID == type_id { + ser_value!($value, "IntRange<i64>", IntRange<i64>, $ser_closure) + } else if *LIST_OTHER_TYPE_ID == type_id { + ser_value!($value, LIST_TYPE_NAME, List, $ser_closure) + } else if *SAMPLE_OTHER_TYPE_ID == type_id { + ser_value!($value, "Sample", Sample, $ser_closure) + } else { + Err( + ser::Error::custom( + format!("unimplemented `Value` serialization for type {}", + glib::Type::Other(type_id), + ) + ) + ) + } + } + type_ => { + Err( + ser::Error::custom( + format!("unimplemented `Value` serialization for type {}", type_) + ) + ) + } + } + ) +); + +pub(crate) struct SendValue(glib::SendValue); +impl SendValue { + pub(crate) fn from(send_value: glib::SendValue) -> Self { + SendValue(send_value) + } +} + +impl From<SendValue> for glib::SendValue { + fn from(send_value: SendValue) -> Self { + send_value.0 + } +} + +impl Serialize for SendValue { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + ser_value!(self.0, |type_, value| { + let mut tup = serializer.serialize_tuple(2)?; + tup.serialize_element(type_)?; + tup.serialize_element(&value)?; + tup.end() + }) + } +} + +macro_rules! impl_ser_send_value_collection ( + ($t:ident) => ( + impl<'a> Serialize for $t<'a> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let send_value_vec = unsafe { + mem::transmute::<&[glib::SendValue], &[SendValue]>( + self.as_slice() + ) + }; + send_value_vec.serialize(serializer) + } + } + ); +); + +impl_ser_send_value_collection!(Array); +impl_ser_send_value_collection!(List); + +macro_rules! de_value( + ($outer_type:expr, $type_name:expr, $seq:expr, $t:ty) => ( + $seq + .next_element::<$t>()? + .ok_or_else(|| + de::Error::custom(format!( + "Expected a value for `{}` with type {:?}", + $outer_type, + $type_name, + )) + )? + .to_value() + ); +); + +macro_rules! de_send_value( + ($type_name:expr, $seq:expr, $t:ty) => ( + SendValue::from( + de_value!("Value", $type_name, $seq, $t) + .try_into_send_value::<$t>() + .map_err(|_| + de::Error::custom(format!( + "Failed to convert `Value` with type {:?} to `SendValue`", + $type_name, + )) + )? + ) + ); + ($type_name:expr, $seq:expr) => ( + match $type_name.as_str() { + "i8" => de_send_value!($type_name, $seq, i8), + "u8" => de_send_value!($type_name, $seq, u8), + "bool" => de_send_value!($type_name, $seq, bool), + "i32" => de_send_value!($type_name, $seq, i32), + "u32" => de_send_value!($type_name, $seq, u32), + "i64" => de_send_value!($type_name, $seq, i64), + "u64" => de_send_value!($type_name, $seq, u64), + "f32" => de_send_value!($type_name, $seq, f32), + "f64" => de_send_value!($type_name, $seq, f64), + "String" => de_send_value!($type_name, $seq, String), + "Array" => de_send_value!($type_name, $seq, Array), + "Bitmask" => de_send_value!($type_name, $seq, Bitmask), + "DateTime" => de_send_value!($type_name, $seq, DateTime), + "Fraction" => de_send_value!($type_name, $seq, Fraction), + "FractionRange" => de_send_value!($type_name, $seq, FractionRange), + "IntRange<i32>" => de_send_value!($type_name, $seq, IntRange<i32>), + "IntRange<i64>" => de_send_value!($type_name, $seq, IntRange<i64>), + "Sample" => de_send_value!($type_name, $seq, Sample), + _ => return Err( + de::Error::custom( + format!( + "unimplemented deserialization for `Value` with type `{}`", + $type_name, + ), + ) + ), + } + ); +); + +struct SendValueVisitor; +impl<'de> Visitor<'de> for SendValueVisitor { + type Value = SendValue; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a tuple: (name, value)") + } + + fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> { + let type_name = seq.next_element::<String>()? + .ok_or(de::Error::custom("Expected a value for `Value` type"))?; + Ok(de_send_value!(type_name, seq)) + } +} + +impl<'de> Deserialize<'de> for SendValue { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + deserializer.deserialize_tuple(2, SendValueVisitor{}) + } +} + +macro_rules! impl_de_send_value_collection ( + ($t:ident) => { + impl<'a, 'de> Deserialize<'de> for $t<'a> { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + let send_value_vec = Vec::<SendValue>::deserialize(deserializer)?; + Ok($t::from_owned(unsafe{ + mem::transmute::<Vec<SendValue>, Vec<glib::SendValue>>(send_value_vec) + })) + } + } + } +); + +impl_de_send_value_collection!(Array); +impl_de_send_value_collection!(List); + +#[cfg(test)] +mod tests { + extern crate ron; + extern crate serde_json; + + #[test] + fn test_serialize_simple() { + use Fraction; + use FractionRange; + use IntRange; + use Bitmask; + + ::init().unwrap(); + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + // Fraction + let fraction = Fraction::new(1, 3); + + let res = ron::ser::to_string_pretty(&fraction, pretty_config.clone()); + assert_eq!(Ok("(1, 3)".to_owned()), res); + + let res = serde_json::to_string(&fraction).unwrap(); + assert_eq!("[1,3]".to_owned(), res); + + // FractionRange + let fraction_range = FractionRange::new(Fraction::new(1, 3), Fraction::new(1, 2)); + + let res = ron::ser::to_string_pretty(&fraction_range, pretty_config.clone()); + assert_eq!( + Ok( + concat!( + "(", + " min: (1, 3),", + " max: (1, 2),", + ")" + ) + .to_owned() + ), + res, + ); + + let res = serde_json::to_string(&fraction_range).unwrap(); + assert_eq!("{\"min\":[1,3],\"max\":[1,2]}".to_owned(), res); + + // IntRange + let int_range = IntRange::<i32>::new_with_step(0, 42, 21); + let res = ron::ser::to_string_pretty(&int_range, pretty_config.clone()); + assert_eq!( + Ok( + concat!( + "(", + " min: 0,", + " max: 42,", + " step: 21,", + ")" + ) + .to_owned() + ), + res, + ); + + let res = serde_json::to_string(&int_range).unwrap(); + assert_eq!("{\"min\":0,\"max\":42,\"step\":21}".to_owned(), res); + + // Bitmask + let bitmask = Bitmask::new(1024 + 128 + 32); + + let res = ron::ser::to_string_pretty(&bitmask, pretty_config.clone()); + assert_eq!(Ok("(1184)".to_owned()), res); + + let res = serde_json::to_string(&bitmask).unwrap(); + assert_eq!("1184".to_owned(), res); + } + + #[test] + fn test_serialize_collections() { + use glib::value::ToValue; + + use Array; + use Fraction; + use List; + + ::init().unwrap(); + + let mut pretty_config = ron::ser::PrettyConfig::default(); + pretty_config.new_line = "".to_string(); + + // Array + let value_13 = Fraction::new(1, 3).to_value(); + let send_value_13 = value_13.try_into_send_value::<Fraction>().unwrap(); + + let value_12 = Fraction::new(1, 2).to_value(); + let send_value_12 = value_12.try_into_send_value::<Fraction>().unwrap(); + + let value_str = "test str".to_value(); + let send_value_str = value_str.try_into_send_value::<String>().unwrap(); + + let array = Array::new(&[&send_value_13, &send_value_12, &send_value_str]); + + let res = ron::ser::to_string_pretty(&array, pretty_config.clone()); + assert_eq!( + Ok( + concat!( + "[", + " (\"Fraction\", (1, 3)),", + " (\"Fraction\", (1, 2)),", + " (\"String\", \"test str\"),", + "]" + ) + .to_owned() + ), + res, + ); + + let res = serde_json::to_string(&array).unwrap(); + assert_eq!( + "[[\"Fraction\",[1,3]],[\"Fraction\",[1,2]],[\"String\",\"test str\"]]" + .to_owned(), + res + ); + + // List + let value_12 = Fraction::new(1, 2).to_value(); + let send_value_12 = value_12.try_into_send_value::<Fraction>().unwrap(); + + let value_str = "test str".to_value(); + let send_value_str = value_str.try_into_send_value::<String>().unwrap(); + + let list = List::new(&[&send_value_12, &send_value_str]); + + let res = ron::ser::to_string_pretty(&list, pretty_config.clone()); + assert_eq!( + Ok( + concat!( + "[", + " (\"Fraction\", (1, 2)),", + " (\"String\", \"test str\"),", + "]" + ) + .to_owned() + ), + res, + ); + } + + #[cfg(feature = "ser_de")] + #[test] + fn test_deserialize_simple() { + extern crate ron; + extern crate serde_json; + + use Fraction; + use FractionRange; + use IntRange; + use Bitmask; + + ::init().unwrap(); + + // Fraction + let fraction_ron = "(1, 3)"; + let fraction: Fraction = ron::de::from_str(fraction_ron).unwrap(); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &3); + + let fraction_json = "[1,3]"; + let fraction: Fraction = serde_json::from_str(fraction_json).unwrap(); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &3); + + // FractionRange + let fraction_range_ron = "(min: (1, 3), max: (1, 2))"; + let fraction_range: FractionRange = ron::de::from_str(fraction_range_ron).unwrap(); + assert_eq!(fraction_range.min().0.denom(), &3); + assert_eq!(fraction_range.max().0.denom(), &2); + + let fraction_range_json = "{\"min\":[1,3],\"max\":[1,2]}"; + let fraction_range: FractionRange = serde_json::from_str(fraction_range_json).unwrap(); + assert_eq!(fraction_range.min().0.denom(), &3); + assert_eq!(fraction_range.max().0.denom(), &2); + + // IntRange + let int_range_ron = "(min: 0, max: 42, step: 21)"; + let int_range: IntRange<i32> = ron::de::from_str(int_range_ron).unwrap(); + assert_eq!(int_range.min(), 0); + assert_eq!(int_range.max(), 42); + assert_eq!(int_range.step(), 21); + + let int_range_json = "{\"min\":0,\"max\":42,\"step\":21}"; + let int_range: IntRange<i32> = serde_json::from_str(int_range_json).unwrap(); + assert_eq!(int_range.min(), 0); + assert_eq!(int_range.max(), 42); + assert_eq!(int_range.step(), 21); + + // Bitmask + let bitmask_ref = Bitmask::new(1024 + 128 + 32); + + let bitmask_ron = "(1184)"; + let bitmask: Bitmask = ron::de::from_str(bitmask_ron).unwrap(); + assert_eq!(bitmask_ref, bitmask); + + let bitmask_json = "1184"; + let bitmask: Bitmask = serde_json::from_str(bitmask_json).unwrap(); + assert_eq!(bitmask_ref, bitmask); + } + + #[cfg(feature = "ser_de")] + #[test] + fn test_deserialize_collections() { + extern crate ron; + extern crate serde_json; + + use Array; + use Fraction; + use List; + + ::init().unwrap(); + + // Array + let array_ron = + r#"[ + ("Fraction", (1, 3)), + ("Fraction", (1, 2)), + ("String", "test str"), + ]"#; + let array: Array = ron::de::from_str(array_ron).unwrap(); + let slice = array.as_slice(); + assert_eq!(3, slice.len()); + + let fraction = slice[0].get::<Fraction>().unwrap(); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &3); + + let fraction = slice[1].get::<Fraction>().unwrap(); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &2); + + assert_eq!("test str".to_owned(), slice[2].get::<String>().unwrap()); + + let array_json = + r#"[["Fraction",[1,3]],["Fraction",[1,2]],["String","test str"]]"#; + let array: Array = serde_json::from_str(array_json).unwrap(); + let slice = array.as_slice(); + assert_eq!(3, slice.len()); + + let fraction = slice[0].get::<Fraction>().unwrap(); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &3); + + let fraction = slice[1].get::<Fraction>().unwrap(); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &2); + + assert_eq!("test str".to_owned(), slice[2].get::<String>().unwrap()); + + // List + let list_ron = + r#"[ + ("Fraction", (1, 2)), + ("String", "test str"), + ]"#; + let list: List = ron::de::from_str(list_ron).unwrap(); + let slice = list.as_slice(); + assert_eq!(2, slice.len()); + + let fraction = slice[0].get::<Fraction>().unwrap(); + assert_eq!(fraction.0.numer(), &1); + assert_eq!(fraction.0.denom(), &2); + + assert_eq!("test str".to_owned(), slice[1].get::<String>().unwrap()); + } +}