mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-23 01:51:06 +00:00
Fix serde for Values
with optional Type
s
Attention: these changes induce breaking changes for the serde representation of some types. Serialization of `Value`s used to rely on the `get` function followed by an `unwrap`. This means that optional types couldn't be serialized when they were `None`. This commit distinguishes between the optional `Value` `Types` and the ones that always return some value. The `Value`s, `Structure` fields and `Tag`s with following types are now represented as `Option`s: - `Buffer` - `DateTime` - `Sample` (note: this type is used for `Tag` images) - `String` (except for `Tag`s - see the comment in `tags_serde.rs`). The representations for these `Type`s remain unchanged when they are used in-place (not as part of a `Value`). Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/issues/215
This commit is contained in:
parent
26423a069c
commit
c74eef374a
4 changed files with 202 additions and 126 deletions
|
@ -254,7 +254,7 @@ mod tests {
|
||||||
" ((\"foo/bar\", [",
|
" ((\"foo/bar\", [",
|
||||||
" (\"int\", \"i32\", 12),",
|
" (\"int\", \"i32\", 12),",
|
||||||
" (\"bool\", \"bool\", true),",
|
" (\"bool\", \"bool\", true),",
|
||||||
" (\"string\", \"String\", \"bla\"),",
|
" (\"string\", \"String\", Some(\"bla\")),",
|
||||||
" (\"fraction\", \"Fraction\", (1, 2)),",
|
" (\"fraction\", \"Fraction\", (1, 2)),",
|
||||||
" (\"array\", \"Array\", [",
|
" (\"array\", \"Array\", [",
|
||||||
" (\"i32\", 1),",
|
" (\"i32\", 1),",
|
||||||
|
@ -286,7 +286,7 @@ mod tests {
|
||||||
" ((\"foo/bar\", [",
|
" ((\"foo/bar\", [",
|
||||||
" (\"int\", \"i32\", 12),",
|
" (\"int\", \"i32\", 12),",
|
||||||
" (\"bool\", \"bool\", true),",
|
" (\"bool\", \"bool\", true),",
|
||||||
" (\"string\", \"String\", \"bla\"),",
|
" (\"string\", \"String\", Some(\"bla\")),",
|
||||||
" (\"fraction\", \"Fraction\", (1, 2)),",
|
" (\"fraction\", \"Fraction\", (1, 2)),",
|
||||||
" (\"array\", \"Array\", [",
|
" (\"array\", \"Array\", [",
|
||||||
" (\"i32\", 1),",
|
" (\"i32\", 1),",
|
||||||
|
@ -321,7 +321,7 @@ mod tests {
|
||||||
" ((\"foo/bar\", [",
|
" ((\"foo/bar\", [",
|
||||||
" (\"int\", \"i32\", 12),",
|
" (\"int\", \"i32\", 12),",
|
||||||
" (\"bool\", \"bool\", true),",
|
" (\"bool\", \"bool\", true),",
|
||||||
" (\"string\", \"String\", \"bla\"),",
|
" (\"string\", \"String\", Some(\"bla\")),",
|
||||||
" (\"fraction\", \"Fraction\", (1, 2)),",
|
" (\"fraction\", \"Fraction\", (1, 2)),",
|
||||||
" (\"array\", \"Array\", [",
|
" (\"array\", \"Array\", [",
|
||||||
" (\"i32\", 1),",
|
" (\"i32\", 1),",
|
||||||
|
@ -363,7 +363,7 @@ mod tests {
|
||||||
("foo/bar", [
|
("foo/bar", [
|
||||||
("int", "i32", 12),
|
("int", "i32", 12),
|
||||||
("bool", "bool", true),
|
("bool", "bool", true),
|
||||||
("string", "String", "bla"),
|
("string", "String", Some("bla")),
|
||||||
("fraction", "Fraction", (1, 2)),
|
("fraction", "Fraction", (1, 2)),
|
||||||
("array", "Array", [
|
("array", "Array", [
|
||||||
("i32", 1),
|
("i32", 1),
|
||||||
|
@ -396,7 +396,7 @@ mod tests {
|
||||||
("foo/bar", [
|
("foo/bar", [
|
||||||
("int", "i32", 12),
|
("int", "i32", 12),
|
||||||
("bool", "bool", true),
|
("bool", "bool", true),
|
||||||
("string", "String", "bla"),
|
("string", "String", None),
|
||||||
("fraction", "Fraction", (1, 2)),
|
("fraction", "Fraction", (1, 2)),
|
||||||
("array", "Array", [
|
("array", "Array", [
|
||||||
("i32", 1),
|
("i32", 1),
|
||||||
|
@ -408,6 +408,7 @@ mod tests {
|
||||||
])"#;
|
])"#;
|
||||||
let caps: Caps = ron::de::from_str(caps_ron).unwrap();
|
let caps: Caps = ron::de::from_str(caps_ron).unwrap();
|
||||||
let s = caps.get_structure(0).unwrap();
|
let s = caps.get_structure(0).unwrap();
|
||||||
|
let str_none: Option<&str> = None;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
s,
|
s,
|
||||||
Structure::new(
|
Structure::new(
|
||||||
|
@ -415,7 +416,7 @@ mod tests {
|
||||||
&[
|
&[
|
||||||
("int", &12),
|
("int", &12),
|
||||||
("bool", &true),
|
("bool", &true),
|
||||||
("string", &"bla"),
|
("string", &str_none),
|
||||||
("fraction", &Fraction::new(1, 2)),
|
("fraction", &Fraction::new(1, 2)),
|
||||||
("array", &Array::new(&[&1, &2])),
|
("array", &Array::new(&[&1, &2])),
|
||||||
],
|
],
|
||||||
|
@ -431,7 +432,7 @@ mod tests {
|
||||||
("foo/bar", [
|
("foo/bar", [
|
||||||
("int", "i32", 12),
|
("int", "i32", 12),
|
||||||
("bool", "bool", true),
|
("bool", "bool", true),
|
||||||
("string", "String", "bla"),
|
("string", "String", Some("bla")),
|
||||||
("fraction", "Fraction", (1, 2)),
|
("fraction", "Fraction", (1, 2)),
|
||||||
("array", "Array", [
|
("array", "Array", [
|
||||||
("i32", 1),
|
("i32", 1),
|
||||||
|
|
|
@ -189,8 +189,8 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok(concat!(
|
Ok(concat!(
|
||||||
"(\"test\", [",
|
"(\"test\", [",
|
||||||
" (\"f1\", \"String\", \"abc\"),",
|
" (\"f1\", \"String\", Some(\"abc\")),",
|
||||||
" (\"f2\", \"String\", \"bcd\"),",
|
" (\"f2\", \"String\", Some(\"bcd\")),",
|
||||||
" (\"f3\", \"i32\", 123),",
|
" (\"f3\", \"i32\", 123),",
|
||||||
" (\"fraction\", \"Fraction\", (1, 2)),",
|
" (\"fraction\", \"Fraction\", (1, 2)),",
|
||||||
" (\"array\", \"Array\", [",
|
" (\"array\", \"Array\", [",
|
||||||
|
@ -210,8 +210,8 @@ mod tests {
|
||||||
|
|
||||||
let s_ron = r#"
|
let s_ron = r#"
|
||||||
("test", [
|
("test", [
|
||||||
("f1", "String", "abc"),
|
("f1", "String", Some("abc")),
|
||||||
("f2", "String", "bcd"),
|
("f2", "String", Some("bcd")),
|
||||||
("f3", "i32", 123),
|
("f3", "i32", 123),
|
||||||
("fraction", "Fraction", (1, 2)),
|
("fraction", "Fraction", (1, 2)),
|
||||||
("array", "Array", [
|
("array", "Array", [
|
||||||
|
@ -242,7 +242,7 @@ mod tests {
|
||||||
|
|
||||||
let s = Structure::builder("test")
|
let s = Structure::builder("test")
|
||||||
.field("f1", &"abc")
|
.field("f1", &"abc")
|
||||||
.field("f2", &String::from("bcd"))
|
.field("f2", &"bcd".to_owned())
|
||||||
.field("f3", &123i32)
|
.field("f3", &123i32)
|
||||||
.field("fraction", &Fraction::new(1, 2))
|
.field("fraction", &Fraction::new(1, 2))
|
||||||
.field("array", &Array::new(&[&1, &2]))
|
.field("array", &Array::new(&[&1, &2]))
|
||||||
|
|
|
@ -27,13 +27,26 @@ use Sample;
|
||||||
use TagMergeMode;
|
use TagMergeMode;
|
||||||
use TagScope;
|
use TagScope;
|
||||||
|
|
||||||
macro_rules! ser_tag (
|
macro_rules! ser_some_tag (
|
||||||
($value:ident, $seq:ident, $t:ty) => (
|
($value:ident, $seq:ident, $t:ty) => (
|
||||||
ser_value!($value, $t, |_, value| {
|
ser_some_value!($value, $t, |_, value| {
|
||||||
$seq.serialize_element(&value)
|
$seq.serialize_element(&value)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
);
|
);
|
||||||
|
macro_rules! ser_opt_tag (
|
||||||
|
($value:ident, $seq:ident, $t:ty) => (
|
||||||
|
ser_opt_value!($value, $t, |_, value| {
|
||||||
|
$seq.serialize_element(&value)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
|
// Note: unlike `Value`s, `Tag`s with optional `Type` `String` & `Date` values are guarenteed
|
||||||
|
// to be Non-null and non-empty in the C API. See:
|
||||||
|
// https://gitlab.freedesktop.org/gstreamer/gstreamer/blob/d90d771a9a512381315f7694c3a50b152035f3cb/gst/gststructure.c#L810-853
|
||||||
|
|
||||||
|
// FIXME: implement serde for type `Date`
|
||||||
|
|
||||||
// serialize trait is only available for `&self`, but we need to mutate the iterator
|
// serialize trait is only available for `&self`, but we need to mutate the iterator
|
||||||
struct TagValuesSer<'a>(Rc<RefCell<GenericTagIter<'a>>>);
|
struct TagValuesSer<'a>(Rc<RefCell<GenericTagIter<'a>>>);
|
||||||
|
@ -51,15 +64,20 @@ impl<'a> Serialize for TagValuesSer<'a> {
|
||||||
let mut seq = serializer.serialize_seq(tag_iter.size_hint().1)?;
|
let mut seq = serializer.serialize_seq(tag_iter.size_hint().1)?;
|
||||||
for value in tag_iter.deref_mut() {
|
for value in tag_iter.deref_mut() {
|
||||||
match value.type_() {
|
match value.type_() {
|
||||||
glib::Type::F64 => ser_tag!(value, seq, f64),
|
glib::Type::F64 => ser_some_tag!(value, seq, f64),
|
||||||
glib::Type::String => ser_tag!(value, seq, String),
|
glib::Type::String => {
|
||||||
glib::Type::U32 => ser_tag!(value, seq, u32),
|
// See above comment about `Tag`s with `String` values
|
||||||
glib::Type::U64 => ser_tag!(value, seq, u64),
|
ser_opt_value!(value, String, |_, value: Option<String>| {
|
||||||
|
seq.serialize_element(&value.expect("string tag ser"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
glib::Type::U32 => ser_some_tag!(value, seq, u32),
|
||||||
|
glib::Type::U64 => ser_some_tag!(value, seq, u64),
|
||||||
glib::Type::Other(type_id) => {
|
glib::Type::Other(type_id) => {
|
||||||
if *DATE_TIME_OTHER_TYPE_ID == type_id {
|
if *DATE_TIME_OTHER_TYPE_ID == type_id {
|
||||||
ser_tag!(value, seq, DateTime)
|
ser_opt_tag!(value, seq, DateTime)
|
||||||
} else if *SAMPLE_OTHER_TYPE_ID == type_id {
|
} else if *SAMPLE_OTHER_TYPE_ID == type_id {
|
||||||
ser_tag!(value, seq, Sample)
|
ser_opt_tag!(value, seq, Sample)
|
||||||
} else {
|
} else {
|
||||||
Err(ser::Error::custom(format!(
|
Err(ser::Error::custom(format!(
|
||||||
"unimplemented `Tag` serialization for type {}",
|
"unimplemented `Tag` serialization for type {}",
|
||||||
|
@ -128,9 +146,14 @@ impl Serialize for TagList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! de_tag_value(
|
macro_rules! de_some_tag(
|
||||||
($tag_name:expr, $seq:expr, $t:ty) => (
|
($tag_name:expr, $seq:expr, $t:ty) => (
|
||||||
de_send_value!("Tag", $tag_name, $seq, $t)
|
de_some_send_value!("Tag", $tag_name, $seq, $t)
|
||||||
|
);
|
||||||
|
);
|
||||||
|
macro_rules! de_opt_tag(
|
||||||
|
($tag_name:expr, $seq:expr, $t:ty) => (
|
||||||
|
de_opt_send_value!("Tag", $tag_name, $seq, $t)
|
||||||
);
|
);
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -152,15 +175,18 @@ impl<'de, 'a> Visitor<'de> for TagValuesVisitor<'a> {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let tag_value = match tag_type {
|
let tag_value = match tag_type {
|
||||||
glib::Type::F64 => de_tag_value!(self.0, seq, f64),
|
glib::Type::F64 => de_some_tag!(self.0, seq, f64),
|
||||||
glib::Type::String => de_tag_value!(self.0, seq, String),
|
glib::Type::String => {
|
||||||
glib::Type::U32 => de_tag_value!(self.0, seq, u32),
|
// See comment above `TagValuesSer` definition about `Tag`s with `String` values
|
||||||
glib::Type::U64 => de_tag_value!(self.0, seq, u64),
|
de_some_tag!(self.0, seq, String)
|
||||||
|
}
|
||||||
|
glib::Type::U32 => de_some_tag!(self.0, seq, u32),
|
||||||
|
glib::Type::U64 => de_some_tag!(self.0, seq, u64),
|
||||||
glib::Type::Other(type_id) => {
|
glib::Type::Other(type_id) => {
|
||||||
if *DATE_TIME_OTHER_TYPE_ID == type_id {
|
if *DATE_TIME_OTHER_TYPE_ID == type_id {
|
||||||
de_tag_value!(self.0, seq, DateTime)
|
de_opt_tag!(self.0, seq, DateTime)
|
||||||
} else if *SAMPLE_OTHER_TYPE_ID == type_id {
|
} else if *SAMPLE_OTHER_TYPE_ID == type_id {
|
||||||
de_tag_value!(self.0, seq, Sample)
|
de_opt_tag!(self.0, seq, Sample)
|
||||||
} else {
|
} else {
|
||||||
return Err(de::Error::custom(format!(
|
return Err(de::Error::custom(format!(
|
||||||
"unimplemented deserialization for `Tag` {} with type `{}`",
|
"unimplemented deserialization for `Tag` {} with type `{}`",
|
||||||
|
@ -339,10 +365,10 @@ mod tests {
|
||||||
" 1,",
|
" 1,",
|
||||||
" ]),",
|
" ]),",
|
||||||
" (\"datetime\", [",
|
" (\"datetime\", [",
|
||||||
" YMD(2018, 5, 28),",
|
" Some(YMD(2018, 5, 28)),",
|
||||||
" ]),",
|
" ]),",
|
||||||
" (\"image\", [",
|
" (\"image\", [",
|
||||||
" (",
|
" Some((",
|
||||||
" buffer: Some((",
|
" buffer: Some((",
|
||||||
" pts: None,",
|
" pts: None,",
|
||||||
" dts: None,",
|
" dts: None,",
|
||||||
|
@ -372,7 +398,7 @@ mod tests {
|
||||||
" duration: -1,",
|
" duration: -1,",
|
||||||
" )),",
|
" )),",
|
||||||
" info: None,",
|
" info: None,",
|
||||||
" ),",
|
" )),",
|
||||||
" ]),",
|
" ]),",
|
||||||
" ],",
|
" ],",
|
||||||
")",
|
")",
|
||||||
|
@ -400,10 +426,10 @@ mod tests {
|
||||||
("bitrate", [96000]),
|
("bitrate", [96000]),
|
||||||
("replaygain-track-gain", [1]),
|
("replaygain-track-gain", [1]),
|
||||||
("datetime", [
|
("datetime", [
|
||||||
YMD(2018, 5, 28),
|
Some(YMD(2018, 5, 28)),
|
||||||
]),
|
]),
|
||||||
("image", [
|
("image", [
|
||||||
(
|
Some((
|
||||||
buffer: Some((
|
buffer: Some((
|
||||||
pts: None,
|
pts: None,
|
||||||
dts: None,
|
dts: None,
|
||||||
|
@ -419,7 +445,7 @@ mod tests {
|
||||||
caps: None,
|
caps: None,
|
||||||
segment: None,
|
segment: None,
|
||||||
info: None,
|
info: None,
|
||||||
),
|
)),
|
||||||
])
|
])
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -433,11 +459,11 @@ mod tests {
|
||||||
Some("another title")
|
Some("another title")
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tags.get_index::<Duration>(0).unwrap().get(),
|
tags.get_index::<Duration>(0).unwrap().get_some(),
|
||||||
Some(::SECOND * 120)
|
::SECOND * 120
|
||||||
);
|
);
|
||||||
assert_eq!(tags.get_index::<Bitrate>(0).unwrap().get(), Some(96_000));
|
assert_eq!(tags.get_index::<Bitrate>(0).unwrap().get_some(), 96_000);
|
||||||
assert_eq!(tags.get_index::<TrackGain>(0).unwrap().get(), Some(1f64));
|
assert_eq!(tags.get_index::<TrackGain>(0).unwrap().get_some(), 1f64);
|
||||||
let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap();
|
let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap();
|
||||||
assert_eq!(datetime.get_year(), 2018);
|
assert_eq!(datetime.get_year(), 2018);
|
||||||
assert_eq!(datetime.get_month(), 5);
|
assert_eq!(datetime.get_month(), 5);
|
||||||
|
@ -470,8 +496,8 @@ mod tests {
|
||||||
tags.get_index::<Title>(1).unwrap().get(),
|
tags.get_index::<Title>(1).unwrap().get(),
|
||||||
Some("another title")
|
Some("another title")
|
||||||
);
|
);
|
||||||
assert_eq!(tags.get_index::<Bitrate>(0).unwrap().get(), Some(96_000));
|
assert_eq!(tags.get_index::<Bitrate>(0).unwrap().get_some(), 96_000);
|
||||||
assert_eq!(tags.get_index::<TrackGain>(0).unwrap().get(), Some(1f64));
|
assert_eq!(tags.get_index::<TrackGain>(0).unwrap().get_some(), 1f64);
|
||||||
let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap();
|
let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap();
|
||||||
assert_eq!(datetime.get_year(), 2018);
|
assert_eq!(datetime.get_year(), 2018);
|
||||||
assert_eq!(datetime.get_month(), 5);
|
assert_eq!(datetime.get_month(), 5);
|
||||||
|
@ -525,16 +551,16 @@ mod tests {
|
||||||
tags.get_index::<Title>(1).unwrap().get(),
|
tags.get_index::<Title>(1).unwrap().get(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tags_de.get_index::<Duration>(0).unwrap().get(),
|
tags_de.get_index::<Duration>(0).unwrap().get_some(),
|
||||||
tags.get_index::<Duration>(0).unwrap().get(),
|
tags.get_index::<Duration>(0).unwrap().get_some(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tags_de.get_index::<Bitrate>(0).unwrap().get(),
|
tags_de.get_index::<Bitrate>(0).unwrap().get_some(),
|
||||||
tags.get_index::<Bitrate>(0).unwrap().get(),
|
tags.get_index::<Bitrate>(0).unwrap().get_some(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tags_de.get_index::<TrackGain>(0).unwrap().get(),
|
tags_de.get_index::<TrackGain>(0).unwrap().get_some(),
|
||||||
tags.get_index::<TrackGain>(0).unwrap().get(),
|
tags.get_index::<TrackGain>(0).unwrap().get_some(),
|
||||||
);
|
);
|
||||||
let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap();
|
let datetime = tags.get_index::<DateTime>(0).unwrap().get().unwrap();
|
||||||
assert_eq!(datetime.get_year(), 2018);
|
assert_eq!(datetime.get_year(), 2018);
|
||||||
|
|
|
@ -31,6 +31,8 @@ fn get_other_type_id<T: StaticType>() -> usize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: implement serde for type `Date`
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub(crate) static ref ARRAY_OTHER_TYPE_ID: usize = get_other_type_id::<Array>();
|
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 BITMASK_OTHER_TYPE_ID: usize = get_other_type_id::<Bitmask>();
|
||||||
|
@ -58,48 +60,56 @@ impl<'de> Deserialize<'de> for Fraction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! ser_value (
|
macro_rules! ser_some_value (
|
||||||
($value:expr, $t:ty, $ser_closure:expr) => (
|
($value:expr, $t:ty, $ser_closure:expr) => (
|
||||||
{
|
{
|
||||||
// FIXME: This should serialize to an `Option` when the `Type` allows it
|
let value = $value.get_some::<$t>().expect("ser_some_value macro");
|
||||||
// See https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/issues/215
|
|
||||||
let value = $value.get::<$t>().expect("Value serialization macro").unwrap();
|
|
||||||
$ser_closure(stringify!($t), value)
|
$ser_closure(stringify!($t), value)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
);
|
||||||
|
macro_rules! ser_opt_value (
|
||||||
|
($value:expr, $t:ty, $ser_closure:expr) => (
|
||||||
|
{
|
||||||
|
let value = $value.get::<$t>().expect("ser_opt_value macro");
|
||||||
|
$ser_closure(stringify!($t), value)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
);
|
||||||
|
macro_rules! ser_value (
|
||||||
($value:expr, $ser_closure:expr) => (
|
($value:expr, $ser_closure:expr) => (
|
||||||
match $value.type_() {
|
match $value.type_() {
|
||||||
glib::Type::I8 => ser_value!($value, i8, $ser_closure),
|
glib::Type::I8 => ser_some_value!($value, i8, $ser_closure),
|
||||||
glib::Type::U8 => ser_value!($value, u8, $ser_closure),
|
glib::Type::U8 => ser_some_value!($value, u8, $ser_closure),
|
||||||
glib::Type::Bool => ser_value!($value, bool, $ser_closure),
|
glib::Type::Bool => ser_some_value!($value, bool, $ser_closure),
|
||||||
glib::Type::I32 => ser_value!($value, i32, $ser_closure),
|
glib::Type::I32 => ser_some_value!($value, i32, $ser_closure),
|
||||||
glib::Type::U32 => ser_value!($value, u32, $ser_closure),
|
glib::Type::U32 => ser_some_value!($value, u32, $ser_closure),
|
||||||
glib::Type::I64 => ser_value!($value, i64, $ser_closure),
|
glib::Type::I64 => ser_some_value!($value, i64, $ser_closure),
|
||||||
glib::Type::U64 => ser_value!($value, u64, $ser_closure),
|
glib::Type::U64 => ser_some_value!($value, u64, $ser_closure),
|
||||||
glib::Type::F32 => ser_value!($value, f32, $ser_closure),
|
glib::Type::F32 => ser_some_value!($value, f32, $ser_closure),
|
||||||
glib::Type::F64 => ser_value!($value, f64, $ser_closure),
|
glib::Type::F64 => ser_some_value!($value, f64, $ser_closure),
|
||||||
glib::Type::String => ser_value!($value, String, $ser_closure),
|
glib::Type::String => ser_opt_value!($value, String, $ser_closure),
|
||||||
glib::Type::Other(type_id) => {
|
glib::Type::Other(type_id) => {
|
||||||
if *ARRAY_OTHER_TYPE_ID == type_id {
|
if *ARRAY_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, Array, $ser_closure)
|
ser_some_value!($value, Array, $ser_closure)
|
||||||
} else if *BITMASK_OTHER_TYPE_ID == type_id {
|
} else if *BITMASK_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, Bitmask, $ser_closure)
|
ser_some_value!($value, Bitmask, $ser_closure)
|
||||||
} else if *DATE_TIME_OTHER_TYPE_ID == type_id {
|
} else if *DATE_TIME_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, DateTime, $ser_closure)
|
ser_opt_value!($value, DateTime, $ser_closure)
|
||||||
} else if *FRACTION_OTHER_TYPE_ID == type_id {
|
} else if *FRACTION_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, Fraction, $ser_closure)
|
ser_some_value!($value, Fraction, $ser_closure)
|
||||||
} else if *FRACTION_RANGE_OTHER_TYPE_ID == type_id {
|
} else if *FRACTION_RANGE_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, FractionRange, $ser_closure)
|
ser_some_value!($value, FractionRange, $ser_closure)
|
||||||
} else if *INT_RANGE_I32_OTHER_TYPE_ID == type_id {
|
} else if *INT_RANGE_I32_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, IntRange<i32>, $ser_closure)
|
ser_some_value!($value, IntRange<i32>, $ser_closure)
|
||||||
} else if *INT_RANGE_I64_OTHER_TYPE_ID == type_id {
|
} else if *INT_RANGE_I64_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, IntRange<i64>, $ser_closure)
|
ser_some_value!($value, IntRange<i64>, $ser_closure)
|
||||||
} else if *LIST_OTHER_TYPE_ID == type_id {
|
} else if *LIST_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, List, $ser_closure)
|
ser_some_value!($value, List, $ser_closure)
|
||||||
} else if *SAMPLE_OTHER_TYPE_ID == type_id {
|
} else if *SAMPLE_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, Sample, $ser_closure)
|
ser_opt_value!($value, Sample, $ser_closure)
|
||||||
} else if *BUFFER_OTHER_TYPE_ID == type_id {
|
} else if *BUFFER_OTHER_TYPE_ID == type_id {
|
||||||
ser_value!($value, Buffer, $ser_closure)
|
ser_opt_value!($value, Buffer, $ser_closure)
|
||||||
} else {
|
} else {
|
||||||
Err(
|
Err(
|
||||||
ser::Error::custom(
|
ser::Error::custom(
|
||||||
|
@ -162,25 +172,28 @@ macro_rules! impl_ser_send_value_collection (
|
||||||
impl_ser_send_value_collection!(Array);
|
impl_ser_send_value_collection!(Array);
|
||||||
impl_ser_send_value_collection!(List);
|
impl_ser_send_value_collection!(List);
|
||||||
|
|
||||||
macro_rules! de_value(
|
macro_rules! de_some_send_value(
|
||||||
($seq:expr, $t:ty) => (
|
|
||||||
{
|
|
||||||
let value = $seq
|
|
||||||
.next_element::<$t>()?
|
|
||||||
.map(|base_value| base_value.to_value());
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
);
|
|
||||||
|
|
||||||
macro_rules! de_send_value(
|
|
||||||
($type_name:expr, $seq:expr, $t:ty) => (
|
($type_name:expr, $seq:expr, $t:ty) => (
|
||||||
de_send_value!("Value", $type_name, $seq, $t)
|
de_some_send_value!("Value", $type_name, $seq, $t)
|
||||||
);
|
);
|
||||||
($outer_type:expr, $type_name:expr, $seq:expr, $t:ty) => (
|
($outer_type:expr, $type_name:expr, $seq:expr, $t:ty) => (
|
||||||
match de_value!($seq, $t)? {
|
de_send_value!($outer_type, $type_name, $seq, $t, $t)
|
||||||
Some(value) => {
|
);
|
||||||
let glib_send_value = value
|
);
|
||||||
|
macro_rules! de_opt_send_value(
|
||||||
|
($type_name:expr, $seq:expr, $t:ty) => (
|
||||||
|
de_opt_send_value!("Value", $type_name, $seq, $t)
|
||||||
|
);
|
||||||
|
($outer_type:expr, $type_name:expr, $seq:expr, $t:ty) => (
|
||||||
|
de_send_value!($outer_type, $type_name, $seq, Option<$t>, $t)
|
||||||
|
);
|
||||||
|
);
|
||||||
|
macro_rules! de_send_value(
|
||||||
|
($outer_type:expr, $type_name:expr, $seq:expr, $elem_t:ty, $t:ty) => (
|
||||||
|
Ok(match $seq.next_element::<$elem_t>()? {
|
||||||
|
Some(base_value) => {
|
||||||
|
Some(SendValue::from(base_value
|
||||||
|
.to_value()
|
||||||
.try_into_send_value::<$t>()
|
.try_into_send_value::<$t>()
|
||||||
.map_err(|_|
|
.map_err(|_|
|
||||||
de::Error::custom(format!(
|
de::Error::custom(format!(
|
||||||
|
@ -188,33 +201,33 @@ macro_rules! de_send_value(
|
||||||
$outer_type,
|
$outer_type,
|
||||||
$type_name,
|
$type_name,
|
||||||
))
|
))
|
||||||
)?;
|
)?
|
||||||
Ok(Some(SendValue::from(glib_send_value)))
|
))
|
||||||
}
|
}
|
||||||
None => Ok(None)
|
None => None
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
($type_name:expr, $seq:expr) => (
|
($type_name:expr, $seq:expr) => (
|
||||||
match $type_name.as_str() {
|
match $type_name.as_str() {
|
||||||
"i8" => de_send_value!($type_name, $seq, i8),
|
"i8" => de_some_send_value!($type_name, $seq, i8),
|
||||||
"u8" => de_send_value!($type_name, $seq, u8),
|
"u8" => de_some_send_value!($type_name, $seq, u8),
|
||||||
"bool" => de_send_value!($type_name, $seq, bool),
|
"bool" => de_some_send_value!($type_name, $seq, bool),
|
||||||
"i32" => de_send_value!($type_name, $seq, i32),
|
"i32" => de_some_send_value!($type_name, $seq, i32),
|
||||||
"u32" => de_send_value!($type_name, $seq, u32),
|
"u32" => de_some_send_value!($type_name, $seq, u32),
|
||||||
"i64" => de_send_value!($type_name, $seq, i64),
|
"i64" => de_some_send_value!($type_name, $seq, i64),
|
||||||
"u64" => de_send_value!($type_name, $seq, u64),
|
"u64" => de_some_send_value!($type_name, $seq, u64),
|
||||||
"f32" => de_send_value!($type_name, $seq, f32),
|
"f32" => de_some_send_value!($type_name, $seq, f32),
|
||||||
"f64" => de_send_value!($type_name, $seq, f64),
|
"f64" => de_some_send_value!($type_name, $seq, f64),
|
||||||
"String" => de_send_value!($type_name, $seq, String),
|
"String" => de_opt_send_value!($type_name, $seq, String),
|
||||||
"Array" => de_send_value!($type_name, $seq, Array),
|
"Array" => de_some_send_value!($type_name, $seq, Array),
|
||||||
"Bitmask" => de_send_value!($type_name, $seq, Bitmask),
|
"Bitmask" => de_some_send_value!($type_name, $seq, Bitmask),
|
||||||
"DateTime" => de_send_value!($type_name, $seq, DateTime),
|
"DateTime" => de_opt_send_value!($type_name, $seq, DateTime),
|
||||||
"Fraction" => de_send_value!($type_name, $seq, Fraction),
|
"Fraction" => de_some_send_value!($type_name, $seq, Fraction),
|
||||||
"FractionRange" => de_send_value!($type_name, $seq, FractionRange),
|
"FractionRange" => de_some_send_value!($type_name, $seq, FractionRange),
|
||||||
"IntRange<i32>" => de_send_value!($type_name, $seq, IntRange<i32>),
|
"IntRange<i32>" => de_some_send_value!($type_name, $seq, IntRange<i32>),
|
||||||
"IntRange<i64>" => de_send_value!($type_name, $seq, IntRange<i64>),
|
"IntRange<i64>" => de_some_send_value!($type_name, $seq, IntRange<i64>),
|
||||||
"Sample" => de_send_value!($type_name, $seq, Sample),
|
"Sample" => de_opt_send_value!($type_name, $seq, Sample),
|
||||||
"Buffer" => de_send_value!($type_name, $seq, Buffer),
|
"Buffer" => de_opt_send_value!($type_name, $seq, Buffer),
|
||||||
_ => return Err(
|
_ => return Err(
|
||||||
de::Error::custom(
|
de::Error::custom(
|
||||||
format!(
|
format!(
|
||||||
|
@ -344,7 +357,16 @@ mod tests {
|
||||||
let value_str = "test str".to_value();
|
let value_str = "test str".to_value();
|
||||||
let send_value_str = value_str.try_into_send_value::<String>().unwrap();
|
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 str_none: Option<&str> = None;
|
||||||
|
let value_str_none = str_none.to_value();
|
||||||
|
let send_value_str_none = value_str_none.try_into_send_value::<String>().unwrap();
|
||||||
|
|
||||||
|
let array = Array::new(&[
|
||||||
|
&send_value_13,
|
||||||
|
&send_value_12,
|
||||||
|
&send_value_str,
|
||||||
|
&send_value_str_none,
|
||||||
|
]);
|
||||||
|
|
||||||
let res = ron::ser::to_string_pretty(&array, pretty_config.clone());
|
let res = ron::ser::to_string_pretty(&array, pretty_config.clone());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -352,7 +374,8 @@ mod tests {
|
||||||
"[",
|
"[",
|
||||||
" (\"Fraction\", (1, 3)),",
|
" (\"Fraction\", (1, 3)),",
|
||||||
" (\"Fraction\", (1, 2)),",
|
" (\"Fraction\", (1, 2)),",
|
||||||
" (\"String\", \"test str\"),",
|
" (\"String\", Some(\"test str\")),",
|
||||||
|
" (\"String\", None),",
|
||||||
"]"
|
"]"
|
||||||
)
|
)
|
||||||
.to_owned()),
|
.to_owned()),
|
||||||
|
@ -361,7 +384,8 @@ mod tests {
|
||||||
|
|
||||||
let res = serde_json::to_string(&array).unwrap();
|
let res = serde_json::to_string(&array).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"[[\"Fraction\",[1,3]],[\"Fraction\",[1,2]],[\"String\",\"test str\"]]".to_owned(),
|
"[[\"Fraction\",[1,3]],[\"Fraction\",[1,2]],[\"String\",\"test str\"],[\"String\",null]]"
|
||||||
|
.to_owned(),
|
||||||
res
|
res
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -372,14 +396,19 @@ mod tests {
|
||||||
let value_str = "test str".to_value();
|
let value_str = "test str".to_value();
|
||||||
let send_value_str = value_str.try_into_send_value::<String>().unwrap();
|
let send_value_str = value_str.try_into_send_value::<String>().unwrap();
|
||||||
|
|
||||||
let list = List::new(&[&send_value_12, &send_value_str]);
|
let str_none: Option<&str> = None;
|
||||||
|
let value_str_none = str_none.to_value();
|
||||||
|
let send_value_str_none = value_str_none.try_into_send_value::<String>().unwrap();
|
||||||
|
|
||||||
|
let list = List::new(&[&send_value_12, &send_value_str, &send_value_str_none]);
|
||||||
|
|
||||||
let res = ron::ser::to_string_pretty(&list, pretty_config.clone());
|
let res = ron::ser::to_string_pretty(&list, pretty_config.clone());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok(concat!(
|
Ok(concat!(
|
||||||
"[",
|
"[",
|
||||||
" (\"Fraction\", (1, 2)),",
|
" (\"Fraction\", (1, 2)),",
|
||||||
" (\"String\", \"test str\"),",
|
" (\"String\", Some(\"test str\")),",
|
||||||
|
" (\"String\", None),",
|
||||||
"]"
|
"]"
|
||||||
)
|
)
|
||||||
.to_owned()),
|
.to_owned()),
|
||||||
|
@ -387,7 +416,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ser_de")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialize_simple() {
|
fn test_deserialize_simple() {
|
||||||
::init().unwrap();
|
::init().unwrap();
|
||||||
|
@ -439,7 +467,6 @@ mod tests {
|
||||||
assert_eq!(bitmask_ref, bitmask);
|
assert_eq!(bitmask_ref, bitmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ser_de")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serde_roundtrip_simple() {
|
fn test_serde_roundtrip_simple() {
|
||||||
::init().unwrap();
|
::init().unwrap();
|
||||||
|
@ -480,7 +507,6 @@ mod tests {
|
||||||
assert_eq!(bitmask_de, bitmask);
|
assert_eq!(bitmask_de, bitmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ser_de")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialize_collections() {
|
fn test_deserialize_collections() {
|
||||||
::init().unwrap();
|
::init().unwrap();
|
||||||
|
@ -489,11 +515,12 @@ mod tests {
|
||||||
let array_ron = r#"[
|
let array_ron = r#"[
|
||||||
("Fraction", (1, 3)),
|
("Fraction", (1, 3)),
|
||||||
("Fraction", (1, 2)),
|
("Fraction", (1, 2)),
|
||||||
("String", "test str"),
|
("String", Some("test str")),
|
||||||
|
("String", None),
|
||||||
]"#;
|
]"#;
|
||||||
let array: Array = ron::de::from_str(array_ron).unwrap();
|
let array: Array = ron::de::from_str(array_ron).unwrap();
|
||||||
let slice = array.as_slice();
|
let slice = array.as_slice();
|
||||||
assert_eq!(3, slice.len());
|
assert_eq!(4, slice.len());
|
||||||
|
|
||||||
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
|
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
|
||||||
assert_eq!(fraction.0.numer(), &1);
|
assert_eq!(fraction.0.numer(), &1);
|
||||||
|
@ -508,10 +535,13 @@ mod tests {
|
||||||
slice[2].get::<String>().expect("slice[2]").unwrap()
|
slice[2].get::<String>().expect("slice[2]").unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let array_json = r#"[["Fraction",[1,3]],["Fraction",[1,2]],["String","test str"]]"#;
|
assert!(slice[3].get::<String>().expect("slice[3]").is_none());
|
||||||
|
|
||||||
|
let array_json =
|
||||||
|
r#"[["Fraction",[1,3]],["Fraction",[1,2]],["String","test str"],["String",null]]"#;
|
||||||
let array: Array = serde_json::from_str(array_json).unwrap();
|
let array: Array = serde_json::from_str(array_json).unwrap();
|
||||||
let slice = array.as_slice();
|
let slice = array.as_slice();
|
||||||
assert_eq!(3, slice.len());
|
assert_eq!(4, slice.len());
|
||||||
|
|
||||||
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
|
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
|
||||||
assert_eq!(fraction.0.numer(), &1);
|
assert_eq!(fraction.0.numer(), &1);
|
||||||
|
@ -526,14 +556,17 @@ mod tests {
|
||||||
slice[2].get::<String>().expect("slice[2]").unwrap()
|
slice[2].get::<String>().expect("slice[2]").unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert!(slice[3].get::<String>().expect("slice[3]").is_none());
|
||||||
|
|
||||||
// List
|
// List
|
||||||
let list_ron = r#"[
|
let list_ron = r#"[
|
||||||
("Fraction", (1, 2)),
|
("Fraction", (1, 2)),
|
||||||
("String", "test str"),
|
("String", Some("test str")),
|
||||||
|
("String", None),
|
||||||
]"#;
|
]"#;
|
||||||
let list: List = ron::de::from_str(list_ron).unwrap();
|
let list: List = ron::de::from_str(list_ron).unwrap();
|
||||||
let slice = list.as_slice();
|
let slice = list.as_slice();
|
||||||
assert_eq!(2, slice.len());
|
assert_eq!(3, slice.len());
|
||||||
|
|
||||||
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
|
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
|
||||||
assert_eq!(fraction.0.numer(), &1);
|
assert_eq!(fraction.0.numer(), &1);
|
||||||
|
@ -543,9 +576,10 @@ mod tests {
|
||||||
"test str".to_owned(),
|
"test str".to_owned(),
|
||||||
slice[1].get::<String>().expect("slice[1]").unwrap()
|
slice[1].get::<String>().expect("slice[1]").unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert!(slice[2].get::<String>().expect("slice[2]").is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ser_de")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serde_roundtrip_collection() {
|
fn test_serde_roundtrip_collection() {
|
||||||
use glib::value::ToValue;
|
use glib::value::ToValue;
|
||||||
|
@ -559,7 +593,15 @@ mod tests {
|
||||||
let send_value_12 = value_12.try_into_send_value::<Fraction>().unwrap();
|
let send_value_12 = value_12.try_into_send_value::<Fraction>().unwrap();
|
||||||
let value_str = "test str".to_value();
|
let value_str = "test str".to_value();
|
||||||
let send_value_str = value_str.try_into_send_value::<String>().unwrap();
|
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 str_none: Option<&str> = None;
|
||||||
|
let value_str_none = str_none.to_value();
|
||||||
|
let send_value_str_none = value_str_none.try_into_send_value::<String>().unwrap();
|
||||||
|
let array = Array::new(&[
|
||||||
|
&send_value_13,
|
||||||
|
&send_value_12,
|
||||||
|
&send_value_str,
|
||||||
|
&send_value_str_none,
|
||||||
|
]);
|
||||||
let array_ser = ron::ser::to_string(&array).unwrap();
|
let array_ser = ron::ser::to_string(&array).unwrap();
|
||||||
|
|
||||||
let array_de: Array = ron::de::from_str(array_ser.as_str()).unwrap();
|
let array_de: Array = ron::de::from_str(array_ser.as_str()).unwrap();
|
||||||
|
@ -582,12 +624,17 @@ mod tests {
|
||||||
slice[2].get::<String>().expect("slice[2]").unwrap()
|
slice[2].get::<String>().expect("slice[2]").unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert!(slice[3].get::<String>().expect("slice[3]").is_none());
|
||||||
|
|
||||||
// List
|
// List
|
||||||
let value_12 = Fraction::new(1, 2).to_value();
|
let value_12 = Fraction::new(1, 2).to_value();
|
||||||
let send_value_12 = value_12.try_into_send_value::<Fraction>().unwrap();
|
let send_value_12 = value_12.try_into_send_value::<Fraction>().unwrap();
|
||||||
let value_str = "test str".to_value();
|
let value_str = "test str".to_value();
|
||||||
let send_value_str = value_str.try_into_send_value::<String>().unwrap();
|
let send_value_str = value_str.try_into_send_value::<String>().unwrap();
|
||||||
let list = List::new(&[&send_value_12, &send_value_str]);
|
let str_none: Option<&str> = None;
|
||||||
|
let value_str_none = str_none.to_value();
|
||||||
|
let send_value_str_none = value_str_none.try_into_send_value::<String>().unwrap();
|
||||||
|
let list = List::new(&[&send_value_12, &send_value_str, &send_value_str_none]);
|
||||||
let list_ser = ron::ser::to_string(&list).unwrap();
|
let list_ser = ron::ser::to_string(&list).unwrap();
|
||||||
|
|
||||||
let list_de: List = ron::de::from_str(list_ser.as_str()).unwrap();
|
let list_de: List = ron::de::from_str(list_ser.as_str()).unwrap();
|
||||||
|
@ -604,5 +651,7 @@ mod tests {
|
||||||
slice_de[1].get::<String>().expect("slice_de[1]").unwrap(),
|
slice_de[1].get::<String>().expect("slice_de[1]").unwrap(),
|
||||||
slice[1].get::<String>().expect("slice[1]").unwrap()
|
slice[1].get::<String>().expect("slice[1]").unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert!(slice[2].get::<String>().expect("slice[2]").is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue