forked from mirrors/gstreamer-rs
serde: separate serde impl and tests from base module
+ fix erroneous `datetime` instead of `buffer` in `BufferRef::serialize` + remove ser/de for `Value`s with types `ULong` & `ILong`
This commit is contained in:
parent
3f0cd6fb87
commit
90b046fbcf
24 changed files with 2949 additions and 2894 deletions
|
@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<BufferDe> 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<u8> = buf_de.buffer.as_mut();
|
||||
let mut buffer =
|
||||
Buffer::from_slice(drained_buffer.drain(..).collect::<Vec<u8>>()).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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
231
gstreamer/src/buffer_serde.rs
Normal file
231
gstreamer/src/buffer_serde.rs
Normal file
|
@ -0,0 +1,231 @@
|
|||
// 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 serde_bytes::{Bytes, ByteBuf};
|
||||
|
||||
use Buffer;
|
||||
use BufferFlags;
|
||||
use BufferRef;
|
||||
use ClockTime;
|
||||
|
||||
impl<'a> Serialize for BufferRef {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<BufferDe> 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<u8> = buf_de.buffer.as_mut();
|
||||
let mut buffer =
|
||||
Buffer::from_slice(drained_buffer.drain(..).collect::<Vec<u8>>()).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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let mut buffer_list = BufferList::new();
|
||||
{
|
||||
let buffer_list = buffer_list.get_mut().unwrap();
|
||||
while let Some(buffer) = seq.next_element::<Buffer>()? {
|
||||
buffer_list.add(buffer);
|
||||
}
|
||||
}
|
||||
Ok(buffer_list)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for BufferList {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
190
gstreamer/src/bufferlist_serde.rs
Normal file
190
gstreamer/src/bufferlist_serde.rs
Normal file
|
@ -0,0 +1,190 @@
|
|||
// 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, SeqAccess, Visitor};
|
||||
use serde::ser::{Serialize, Serializer, SerializeSeq};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use Buffer;
|
||||
use BufferList;
|
||||
use BufferListRef;
|
||||
|
||||
impl Serialize for BufferListRef {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let mut buffer_list = BufferList::new();
|
||||
{
|
||||
let buffer_list = buffer_list.get_mut().unwrap();
|
||||
while let Some(buffer) = seq.next_element::<Buffer>()? {
|
||||
buffer_list.add(buffer);
|
||||
}
|
||||
}
|
||||
Ok(buffer_list)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for BufferList {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let mut caps = Caps::new_empty();
|
||||
{
|
||||
let caps = caps.get_mut().unwrap();
|
||||
while let Some(structure) = seq.next_element::<Structure>()? {
|
||||
caps.append_structure(structure);
|
||||
}
|
||||
}
|
||||
Ok(caps)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Caps {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
148
gstreamer/src/caps_serde.rs
Normal file
148
gstreamer/src/caps_serde.rs
Normal file
|
@ -0,0 +1,148 @@
|
|||
// 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, SeqAccess, Visitor};
|
||||
use serde::ser::{Serialize, Serializer, SerializeSeq};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use Caps;
|
||||
use CapsRef;
|
||||
use Structure;
|
||||
|
||||
impl<'a> Serialize for CapsRef {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let mut caps = Caps::new_empty();
|
||||
{
|
||||
let caps = caps.get_mut().unwrap();
|
||||
while let Some(structure) = seq.next_element::<Structure>()? {
|
||||
caps.append_structure(structure);
|
||||
}
|
||||
}
|
||||
Ok(caps)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Caps {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
u64::deserialize(deserializer)
|
||||
.and_then(|value| Ok(ClockTime::from_nseconds(value)))
|
||||
}
|
||||
|
||||
fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
|
||||
Ok(ClockTime(None))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ClockTime {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
deserializer.deserialize_option(ClockTimeVisitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl ToGlib for ClockTime {
|
||||
type GlibType = ffi::GstClockTime;
|
||||
|
@ -203,74 +156,3 @@ impl glib::StaticType for ClockTime {
|
|||
<u64 as glib::StaticType>::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);
|
||||
}
|
||||
}
|
||||
|
|
114
gstreamer/src/clock_time_serde.rs
Normal file
114
gstreamer/src/clock_time_serde.rs
Normal file
|
@ -0,0 +1,114 @@
|
|||
// 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;
|
||||
use serde::de::{Deserialize, Deserializer, Visitor};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use ClockTime;
|
||||
|
||||
impl<'a> Serialize for ClockTime {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
u64::deserialize(deserializer)
|
||||
.and_then(|value| Ok(ClockTime::from_nseconds(value)))
|
||||
}
|
||||
|
||||
fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
|
||||
Ok(ClockTime(None))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ClockTime {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<DateTimeDe> 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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
144
gstreamer/src/date_time_serde.rs
Normal file
144
gstreamer/src/date_time_serde.rs
Normal file
|
@ -0,0 +1,144 @@
|
|||
// 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 DateTime;
|
||||
|
||||
impl<'a> Serialize for DateTime {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<DateTimeDe> 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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
self.as_ref().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SampleDe {
|
||||
buffer: Option<Buffer>,
|
||||
buffer_list: Option<BufferList>,
|
||||
caps: Option<Caps>,
|
||||
segment: Option<Segment>,
|
||||
info: Option<Structure>,
|
||||
}
|
||||
|
||||
impl From<SampleDe> for Sample {
|
||||
fn from(mut buf_de: SampleDe) -> Self {
|
||||
if buf_de.buffer.is_some() {
|
||||
Sample::new::<GenericFormattedValue>(
|
||||
buf_de.buffer.as_ref(),
|
||||
buf_de.caps.as_ref(),
|
||||
buf_de.segment.as_ref(),
|
||||
buf_de.info.take(),
|
||||
)
|
||||
} else {
|
||||
Sample::with_buffer_list::<GenericFormattedValue>(
|
||||
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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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::<GenericFormattedValue>(
|
||||
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::<GenericFormattedValue>(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());
|
||||
}
|
||||
}
|
||||
|
|
325
gstreamer/src/sample_serde.rs
Normal file
325
gstreamer/src/sample_serde.rs
Normal file
|
@ -0,0 +1,325 @@
|
|||
// 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 Buffer;
|
||||
use BufferList;
|
||||
use Caps;
|
||||
use GenericFormattedValue;
|
||||
use Sample;
|
||||
use SampleRef;
|
||||
use Segment;
|
||||
use Structure;
|
||||
|
||||
impl<'a> Serialize for SampleRef {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
self.as_ref().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SampleDe {
|
||||
buffer: Option<Buffer>,
|
||||
buffer_list: Option<BufferList>,
|
||||
caps: Option<Caps>,
|
||||
segment: Option<Segment>,
|
||||
info: Option<Structure>,
|
||||
}
|
||||
|
||||
impl From<SampleDe> for Sample {
|
||||
fn from(mut buf_de: SampleDe) -> Self {
|
||||
if buf_de.buffer.is_some() {
|
||||
Sample::new::<GenericFormattedValue>(
|
||||
buf_de.buffer.as_ref(),
|
||||
buf_de.caps.as_ref(),
|
||||
buf_de.segment.as_ref(),
|
||||
buf_de.info.take(),
|
||||
)
|
||||
} else {
|
||||
Sample::with_buffer_list::<GenericFormattedValue>(
|
||||
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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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::<GenericFormattedValue>(
|
||||
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::<GenericFormattedValue>(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());
|
||||
}
|
||||
}
|
|
@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<SegmentDe> 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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
|
167
gstreamer/src/segment_serde.rs
Normal file
167
gstreamer/src/segment_serde.rs
Normal file
|
@ -0,0 +1,167 @@
|
|||
// 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 Format;
|
||||
use GenericFormattedValue;
|
||||
use Segment;
|
||||
use SegmentFlags;
|
||||
|
||||
impl<'a> Serialize for Segment {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<SegmentDe> 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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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()));
|
||||
}
|
||||
}
|
|
@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
self.as_ref().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
struct FieldDe(String, SendValue);
|
||||
impl From<FieldDe> 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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let name = seq.next_element::<String>()?
|
||||
.ok_or(de::Error::custom("Expected a value for `Value` name, found `None`"))?;
|
||||
let type_name = seq.next_element::<String>()?
|
||||
.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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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<NamelessStructure> 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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
// Can't build a `Structure` with an empty name
|
||||
let mut structure = Structure::new_empty("None");
|
||||
while let Some(field) = seq.next_element::<FieldDe>()? {
|
||||
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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let name = seq.next_element::<String>()?
|
||||
.ok_or(de::Error::custom(
|
||||
"Expected a name for the `Structure`, found `None`"
|
||||
))?;
|
||||
let mut structure: Structure = seq.next_element::<NamelessStructure>()?
|
||||
.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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
245
gstreamer/src/structure_serde.rs
Normal file
245
gstreamer/src/structure_serde.rs
Normal file
|
@ -0,0 +1,245 @@
|
|||
// 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::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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
self.as_ref().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
struct FieldDe(String, SendValue);
|
||||
impl From<FieldDe> 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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let name = seq.next_element::<String>()?
|
||||
.ok_or(de::Error::custom("Expected a value for `Value` name"))?;
|
||||
let type_name = seq.next_element::<String>()?
|
||||
.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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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<NamelessStructure> 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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
// Can't build a `Structure` with an empty name
|
||||
let mut structure = Structure::new_empty("None");
|
||||
while let Some(field) = seq.next_element::<FieldDe>()? {
|
||||
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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let name = seq.next_element::<String>()?
|
||||
.ok_or(de::Error::custom("Expected a name for the `Structure`"))?;
|
||||
let mut structure: Structure = seq.next_element::<NamelessStructure>()?
|
||||
.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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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<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, 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<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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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::<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,
|
||||
);
|
||||
}
|
||||
|
||||
#[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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
429
gstreamer/src/tags_serde.rs
Normal file
429
gstreamer/src/tags_serde.rs
Normal file
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
379
gstreamer/src/toc_serde.rs
Normal file
379
gstreamer/src/toc_serde.rs
Normal file
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
534
gstreamer/src/value_serde.rs
Normal file
534
gstreamer/src/value_serde.rs
Normal file
|
@ -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());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue