mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-28 20:41:31 +00:00
Add De/Serialization for most bitflag types
Represents combinations of flags with a '+' separated string of nicks, or an empty string for no flags set. Note that most flag types will ignore any flags using multiple bits when serializing, since in most cases these flags cover all used bits.
This commit is contained in:
parent
94b5a13f4b
commit
1b22be2e15
34 changed files with 1631 additions and 158 deletions
|
@ -221,11 +221,14 @@ plugins-update-nightly:
|
|||
- |
|
||||
get_features() {
|
||||
crate=$1
|
||||
if [ "$crate" = "gstreamer" ]; then
|
||||
case "$crate" in
|
||||
gstreamer-audio|gstreamer-editing-services|gstreamer-gl|gstreamer-pbutils|gstreamer-rtp|gstreamer-rtsp|gstreamer-video|gstreamer)
|
||||
echo "--features=ser_de,v1_22"
|
||||
else
|
||||
;;
|
||||
*)
|
||||
echo "--features=v1_22"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
for crate in gstreamer* gstreamer-gl/{egl,wayland,x11}; do
|
||||
if [ -e $crate/Cargo.toml ]; then
|
||||
|
@ -368,11 +371,14 @@ clippy:
|
|||
- |
|
||||
get_features() {
|
||||
crate=$1
|
||||
if [ "$crate" = "gstreamer" ]; then
|
||||
case "$crate" in
|
||||
gstreamer-audio|gstreamer-editing-services|gstreamer-gl|gstreamer-pbutils|gstreamer-rtp|gstreamer-rtsp|gstreamer-video|gstreamer)
|
||||
echo "--features=ser_de,v1_22"
|
||||
else
|
||||
;;
|
||||
*)
|
||||
echo "--features=v1_22"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
for crate in gstreamer* gstreamer-gl/{egl,wayland,x11}; do
|
||||
if [ -e $crate/Cargo.toml ]; then
|
||||
|
|
|
@ -23,9 +23,11 @@ gst = { package = "gstreamer", path = "../gstreamer" }
|
|||
gst-base = { package = "gstreamer-base", path = "../gstreamer-base" }
|
||||
array-init = "2.0"
|
||||
once_cell = "1.0"
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
itertools = "0.10"
|
||||
serde_json = "1.0"
|
||||
gir-format-check = "0.1"
|
||||
|
||||
[features]
|
||||
|
@ -34,7 +36,8 @@ v1_16 = ["gst/v1_16", "gst-base/v1_16", "ffi/v1_16"]
|
|||
v1_18 = ["gst/v1_18", "gst-base/v1_18", "ffi/v1_18", "v1_16"]
|
||||
v1_20 = ["gst/v1_20", "gst-base/v1_20", "ffi/v1_20", "v1_18"]
|
||||
v1_22 = ["gst/v1_22", "gst-base/v1_22", "ffi/v1_22", "v1_20"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "gst-base/dox"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "gst-base/dox", "ser_de"]
|
||||
ser_de = ["serde", "gst/ser_de"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["dox"]
|
||||
|
|
76
gstreamer-audio/src/flag_serde.rs
Normal file
76
gstreamer-audio/src/flag_serde.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, ToGlibPtr};
|
||||
use glib::{FlagsClass, StaticType, ToValue};
|
||||
use gst::bitflags_serde_impl;
|
||||
|
||||
bitflags_serde_impl!(crate::AudioFlags);
|
||||
bitflags_serde_impl!(crate::AudioFormatFlags);
|
||||
bitflags_serde_impl!(crate::AudioPackFlags);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! check_serialize {
|
||||
($flags:expr, $expected:expr) => {
|
||||
let actual = serde_json::to_string(&$flags).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_deserialize {
|
||||
($ty:ty, $expected:expr, $json:expr) => {
|
||||
let actual: $ty = serde_json::from_str(&$json).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_roundtrip {
|
||||
($ty:ty, $flags:expr) => {
|
||||
let json = serde_json::to_string(&$flags).unwrap();
|
||||
let deserialized: $ty = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, $flags);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_serialize!(crate::AudioFlags::all(), "\"unpositioned\"");
|
||||
check_serialize!(
|
||||
crate::AudioFormatFlags::all(),
|
||||
"\"integer+float+signed+complex+unpack\""
|
||||
);
|
||||
check_serialize!(crate::AudioPackFlags::all(), "\"truncate-range\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_deserialize!(
|
||||
crate::AudioFlags,
|
||||
crate::AudioFlags::all(),
|
||||
"\"unpositioned\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::AudioFormatFlags,
|
||||
crate::AudioFormatFlags::all(),
|
||||
"\"integer+float+signed+complex+unpack\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::AudioPackFlags,
|
||||
crate::AudioPackFlags::all(),
|
||||
"\"truncate-range\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_roundtrip!(crate::AudioFlags, crate::AudioFlags::all());
|
||||
check_roundtrip!(crate::AudioFormatFlags, crate::AudioFormatFlags::all());
|
||||
check_roundtrip!(crate::AudioPackFlags, crate::AudioPackFlags::all());
|
||||
}
|
||||
}
|
|
@ -31,6 +31,9 @@ macro_rules! skip_assert_initialized {
|
|||
mod auto;
|
||||
pub use crate::auto::*;
|
||||
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod flag_serde;
|
||||
|
||||
mod audio_format;
|
||||
pub use crate::audio_format::*;
|
||||
mod audio_format_info;
|
||||
|
|
|
@ -22,16 +22,19 @@ gio = { git = "https://github.com/gtk-rs/gtk-rs-core" }
|
|||
gst = { package = "gstreamer", path = "../gstreamer" }
|
||||
gst-base = { package = "gstreamer-base", path = "../gstreamer-base" }
|
||||
gst-pbutils = { package = "gstreamer-pbutils", path = "../gstreamer-pbutils" }
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
gir-format-check = "0.1"
|
||||
serde_json = "1.0"
|
||||
|
||||
[features]
|
||||
v1_16 = ["gst/v1_16", "gst-base/v1_16", "gst-pbutils/v1_16", "ffi/v1_16"]
|
||||
v1_18 = ["gst/v1_18", "gst-base/v1_18", "gst-pbutils/v1_18", "ffi/v1_18", "v1_16"]
|
||||
v1_20 = ["gst/v1_20", "gst-base/v1_20", "gst-pbutils/v1_20", "ffi/v1_20", "v1_18"]
|
||||
v1_22 = ["gst/v1_22", "gst-base/v1_22", "gst-pbutils/v1_22", "ffi/v1_22", "v1_20"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gio/dox", "gst/dox", "gst-base/dox", "gst-pbutils/dox"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gio/dox", "gst/dox", "gst-base/dox", "gst-pbutils/dox", "ser_de"]
|
||||
ser_de = ["serde", "gst/ser_de", "gst-pbutils/ser_de"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["dox"]
|
||||
|
|
90
gstreamer-editing-services/src/flag_serde.rs
Normal file
90
gstreamer-editing-services/src/flag_serde.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, ToGlibPtr};
|
||||
use glib::{FlagsClass, StaticType, ToValue};
|
||||
use gst::bitflags_serde_impl;
|
||||
|
||||
bitflags_serde_impl!(crate::MarkerFlags, "v1_20");
|
||||
bitflags_serde_impl!(crate::MetaFlag);
|
||||
bitflags_serde_impl!(crate::PipelineFlags);
|
||||
bitflags_serde_impl!(crate::TrackType);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! check_serialize {
|
||||
($flags:expr, $expected:expr) => {
|
||||
let actual = serde_json::to_string(&$flags).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_deserialize {
|
||||
($ty:ty, $expected:expr, $json:expr) => {
|
||||
let actual: $ty = serde_json::from_str(&$json).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_roundtrip {
|
||||
($ty:ty, $flags:expr) => {
|
||||
let json = serde_json::to_string(&$flags).unwrap();
|
||||
let deserialized: $ty = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, $flags);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(crate::MarkerFlags::all(), "\"snappable\"");
|
||||
check_serialize!(crate::MetaFlag::all(), "\"readable+writable\"");
|
||||
check_serialize!(
|
||||
crate::PipelineFlags::all(),
|
||||
"\"audio_preview+video_preview+render+smart_render\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::TrackType::all(),
|
||||
"\"unknown+audio+video+text+custom\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(
|
||||
crate::MarkerFlags,
|
||||
crate::MarkerFlags::all(),
|
||||
"\"snappable\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::MetaFlag,
|
||||
crate::MetaFlag::all(),
|
||||
"\"readable+writable\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::PipelineFlags,
|
||||
crate::PipelineFlags::all(),
|
||||
"\"audio_preview+video_preview+render+smart_render\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::TrackType,
|
||||
crate::TrackType::all(),
|
||||
"\"unknown+audio+video+text+custom\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
gst::init().unwrap();
|
||||
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(crate::MarkerFlags, crate::MarkerFlags::all());
|
||||
check_roundtrip!(crate::MetaFlag, crate::MetaFlag::all());
|
||||
check_roundtrip!(crate::PipelineFlags, crate::PipelineFlags::all());
|
||||
check_roundtrip!(crate::TrackType, crate::TrackType::all());
|
||||
}
|
||||
}
|
|
@ -62,6 +62,9 @@ macro_rules! skip_assert_initialized {
|
|||
mod auto;
|
||||
pub use crate::auto::*;
|
||||
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod flag_serde;
|
||||
|
||||
// Re-export all the traits in a prelude module, so that applications
|
||||
// can always "use ges::prelude::*" without getting conflicts
|
||||
pub mod prelude {
|
||||
|
|
|
@ -26,9 +26,11 @@ glib = { git = "https://github.com/gtk-rs/gtk-rs-core" }
|
|||
gst = { package = "gstreamer", path = "../gstreamer" }
|
||||
gst-base = { package = "gstreamer-base", path = "../gstreamer-base" }
|
||||
gst-video = { package = "gstreamer-video", path = "../gstreamer-video" }
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
gir-format-check = "0.1"
|
||||
serde_json = "1.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -36,7 +38,8 @@ v1_16 = ["gst/v1_16", "gst-base/v1_16", "gst-video/v1_16", "ffi/v1_16"]
|
|||
v1_18 = ["gst/v1_18", "gst-base/v1_18", "gst-video/v1_18", "ffi/v1_18", "v1_16"]
|
||||
v1_20 = ["gst/v1_20", "gst-base/v1_20", "gst-video/v1_20", "ffi/v1_20", "v1_18"]
|
||||
v1_22 = ["gst/v1_22", "gst-base/v1_22", "gst-video/v1_22", "ffi/v1_22", "v1_20"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "gst-base/dox", "gst-video/dox"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "gst-base/dox", "gst-video/dox", "ser_de"]
|
||||
ser_de = ["serde", "gst/ser_de", "gst-video/ser_de"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["dox"]
|
||||
|
|
110
gstreamer-gl/src/flag_serde.rs
Normal file
110
gstreamer-gl/src/flag_serde.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, ToGlibPtr};
|
||||
use glib::{FlagsClass, StaticType, ToValue};
|
||||
use gst::bitflags_serde_impl;
|
||||
|
||||
bitflags_serde_impl!(crate::GLAPI);
|
||||
bitflags_serde_impl!(crate::GLConfigSurfaceType, "v1_20");
|
||||
bitflags_serde_impl!(crate::GLDisplayType);
|
||||
bitflags_serde_impl!(crate::GLPlatform);
|
||||
bitflags_serde_impl!(crate::GLSLProfile);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! check_serialize {
|
||||
($flags:expr, $expected:expr) => {
|
||||
let actual = serde_json::to_string(&$flags).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_deserialize {
|
||||
($ty:ty, $expected:expr, $json:expr) => {
|
||||
let actual: $ty = serde_json::from_str(&$json).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_roundtrip {
|
||||
($ty:ty, $flags:expr) => {
|
||||
let json = serde_json::to_string(&$flags).unwrap();
|
||||
let deserialized: $ty = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, $flags);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_serialize!(crate::GLAPI::all(), "\"opengl+opengl3+gles1+gles2\"");
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(
|
||||
crate::GLConfigSurfaceType::all(),
|
||||
"\"window+pbuffer+pixmap\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(
|
||||
crate::GLDisplayType::all(),
|
||||
concat!(
|
||||
"\"x11+wayland+cocoa+win32+dispmanx+egl+viv-fb+gbm+egl-device",
|
||||
"+eagl+winrt+android\""
|
||||
)
|
||||
);
|
||||
check_serialize!(crate::GLPlatform::all(), "\"egl+glx+wgl+cgl+eagl\"");
|
||||
check_serialize!(crate::GLSLProfile::all(), "\"es+core+compatibility\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_deserialize!(
|
||||
crate::GLAPI,
|
||||
crate::GLAPI::all(),
|
||||
"\"opengl+opengl3+gles1+gles2\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(
|
||||
crate::GLConfigSurfaceType,
|
||||
crate::GLConfigSurfaceType::all(),
|
||||
"\"none+window+pbuffer+pixmap\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(
|
||||
crate::GLDisplayType,
|
||||
crate::GLDisplayType::all(),
|
||||
concat!(
|
||||
"\"x11+wayland+cocoa+win32+dispmanx+egl+viv-fb+gbm+egl-device",
|
||||
"+eagl+winrt+android\""
|
||||
)
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::GLPlatform,
|
||||
crate::GLPlatform::all(),
|
||||
"\"egl+glx+wgl+cgl+eagl\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::GLSLProfile,
|
||||
crate::GLSLProfile::all(),
|
||||
"\"es+core+compatibility\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_roundtrip!(crate::GLAPI, crate::GLAPI::all());
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(
|
||||
crate::GLConfigSurfaceType,
|
||||
crate::GLConfigSurfaceType::all()
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(crate::GLDisplayType, crate::GLDisplayType::all());
|
||||
check_roundtrip!(crate::GLPlatform, crate::GLPlatform::all());
|
||||
check_roundtrip!(crate::GLSLProfile, crate::GLSLProfile::all());
|
||||
}
|
||||
}
|
|
@ -32,6 +32,9 @@ mod auto;
|
|||
pub use crate::auto::functions::*;
|
||||
pub use crate::auto::*;
|
||||
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod flag_serde;
|
||||
|
||||
mod caps_features;
|
||||
pub use crate::caps_features::CAPS_FEATURES_MEMORY_GL_MEMORY;
|
||||
mod context;
|
||||
|
|
|
@ -20,9 +20,11 @@ ffi = { package = "gstreamer-pbutils-sys", path = "sys" }
|
|||
glib = { git = "https://github.com/gtk-rs/gtk-rs-core" }
|
||||
gst = { package = "gstreamer", path = "../gstreamer" }
|
||||
thiserror = "1.0"
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
gir-format-check = "0.1"
|
||||
serde_json = "1.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -30,7 +32,8 @@ v1_16 = ["gst/v1_16", "ffi/v1_16"]
|
|||
v1_18 = ["gst/v1_18", "ffi/v1_18", "v1_16"]
|
||||
v1_20 = ["gst/v1_20", "ffi/v1_20", "v1_18"]
|
||||
v1_22 = ["gst/v1_22", "ffi/v1_22", "v1_20"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "ser_de"]
|
||||
ser_de = ["serde", "gst/ser_de"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["dox"]
|
||||
|
|
77
gstreamer-pbutils/src/flag_serde.rs
Normal file
77
gstreamer-pbutils/src/flag_serde.rs
Normal file
|
@ -0,0 +1,77 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, ToGlibPtr};
|
||||
use glib::{FlagsClass, StaticType, ToValue};
|
||||
use gst::bitflags_serde_impl;
|
||||
|
||||
bitflags_serde_impl!(crate::DiscovererSerializeFlags);
|
||||
bitflags_serde_impl!(crate::PbUtilsCapsDescriptionFlags, "v1_20");
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! check_serialize {
|
||||
($flags:expr, $expected:expr) => {
|
||||
let actual = serde_json::to_string(&$flags).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_deserialize {
|
||||
($ty:ty, $expected:expr, $json:expr) => {
|
||||
let actual: $ty = serde_json::from_str(&$json).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_roundtrip {
|
||||
($ty:ty, $flags:expr) => {
|
||||
let json = serde_json::to_string(&$flags).unwrap();
|
||||
let deserialized: $ty = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, $flags);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_serialize!(crate::DiscovererSerializeFlags::all(), "\"caps+tags+misc\"");
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(
|
||||
crate::PbUtilsCapsDescriptionFlags::all(),
|
||||
"\"container+audio+video+image+subtitle+tag+generic\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_deserialize!(
|
||||
crate::DiscovererSerializeFlags,
|
||||
crate::DiscovererSerializeFlags::all(),
|
||||
"\"caps+tags+misc\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(
|
||||
crate::PbUtilsCapsDescriptionFlags,
|
||||
crate::PbUtilsCapsDescriptionFlags::all(),
|
||||
"\"container+audio+video+image+subtitle+tag+generic\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_roundtrip!(
|
||||
crate::DiscovererSerializeFlags,
|
||||
crate::DiscovererSerializeFlags::all()
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(
|
||||
crate::PbUtilsCapsDescriptionFlags,
|
||||
crate::PbUtilsCapsDescriptionFlags::all()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -38,6 +38,9 @@ mod auto;
|
|||
pub use crate::auto::functions::*;
|
||||
pub use crate::auto::*;
|
||||
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod flag_serde;
|
||||
|
||||
mod discoverer;
|
||||
pub use crate::discoverer::*;
|
||||
|
||||
|
|
|
@ -20,9 +20,11 @@ libc = "0.2"
|
|||
ffi = { package = "gstreamer-rtp-sys", path = "sys" }
|
||||
glib = { git = "https://github.com/gtk-rs/gtk-rs-core" }
|
||||
gst = { package = "gstreamer", path = "../gstreamer" }
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
gir-format-check = "0.1"
|
||||
serde_json = "1.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -30,7 +32,8 @@ v1_16 = ["gst/v1_16", "ffi/v1_16"]
|
|||
v1_18 = ["gst/v1_18", "ffi/v1_18", "v1_16"]
|
||||
v1_20 = ["gst/v1_20", "ffi/v1_20", "v1_18"]
|
||||
v1_22 = ["gst/v1_22", "ffi/v1_22", "v1_20"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "ser_de"]
|
||||
ser_de = ["serde", "gst/ser_de"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["dox"]
|
||||
|
|
114
gstreamer-rtp/src/flag_serde.rs
Normal file
114
gstreamer-rtp/src/flag_serde.rs
Normal file
|
@ -0,0 +1,114 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, ToGlibPtr};
|
||||
use glib::{FlagsClass, StaticType, ToValue};
|
||||
use gst::{bitflags_deserialize_impl, bitflags_serde_impl, bitflags_serialize_impl};
|
||||
|
||||
bitflags_serialize_impl!(crate::RTPBufferFlags, by_ones_decreasing);
|
||||
bitflags_deserialize_impl!(crate::RTPBufferFlags);
|
||||
bitflags_serde_impl!(crate::RTPBufferMapFlags);
|
||||
// use this implementation, since serializing to "sendonly+recvonly"
|
||||
// wouldn't make much sense
|
||||
bitflags_serialize_impl!(
|
||||
crate::RTPHeaderExtensionDirection,
|
||||
by_ones_decreasing,
|
||||
"v1_20"
|
||||
);
|
||||
bitflags_deserialize_impl!(crate::RTPHeaderExtensionDirection, "v1_20");
|
||||
bitflags_serde_impl!(crate::RTPHeaderExtensionFlags, "v1_20");
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! check_serialize {
|
||||
($flags:expr, $expected:expr) => {
|
||||
let actual = serde_json::to_string(&$flags).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_deserialize {
|
||||
($ty:ty, $expected:expr, $json:expr) => {
|
||||
let actual: $ty = serde_json::from_str(&$json).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_roundtrip {
|
||||
($ty:ty, $flags:expr) => {
|
||||
let json = serde_json::to_string(&$flags).unwrap();
|
||||
let deserialized: $ty = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, $flags);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_serialize!(crate::RTPBufferFlags::all(), "\"retransmission+redundant\"");
|
||||
check_serialize!(crate::RTPBufferMapFlags::all(), "\"skip-padding\"");
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(
|
||||
crate::RTPHeaderExtensionDirection::all(),
|
||||
"\"sendrecv+inherited\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(
|
||||
crate::RTPHeaderExtensionDirection::INACTIVE
|
||||
| crate::RTPHeaderExtensionDirection::SENDONLY
|
||||
| crate::RTPHeaderExtensionDirection::INHERITED,
|
||||
"\"sendonly+inherited\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(
|
||||
crate::RTPHeaderExtensionFlags::all(),
|
||||
"\"one-byte+two-byte\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_deserialize!(
|
||||
crate::RTPBufferFlags,
|
||||
crate::RTPBufferFlags::all(),
|
||||
"\"retransmission+redundant\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::RTPBufferMapFlags,
|
||||
crate::RTPBufferMapFlags::all(),
|
||||
"\"skip-padding\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(
|
||||
crate::RTPHeaderExtensionDirection,
|
||||
crate::RTPHeaderExtensionDirection::all(),
|
||||
"\"sendrecv+inactive+inherited\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(
|
||||
crate::RTPHeaderExtensionFlags,
|
||||
crate::RTPHeaderExtensionFlags::all(),
|
||||
"\"one-byte+two-byte\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_roundtrip!(crate::RTPBufferFlags, crate::RTPBufferFlags::all());
|
||||
check_roundtrip!(crate::RTPBufferMapFlags, crate::RTPBufferMapFlags::all());
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(
|
||||
crate::RTPHeaderExtensionDirection,
|
||||
crate::RTPHeaderExtensionDirection::all()
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(
|
||||
crate::RTPHeaderExtensionFlags,
|
||||
crate::RTPHeaderExtensionFlags::all()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -32,6 +32,9 @@ mod auto;
|
|||
pub use crate::auto::functions::*;
|
||||
pub use crate::auto::*;
|
||||
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod flag_serde;
|
||||
|
||||
pub mod subclass;
|
||||
|
||||
pub mod rtp_buffer;
|
||||
|
|
|
@ -24,9 +24,11 @@ gst = { package = "gstreamer", path = "../gstreamer" }
|
|||
gst-sdp = { package = "gstreamer-sdp", path = "../gstreamer-sdp" }
|
||||
gst-rtsp = { package = "gstreamer-rtsp", path = "../gstreamer-rtsp" }
|
||||
gst-net = { package = "gstreamer-net", path = "../gstreamer-net" }
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
gir-format-check = "0.1"
|
||||
serde_json = "1.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -34,7 +36,8 @@ v1_16 = ["gst/v1_16", "gst-sdp/v1_16", "gst-rtsp/v1_16", "gst-net/v1_16", "ffi/v
|
|||
v1_18 = ["gst/v1_18", "gst-sdp/v1_18", "gst-rtsp/v1_18", "gst-net/v1_18", "ffi/v1_18", "v1_16"]
|
||||
v1_20 = ["gst/v1_20", "gst-sdp/v1_20", "gst-rtsp/v1_20", "gst-net/v1_20", "ffi/v1_20", "v1_18"]
|
||||
v1_22 = ["gst/v1_22", "gst-sdp/v1_22", "gst-rtsp/v1_22", "gst-net/v1_22", "ffi/v1_22", "v1_20"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gio/dox", "gst/dox", "gst-sdp/dox", "gst-rtsp/dox", "gst-net/dox"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gio/dox", "gst/dox", "gst-sdp/dox", "gst-rtsp/dox", "gst-net/dox", "ser_de"]
|
||||
ser_de = ["serde", "gst/ser_de", "gst-rtsp/ser_de"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["dox"]
|
||||
|
|
57
gstreamer-rtsp-server/src/flag_serde.rs
Normal file
57
gstreamer-rtsp-server/src/flag_serde.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, ToGlibPtr};
|
||||
use glib::{FlagsClass, StaticType, ToValue};
|
||||
use gst::bitflags_serde_impl;
|
||||
|
||||
bitflags_serde_impl!(crate::RTSPTransportMode);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! check_serialize {
|
||||
($flags:expr, $expected:expr) => {
|
||||
let actual = serde_json::to_string(&$flags).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_deserialize {
|
||||
($ty:ty, $expected:expr, $json:expr) => {
|
||||
let actual: $ty = serde_json::from_str(&$json).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_roundtrip {
|
||||
($ty:ty, $flags:expr) => {
|
||||
let json = serde_json::to_string(&$flags).unwrap();
|
||||
let deserialized: $ty = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, $flags);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_serialize!(crate::RTSPTransportMode::all(), "\"play+record\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_deserialize!(
|
||||
crate::RTSPTransportMode,
|
||||
crate::RTSPTransportMode::all(),
|
||||
"\"play+record\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_roundtrip!(crate::RTSPTransportMode, crate::RTSPTransportMode::all());
|
||||
}
|
||||
}
|
|
@ -35,6 +35,9 @@ macro_rules! skip_assert_initialized {
|
|||
mod auto;
|
||||
pub use crate::auto::*;
|
||||
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod flag_serde;
|
||||
|
||||
mod rtsp_address_pool;
|
||||
mod rtsp_auth;
|
||||
mod rtsp_client;
|
||||
|
|
|
@ -20,9 +20,11 @@ ffi = { package = "gstreamer-rtsp-sys", path = "sys" }
|
|||
glib = { git = "https://github.com/gtk-rs/gtk-rs-core" }
|
||||
gst = { package = "gstreamer", path = "../gstreamer" }
|
||||
gst-sdp = { package = "gstreamer-sdp", path = "../gstreamer-sdp" }
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
gir-format-check = "0.1"
|
||||
serde_json = "1.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -30,7 +32,8 @@ v1_16 = ["gst/v1_16", "gst-sdp/v1_16", "ffi/v1_16"]
|
|||
v1_18 = ["gst/v1_18", "gst-sdp/v1_18", "ffi/v1_18", "v1_16"]
|
||||
v1_20 = ["gst/v1_20", "gst-sdp/v1_20", "ffi/v1_20", "v1_18"]
|
||||
v1_22 = ["gst/v1_22", "gst-sdp/v1_22", "ffi/v1_22", "v1_20"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "gst-sdp/dox"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "gst-sdp/dox", "ser_de"]
|
||||
ser_de = ["serde", "gst/ser_de"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["dox"]
|
||||
|
|
97
gstreamer-rtsp/src/flag_serde.rs
Normal file
97
gstreamer-rtsp/src/flag_serde.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, ToGlibPtr};
|
||||
use glib::{FlagsClass, StaticType, ToValue};
|
||||
use gst::bitflags_serde_impl;
|
||||
|
||||
bitflags_serde_impl!(crate::RTSPEvent);
|
||||
bitflags_serde_impl!(crate::RTSPLowerTrans);
|
||||
bitflags_serde_impl!(crate::RTSPMethod);
|
||||
bitflags_serde_impl!(crate::RTSPProfile);
|
||||
bitflags_serde_impl!(crate::RTSPTransMode);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! check_serialize {
|
||||
($flags:expr, $expected:expr) => {
|
||||
let actual = serde_json::to_string(&$flags).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_deserialize {
|
||||
($ty:ty, $expected:expr, $json:expr) => {
|
||||
let actual: $ty = serde_json::from_str(&$json).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_roundtrip {
|
||||
($ty:ty, $flags:expr) => {
|
||||
let json = serde_json::to_string(&$flags).unwrap();
|
||||
let deserialized: $ty = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, $flags);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_serialize!(crate::RTSPEvent::all(), "\"read+write\"");
|
||||
check_serialize!(
|
||||
crate::RTSPLowerTrans::all(),
|
||||
"\"udp+udp-mcast+tcp+http+tls\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::RTSPMethod::all(),
|
||||
concat!(
|
||||
"\"describe+announce+get-parameter+options+pause+play+record",
|
||||
"+redirect+setup+set-parameter+teardown+get+post\""
|
||||
)
|
||||
);
|
||||
check_serialize!(crate::RTSPProfile::all(), "\"avp+savp+avpf+savpf\"");
|
||||
check_serialize!(crate::RTSPTransMode::all(), "\"rtp+rdt\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_deserialize!(crate::RTSPEvent, crate::RTSPEvent::all(), "\"read+write\"");
|
||||
check_deserialize!(
|
||||
crate::RTSPLowerTrans,
|
||||
crate::RTSPLowerTrans::all(),
|
||||
"\"udp+udp-mcast+tcp+http+tls\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::RTSPMethod,
|
||||
crate::RTSPMethod::all(),
|
||||
concat!(
|
||||
"\"describe+announce+get-parameter+options+pause+play+record",
|
||||
"+redirect+setup+set-parameter+teardown+get+post\""
|
||||
)
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::RTSPProfile,
|
||||
crate::RTSPProfile::all(),
|
||||
"\"avp+savp+avpf+savpf\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::RTSPTransMode,
|
||||
crate::RTSPTransMode::all(),
|
||||
"\"rtp+rdt\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
gst::init().unwrap();
|
||||
|
||||
check_roundtrip!(crate::RTSPEvent, crate::RTSPEvent::all());
|
||||
check_roundtrip!(crate::RTSPLowerTrans, crate::RTSPLowerTrans::all());
|
||||
check_roundtrip!(crate::RTSPMethod, crate::RTSPMethod::all());
|
||||
check_roundtrip!(crate::RTSPProfile, crate::RTSPProfile::all());
|
||||
check_roundtrip!(crate::RTSPTransMode, crate::RTSPTransMode::all());
|
||||
}
|
||||
}
|
|
@ -29,6 +29,9 @@ macro_rules! skip_assert_initialized {
|
|||
mod auto;
|
||||
pub use crate::auto::*;
|
||||
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod flag_serde;
|
||||
|
||||
// Re-export all the traits in a prelude module, so that applications
|
||||
// can always "use gst_rtsp::prelude::*" without getting conflicts
|
||||
pub mod prelude {
|
||||
|
|
|
@ -36,8 +36,8 @@ v1_16 = ["gst/v1_16", "gst-base/v1_16", "ffi/v1_16"]
|
|||
v1_18 = ["gst/v1_18", "gst-base/v1_18", "ffi/v1_18", "v1_16"]
|
||||
v1_20 = ["gst/v1_20", "gst-base/v1_20", "ffi/v1_20", "v1_18"]
|
||||
v1_22 = ["gst/v1_22", "gst-base/v1_22", "ffi/v1_22", "v1_20"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "gst-base/dox"]
|
||||
ser_de = ["serde"]
|
||||
dox = ["v1_22", "ffi/dox", "glib/dox", "gst/dox", "gst-base/dox", "ser_de"]
|
||||
ser_de = ["serde", "gst/ser_de"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["dox"]
|
||||
|
|
231
gstreamer-video/src/flag_serde.rs
Normal file
231
gstreamer-video/src/flag_serde.rs
Normal file
|
@ -0,0 +1,231 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, ToGlibPtr};
|
||||
use glib::{FlagsClass, StaticType, ToValue};
|
||||
use gst::bitflags_serde_impl;
|
||||
|
||||
bitflags_serde_impl!(crate::NavigationModifierType, "v1_22");
|
||||
bitflags_serde_impl!(crate::VideoBufferFlags);
|
||||
bitflags_serde_impl!(crate::VideoChromaSite);
|
||||
bitflags_serde_impl!(crate::VideoCodecFrameFlags, "v1_20");
|
||||
bitflags_serde_impl!(crate::VideoDecoderRequestSyncPointFlags, "v1_20");
|
||||
bitflags_serde_impl!(crate::VideoFlags);
|
||||
bitflags_serde_impl!(crate::VideoFormatFlags);
|
||||
bitflags_serde_impl!(crate::VideoFrameFlags);
|
||||
bitflags_serde_impl!(crate::VideoMultiviewFlags);
|
||||
bitflags_serde_impl!(crate::VideoOverlayFormatFlags, "v1_16");
|
||||
bitflags_serde_impl!(crate::VideoPackFlags);
|
||||
bitflags_serde_impl!(crate::VideoTimeCodeFlags, "v1_18");
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! check_serialize {
|
||||
($flags:expr, $expected:expr) => {
|
||||
let actual = serde_json::to_string(&$flags).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_deserialize {
|
||||
($ty:ty, $expected:expr, $json:expr) => {
|
||||
let actual: $ty = serde_json::from_str(&$json).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_roundtrip {
|
||||
($ty:ty, $flags:expr) => {
|
||||
let json = serde_json::to_string(&$flags).unwrap();
|
||||
let deserialized: $ty = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, $flags);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
check_serialize!(
|
||||
crate::NavigationModifierType::all(),
|
||||
concat!(
|
||||
"\"shift-mask+lock-mask+control-mask+alt-mask+button1-mask",
|
||||
"+button2-mask+button3-mask+button4-mask+button5-mask",
|
||||
"+super-mask+hyper-mask+meta-mask\""
|
||||
)
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_serialize!(
|
||||
crate::VideoBufferFlags::all(),
|
||||
"\"interlaced+tff+rff+onefield+multiple-view+first-in-bundle+marker\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::VideoChromaSite::all(),
|
||||
"\"none+h-cosited+v-cosited+alt-line\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(
|
||||
crate::VideoCodecFrameFlags::all(),
|
||||
"\"decode-only+sync-point+force-keyframe+force-keyframe-headers+corrupted\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(
|
||||
crate::VideoDecoderRequestSyncPointFlags::all(),
|
||||
"\"discard-input+corrupt-output\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::VideoFlags::all(),
|
||||
"\"variable-fps+premultiplied-alpha\""
|
||||
);
|
||||
#[cfg(feature = "v1_22")]
|
||||
check_serialize!(
|
||||
crate::VideoFormatFlags::all(),
|
||||
"\"yuv+rgb+gray+alpha+le+palette+complex+unpack+tiled+subtiles\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::VideoFrameFlags::all(),
|
||||
"\"interlaced+tff+rff+onefield+multiple-view+first-in-bundle\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::VideoMultiviewFlags::all(),
|
||||
concat!(
|
||||
"\"right-view-first+left-flipped+left-flopped+right-flipped",
|
||||
"+right-flopped+half-aspect+mixed-mono\""
|
||||
)
|
||||
);
|
||||
#[cfg(feature = "v1_16")]
|
||||
check_serialize!(
|
||||
crate::VideoOverlayFormatFlags::all(),
|
||||
"\"premultiplied-alpha+global-alpha\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::VideoPackFlags::all(),
|
||||
"\"truncate-range+interlaced\""
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_serialize!(
|
||||
crate::VideoTimeCodeFlags::all(),
|
||||
"\"drop-frame+interlaced\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
gst::init().unwrap();
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
check_deserialize!(
|
||||
crate::NavigationModifierType,
|
||||
crate::NavigationModifierType::all(),
|
||||
concat!(
|
||||
"\"shift-mask+lock-mask+control-mask+alt-mask+button1-mask",
|
||||
"+button2-mask+button3-mask+button4-mask+button5-mask",
|
||||
"+super-mask+hyper-mask+meta-mask\""
|
||||
)
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_deserialize!(
|
||||
crate::VideoBufferFlags,
|
||||
crate::VideoBufferFlags::all(),
|
||||
"\"interlaced+tff+rff+onefield+multiple-view+first-in-bundle+marker\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::VideoChromaSite,
|
||||
crate::VideoChromaSite::all(),
|
||||
"\"none+h-cosited+v-cosited+alt-line\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(
|
||||
crate::VideoCodecFrameFlags,
|
||||
crate::VideoCodecFrameFlags::all(),
|
||||
"\"decode-only+sync-point+force-keyframe+force-keyframe-headers+corrupted\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(
|
||||
crate::VideoDecoderRequestSyncPointFlags,
|
||||
crate::VideoDecoderRequestSyncPointFlags::all(),
|
||||
"\"discard-input+corrupt-output\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::VideoFlags,
|
||||
crate::VideoFlags::all(),
|
||||
"\"variable-fps+premultiplied-alpha\""
|
||||
);
|
||||
#[cfg(feature = "v1_22")]
|
||||
check_deserialize!(
|
||||
crate::VideoFormatFlags,
|
||||
crate::VideoFormatFlags::all(),
|
||||
"\"yuv+rgb+gray+alpha+le+palette+complex+unpack+tiled+subtiles\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::VideoFrameFlags,
|
||||
crate::VideoFrameFlags::all(),
|
||||
"\"interlaced+tff+rff+onefield+multiple-view+first-in-bundle\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::VideoMultiviewFlags,
|
||||
crate::VideoMultiviewFlags::all(),
|
||||
concat!(
|
||||
"\"right-view-first+left-flipped+left-flopped+right-flipped",
|
||||
"+right-flopped+half-aspect+mixed-mono\""
|
||||
)
|
||||
);
|
||||
#[cfg(feature = "v1_16")]
|
||||
check_deserialize!(
|
||||
crate::VideoOverlayFormatFlags,
|
||||
crate::VideoOverlayFormatFlags::all(),
|
||||
"\"premultiplied-alpha+global-alpha\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::VideoPackFlags,
|
||||
crate::VideoPackFlags::all(),
|
||||
"\"truncate-range+interlaced\""
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_deserialize!(
|
||||
crate::VideoTimeCodeFlags,
|
||||
crate::VideoTimeCodeFlags::all(),
|
||||
"\"drop-frame+interlaced\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
gst::init().unwrap();
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
check_roundtrip!(
|
||||
crate::NavigationModifierType,
|
||||
crate::NavigationModifierType::all()
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_roundtrip!(crate::VideoBufferFlags, crate::VideoBufferFlags::all());
|
||||
check_roundtrip!(crate::VideoChromaSite, crate::VideoChromaSite::all());
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(
|
||||
crate::VideoCodecFrameFlags,
|
||||
crate::VideoCodecFrameFlags::all()
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(
|
||||
crate::VideoDecoderRequestSyncPointFlags,
|
||||
crate::VideoDecoderRequestSyncPointFlags::all()
|
||||
);
|
||||
check_roundtrip!(crate::VideoFlags, crate::VideoFlags::all());
|
||||
#[cfg(feature = "v1_22")]
|
||||
check_roundtrip!(crate::VideoFormatFlags, crate::VideoFormatFlags::all());
|
||||
check_roundtrip!(crate::VideoFrameFlags, crate::VideoFrameFlags::all());
|
||||
check_roundtrip!(
|
||||
crate::VideoMultiviewFlags,
|
||||
crate::VideoMultiviewFlags::all()
|
||||
);
|
||||
#[cfg(feature = "v1_16")]
|
||||
check_roundtrip!(
|
||||
crate::VideoOverlayFormatFlags,
|
||||
crate::VideoOverlayFormatFlags::all()
|
||||
);
|
||||
check_roundtrip!(crate::VideoPackFlags, crate::VideoPackFlags::all());
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_roundtrip!(crate::VideoTimeCodeFlags, crate::VideoTimeCodeFlags::all());
|
||||
}
|
||||
}
|
|
@ -32,6 +32,9 @@ macro_rules! skip_assert_initialized {
|
|||
mod auto;
|
||||
pub use crate::auto::*;
|
||||
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod flag_serde;
|
||||
|
||||
mod navigation;
|
||||
|
||||
mod caps_features;
|
||||
|
|
|
@ -9,10 +9,6 @@ use std::mem;
|
|||
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))]
|
||||
use crate::NavigationModifierType;
|
||||
|
||||
#[cfg(all(feature = "ser_de", any(feature = "v1_22", feature = "dox")))]
|
||||
#[cfg_attr(feature = "dox", feature = "ser_de", doc(cfg(feature = "v1_22")))]
|
||||
use glib::{FlagsClass, StaticType};
|
||||
|
||||
// FIXME: Copy from gstreamer/src/event.rs
|
||||
macro_rules! event_builder_generic_impl {
|
||||
($new_fn:expr) => {
|
||||
|
@ -1267,81 +1263,6 @@ impl NavigationEvent {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "ser_de", any(feature = "v1_22", feature = "dox")))]
|
||||
#[cfg_attr(feature = "dox", feature = "ser_de", doc(cfg(feature = "v1_22")))]
|
||||
impl serde::Serialize for NavigationModifierType {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let class = FlagsClass::new(NavigationModifierType::static_type()).unwrap();
|
||||
|
||||
let mut handled = NavigationModifierType::empty();
|
||||
let mut res = "".to_owned();
|
||||
for v in class.values() {
|
||||
let value = v.value();
|
||||
if value.count_ones() != 1 || value & handled.bits() != 0 {
|
||||
continue;
|
||||
} else if (value & self.bits()) == value {
|
||||
if !res.is_empty() {
|
||||
res.push('+');
|
||||
}
|
||||
res.push_str(v.nick());
|
||||
handled.insert(NavigationModifierType::from_bits(value).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
serializer.serialize_str(&res)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "ser_de", any(feature = "v1_22", feature = "dox")))]
|
||||
#[cfg_attr(feature = "dox", feature = "ser_de", doc(cfg(feature = "v1_22")))]
|
||||
struct NavigationModifierTypeVisitor;
|
||||
|
||||
#[cfg(all(feature = "ser_de", any(feature = "v1_22", feature = "dox")))]
|
||||
#[cfg_attr(feature = "dox", feature = "ser_de", doc(cfg(feature = "v1_22")))]
|
||||
impl<'de> serde::de::Visitor<'de> for NavigationModifierTypeVisitor {
|
||||
type Value = NavigationModifierType;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("one or more mask names separated by plus signs, or the empty string")
|
||||
}
|
||||
|
||||
fn visit_str<E: serde::de::Error>(self, value: &str) -> std::result::Result<Self::Value, E> {
|
||||
if value.is_empty() {
|
||||
return Ok(NavigationModifierType::empty());
|
||||
}
|
||||
|
||||
let mut gvalue = glib::Value::from_type(NavigationModifierType::static_type());
|
||||
let tokens = value.split('+');
|
||||
let class = FlagsClass::new(NavigationModifierType::static_type()).unwrap();
|
||||
|
||||
for token in tokens {
|
||||
gvalue = class
|
||||
.set_by_nick(gvalue, token)
|
||||
.map_err(|_| serde::de::Error::custom(&format!("Invalid value: {}", token)))?;
|
||||
}
|
||||
|
||||
Ok(unsafe {
|
||||
from_glib(glib::gobject_ffi::g_value_get_flags(
|
||||
gvalue.to_glib_none().0,
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "ser_de", any(feature = "v1_22", feature = "dox")))]
|
||||
#[cfg_attr(feature = "dox", feature = "ser_de", doc(cfg(feature = "v1_22")))]
|
||||
impl<'de> serde::Deserialize<'de> for NavigationModifierType {
|
||||
fn deserialize<D: serde::de::Deserializer<'de>>(
|
||||
deserializer: D,
|
||||
) -> std::result::Result<Self, D::Error> {
|
||||
skip_assert_initialized!();
|
||||
deserializer.deserialize_str(NavigationModifierTypeVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
|
|
|
@ -104,9 +104,7 @@ mod tests {
|
|||
" duration: Some(5),",
|
||||
" offset: 3,",
|
||||
" offset_end: 4,",
|
||||
" flags: (",
|
||||
" bits: 80,",
|
||||
" ),",
|
||||
" flags: \"live+discont\",",
|
||||
" buffer: \"AQIDBA==\",",
|
||||
")"
|
||||
)
|
||||
|
@ -123,7 +121,7 @@ mod tests {
|
|||
"\"duration\":5,",
|
||||
"\"offset\":3,",
|
||||
"\"offset_end\":4,",
|
||||
"\"flags\":{\"bits\":80},",
|
||||
"\"flags\":\"live+discont\",",
|
||||
"\"buffer\":[1,2,3,4]",
|
||||
"}"
|
||||
)
|
||||
|
@ -143,9 +141,7 @@ mod tests {
|
|||
duration: Some(5),
|
||||
offset: 3,
|
||||
offset_end: 4,
|
||||
flags: (
|
||||
bits: 80,
|
||||
),
|
||||
flags: "live+discont",
|
||||
buffer: "AQIDBA==",
|
||||
)
|
||||
"#;
|
||||
|
@ -168,7 +164,7 @@ mod tests {
|
|||
"duration":5,
|
||||
"offset":3,
|
||||
"offset_end":4,
|
||||
"flags":{"bits":80},
|
||||
"flags":"live+discont",
|
||||
"buffer":[1,2,3,4]
|
||||
}
|
||||
"#;
|
||||
|
|
|
@ -107,9 +107,7 @@ mod tests {
|
|||
" duration: Some(4),",
|
||||
" offset: 0,",
|
||||
" offset_end: 4,",
|
||||
" flags: (",
|
||||
" bits: 0,",
|
||||
" ),",
|
||||
" flags: \"\",",
|
||||
" buffer: \"AQIDBA==\",",
|
||||
" ),",
|
||||
" (",
|
||||
|
@ -118,9 +116,7 @@ mod tests {
|
|||
" duration: Some(2),",
|
||||
" offset: 4,",
|
||||
" offset_end: 6,",
|
||||
" flags: (",
|
||||
" bits: 0,",
|
||||
" ),",
|
||||
" flags: \"\",",
|
||||
" buffer: \"BQY=\",",
|
||||
" ),",
|
||||
"]"
|
||||
|
@ -142,9 +138,7 @@ mod tests {
|
|||
duration: Some(4),
|
||||
offset: 0,
|
||||
offset_end: 4,
|
||||
flags: (
|
||||
bits: 0,
|
||||
),
|
||||
flags: "",
|
||||
buffer: "AQIDBA==",
|
||||
),
|
||||
(
|
||||
|
@ -153,9 +147,7 @@ mod tests {
|
|||
duration: Some(2),
|
||||
offset: 4,
|
||||
offset_end: 6,
|
||||
flags: (
|
||||
bits: 0,
|
||||
),
|
||||
flags: "",
|
||||
buffer: "BQY=",
|
||||
),
|
||||
]
|
||||
|
|
533
gstreamer/src/flag_serde.rs
Normal file
533
gstreamer/src/flag_serde.rs
Normal file
|
@ -0,0 +1,533 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, ToGlibPtr};
|
||||
use glib::{FlagsClass, StaticType, ToValue};
|
||||
|
||||
bitflags_serde_impl!(crate::BinFlags);
|
||||
bitflags_serde_impl!(crate::BufferCopyFlags);
|
||||
bitflags_serde_impl!(crate::BufferFlags);
|
||||
bitflags_serde_impl!(crate::BufferPoolAcquireFlags);
|
||||
bitflags_serde_impl!(crate::ClockFlags);
|
||||
|
||||
impl serde::Serialize for crate::DebugColorFlags {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&format!(
|
||||
"{}+{}{}{}",
|
||||
match *self & Self::from_bits(0b111).expect("Failed to create value from fg-color mask")
|
||||
{
|
||||
Self::FG_BLACK => "fg-black",
|
||||
Self::FG_RED => "fg-red",
|
||||
Self::FG_GREEN => "fg-green",
|
||||
Self::FG_YELLOW => "fg-yellow",
|
||||
Self::FG_BLUE => "fg-blue",
|
||||
Self::FG_MAGENTA => "fg-magenta",
|
||||
Self::FG_CYAN => "fg-cyan",
|
||||
Self::FG_WHITE => "fg-white",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
match *self
|
||||
& Self::from_bits(0b111_0000).expect("Failed to create value from bg-color mask")
|
||||
{
|
||||
Self::BG_BLACK => "bg-black",
|
||||
Self::BG_RED => "bg-red",
|
||||
Self::BG_GREEN => "bg-green",
|
||||
Self::BG_YELLOW => "bg-yellow",
|
||||
Self::BG_BLUE => "bg-blue",
|
||||
Self::BG_MAGENTA => "bg-magenta",
|
||||
Self::BG_CYAN => "bg-cyan",
|
||||
Self::BG_WHITE => "bg-white",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
if self.contains(Self::BOLD) {
|
||||
"+bold"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
if self.contains(Self::UNDERLINE) {
|
||||
"+underline"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
bitflags_deserialize_impl!(crate::DebugColorFlags);
|
||||
bitflags_serialize_impl!(crate::DebugGraphDetails, by_ones_decreasing);
|
||||
bitflags_deserialize_impl!(crate::DebugGraphDetails);
|
||||
bitflags_serde_impl!(crate::ElementFlags);
|
||||
bitflags_serde_impl!(crate::EventTypeFlags);
|
||||
bitflags_serde_impl!(crate::GapFlags, "v1_20");
|
||||
bitflags_serde_impl!(crate::MemoryFlags);
|
||||
bitflags_serde_impl!(crate::MetaFlags);
|
||||
bitflags_serde_impl!(crate::ObjectFlags);
|
||||
bitflags_serde_impl!(crate::PadFlags);
|
||||
bitflags_serde_impl!(crate::PadLinkCheck);
|
||||
bitflags_serde_impl!(crate::PadProbeType);
|
||||
bitflags_serde_impl!(crate::ParseFlags);
|
||||
bitflags_serde_impl!(crate::PluginAPIFlags, "v1_18");
|
||||
bitflags_serde_impl!(crate::PluginDependencyFlags);
|
||||
bitflags_serde_impl!(crate::PluginFlags);
|
||||
bitflags_serde_impl!(crate::SchedulingFlags);
|
||||
bitflags_serde_impl!(crate::SeekFlags);
|
||||
bitflags_serde_impl!(crate::SegmentFlags);
|
||||
bitflags_serde_impl!(crate::SerializeFlags, "v1_20");
|
||||
bitflags_serde_impl!(crate::StackTraceFlags);
|
||||
bitflags_serde_impl!(crate::StreamFlags);
|
||||
bitflags_serde_impl!(crate::StreamType);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! check_serialize {
|
||||
($flags:expr, $expected:expr) => {
|
||||
let actual = serde_json::to_string(&$flags).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_deserialize {
|
||||
($ty:ty, $expected:expr, $json:expr) => {
|
||||
let actual: $ty = serde_json::from_str(&$json).unwrap();
|
||||
assert_eq!(actual, $expected);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! check_roundtrip {
|
||||
($ty:ty, $flags:expr) => {
|
||||
let json = serde_json::to_string(&$flags).unwrap();
|
||||
let deserialized: $ty = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized, $flags);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
crate::init().unwrap();
|
||||
|
||||
check_serialize!(crate::BinFlags::empty(), "\"\"");
|
||||
check_serialize!(crate::BinFlags::all(), "\"no-resync+streams-aware\"");
|
||||
check_serialize!(
|
||||
crate::BufferCopyFlags::all(),
|
||||
"\"flags+timestamps+meta+memory+merge+deep\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::BufferFlags::all(),
|
||||
concat!(
|
||||
"\"live+decode-only+discont+resync+corrupted+marker+header+gap",
|
||||
"+droppable+delta-unit+tag-memory+sync-after+non-droppable\""
|
||||
)
|
||||
);
|
||||
check_serialize!(
|
||||
crate::BufferPoolAcquireFlags::all(),
|
||||
"\"key-unit+dontwait+discont\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::ClockFlags::all(),
|
||||
concat!(
|
||||
"\"can-do-single-sync+can-do-single-async",
|
||||
"+can-do-periodic-sync+can-do-periodic-async",
|
||||
"+can-set-resolution+can-set-master+needs-startup-sync\""
|
||||
)
|
||||
);
|
||||
|
||||
check_serialize!(
|
||||
crate::DebugColorFlags::all(),
|
||||
"\"fg-white+bg-white+bold+underline\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::DebugColorFlags::FG_MAGENTA | crate::DebugColorFlags::BOLD,
|
||||
"\"fg-magenta+bg-black+bold\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::DebugColorFlags::FG_RED
|
||||
| crate::DebugColorFlags::FG_BLUE
|
||||
| crate::DebugColorFlags::BG_BLACK,
|
||||
"\"fg-magenta+bg-black\""
|
||||
);
|
||||
|
||||
check_serialize!(crate::DebugGraphDetails::all(), "\"verbose\"");
|
||||
check_serialize!(
|
||||
crate::DebugGraphDetails::MEDIA_TYPE
|
||||
| crate::DebugGraphDetails::CAPS_DETAILS
|
||||
| crate::DebugGraphDetails::NON_DEFAULT_PARAMS
|
||||
| crate::DebugGraphDetails::STATES
|
||||
| crate::DebugGraphDetails::FULL_PARAMS
|
||||
| crate::DebugGraphDetails::ALL,
|
||||
"\"all+full-params\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::DebugGraphDetails::MEDIA_TYPE
|
||||
| crate::DebugGraphDetails::CAPS_DETAILS
|
||||
| crate::DebugGraphDetails::NON_DEFAULT_PARAMS
|
||||
| crate::DebugGraphDetails::STATES
|
||||
| crate::DebugGraphDetails::FULL_PARAMS,
|
||||
"\"all+full-params\""
|
||||
);
|
||||
|
||||
check_serialize!(
|
||||
crate::ElementFlags::all(),
|
||||
"\"locked-state+sink+source+provide-clock+require-clock+indexable\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::EventTypeFlags::all(),
|
||||
"\"upstream+downstream+serialized+sticky+sticky-multi\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(crate::GapFlags::all(), "\"data\"");
|
||||
check_serialize!(
|
||||
crate::MemoryFlags::all(),
|
||||
concat!(
|
||||
"\"readonly+no-share+zero-prefixed+zero-padded",
|
||||
"+physically-contiguous+not-mappable\""
|
||||
)
|
||||
);
|
||||
check_serialize!(crate::MetaFlags::all(), "\"readonly+pooled+locked\"");
|
||||
check_serialize!(crate::ObjectFlags::all(), "\"may-be-leaked\"");
|
||||
check_serialize!(
|
||||
crate::PadFlags::all(),
|
||||
concat!(
|
||||
"\"blocked+flushing+eos+blocking+need-parent+need-reconfigure",
|
||||
"+pending-events+fixed-caps+proxy-caps+proxy-allocation",
|
||||
"+proxy-scheduling+accept-intersect+accept-template\""
|
||||
)
|
||||
);
|
||||
check_serialize!(
|
||||
crate::PadLinkCheck::all(),
|
||||
"\"hierarchy+template-caps+caps+no-reconfigure\""
|
||||
);
|
||||
check_serialize!(
|
||||
crate::PadProbeType::all(),
|
||||
concat!(
|
||||
"\"idle+block+buffer+buffer-list+event-downstream",
|
||||
"+event-upstream+event-flush+query-downstream+query-upstream",
|
||||
"+push+pull\""
|
||||
)
|
||||
);
|
||||
check_serialize!(
|
||||
crate::ParseFlags::all(),
|
||||
"\"fatal-errors+no-single-element-bins+place-in-bin\""
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_serialize!(crate::PluginAPIFlags::all(), "\"members\"");
|
||||
check_serialize!(
|
||||
crate::PluginDependencyFlags::all(),
|
||||
concat!(
|
||||
"\"recurse+paths-are-default-only+file-name-is-suffix",
|
||||
"+file-name-is-prefix+paths-are-relative-to-exe\""
|
||||
)
|
||||
);
|
||||
check_serialize!(crate::PluginFlags::all(), "\"cached+blacklisted\"");
|
||||
check_serialize!(
|
||||
crate::SchedulingFlags::all(),
|
||||
"\"seekable+sequential+bandwidth-limited\""
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_serialize!(
|
||||
crate::SeekFlags::all(),
|
||||
concat!(
|
||||
"\"flush+accurate+key-unit+segment+trickmode+snap-before",
|
||||
"+snap-after+trickmode-key-units+trickmode-no-audio",
|
||||
"+trickmode-forward-predicted+instant-rate-change\""
|
||||
)
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_serialize!(
|
||||
crate::SegmentFlags::all(),
|
||||
concat!(
|
||||
"\"reset+trickmode+segment+trickmode-key-units",
|
||||
"+trickmode-forward-predicted+trickmode-no-audio\""
|
||||
)
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_serialize!(crate::SerializeFlags::all(), "\"backward-compat\"");
|
||||
check_serialize!(crate::StackTraceFlags::all(), "\"full\"");
|
||||
check_serialize!(crate::StreamFlags::all(), "\"sparse+select+unselect\"");
|
||||
check_serialize!(
|
||||
crate::StreamType::all(),
|
||||
"\"unknown+audio+video+container+text\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize() {
|
||||
crate::init().unwrap();
|
||||
|
||||
check_deserialize!(crate::BinFlags, crate::BinFlags::empty(), "\"\"");
|
||||
check_deserialize!(
|
||||
crate::BinFlags,
|
||||
crate::BinFlags::all(),
|
||||
"\"no-resync+streams-aware\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::BufferCopyFlags,
|
||||
crate::BufferCopyFlags::all(),
|
||||
"\"flags+timestamps+meta+memory+merge+deep\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::BufferFlags,
|
||||
crate::BufferFlags::all(),
|
||||
concat!(
|
||||
"\"live+decode-only+discont+resync+corrupted+marker+header+gap",
|
||||
"+droppable+delta-unit+tag-memory+sync-after+non-droppable\""
|
||||
)
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::BufferPoolAcquireFlags,
|
||||
crate::BufferPoolAcquireFlags::all(),
|
||||
"\"key-unit+dontwait+discont\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::ClockFlags,
|
||||
crate::ClockFlags::all(),
|
||||
concat!(
|
||||
"\"can-do-single-sync+can-do-single-async",
|
||||
"+can-do-periodic-sync+can-do-periodic-async",
|
||||
"+can-set-resolution+can-set-master+needs-startup-sync\""
|
||||
)
|
||||
);
|
||||
|
||||
check_deserialize!(
|
||||
crate::DebugColorFlags,
|
||||
crate::DebugColorFlags::all(),
|
||||
"\"fg-white+bg-white+bold+underline\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::DebugColorFlags,
|
||||
crate::DebugColorFlags::FG_MAGENTA | crate::DebugColorFlags::BOLD,
|
||||
"\"fg-magenta+bg-black+bold\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::DebugColorFlags,
|
||||
crate::DebugColorFlags::FG_RED
|
||||
| crate::DebugColorFlags::FG_BLUE
|
||||
| crate::DebugColorFlags::BG_BLACK,
|
||||
"\"fg-magenta+bg-black\""
|
||||
);
|
||||
|
||||
check_deserialize!(
|
||||
crate::DebugGraphDetails,
|
||||
crate::DebugGraphDetails::all(),
|
||||
"\"verbose\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::DebugGraphDetails,
|
||||
crate::DebugGraphDetails::MEDIA_TYPE
|
||||
| crate::DebugGraphDetails::CAPS_DETAILS
|
||||
| crate::DebugGraphDetails::NON_DEFAULT_PARAMS
|
||||
| crate::DebugGraphDetails::STATES
|
||||
| crate::DebugGraphDetails::FULL_PARAMS
|
||||
| crate::DebugGraphDetails::ALL,
|
||||
"\"all+full-params\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::DebugGraphDetails,
|
||||
crate::DebugGraphDetails::MEDIA_TYPE
|
||||
| crate::DebugGraphDetails::CAPS_DETAILS
|
||||
| crate::DebugGraphDetails::NON_DEFAULT_PARAMS
|
||||
| crate::DebugGraphDetails::STATES
|
||||
| crate::DebugGraphDetails::FULL_PARAMS,
|
||||
"\"all+full-params\""
|
||||
);
|
||||
|
||||
check_deserialize!(
|
||||
crate::ElementFlags,
|
||||
crate::ElementFlags::all(),
|
||||
"\"locked-state+sink+source+provide-clock+require-clock+indexable\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::EventTypeFlags,
|
||||
crate::EventTypeFlags::all(),
|
||||
"\"upstream+downstream+serialized+sticky+sticky-multi\""
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(crate::GapFlags, crate::GapFlags::all(), "\"data\"");
|
||||
check_deserialize!(
|
||||
crate::MemoryFlags,
|
||||
crate::MemoryFlags::all(),
|
||||
concat!(
|
||||
"\"readonly+no-share+zero-prefixed+zero-padded",
|
||||
"+physically-contiguous+not-mappable\""
|
||||
)
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::MetaFlags,
|
||||
crate::MetaFlags::all(),
|
||||
"\"readonly+pooled+locked\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::ObjectFlags,
|
||||
crate::ObjectFlags::all(),
|
||||
"\"may-be-leaked\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::PadFlags,
|
||||
crate::PadFlags::all(),
|
||||
concat!(
|
||||
"\"blocked+flushing+eos+blocking+need-parent+need-reconfigure",
|
||||
"+pending-events+fixed-caps+proxy-caps+proxy-allocation",
|
||||
"+proxy-scheduling+accept-intersect+accept-template\""
|
||||
)
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::PadLinkCheck,
|
||||
crate::PadLinkCheck::all(),
|
||||
"\"hierarchy+template-caps+caps+no-reconfigure\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::PadProbeType,
|
||||
crate::PadProbeType::all(),
|
||||
concat!(
|
||||
"\"idle+block+buffer+buffer-list+event-downstream",
|
||||
"+event-upstream+event-flush+query-downstream+query-upstream",
|
||||
"+push+pull\""
|
||||
)
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::ParseFlags,
|
||||
crate::ParseFlags::all(),
|
||||
"\"fatal-errors+no-single-element-bins+place-in-bin\""
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_deserialize!(
|
||||
crate::PluginAPIFlags,
|
||||
crate::PluginAPIFlags::all(),
|
||||
"\"members\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::PluginDependencyFlags,
|
||||
crate::PluginDependencyFlags::all(),
|
||||
concat!(
|
||||
"\"recurse+paths-are-default-only+file-name-is-suffix",
|
||||
"+file-name-is-prefix+paths-are-relative-to-exe\""
|
||||
)
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::PluginFlags,
|
||||
crate::PluginFlags::all(),
|
||||
"\"cached+blacklisted\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::SchedulingFlags,
|
||||
crate::SchedulingFlags::all(),
|
||||
"\"seekable+sequential+bandwidth-limited\""
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_deserialize!(
|
||||
crate::SeekFlags,
|
||||
crate::SeekFlags::all(),
|
||||
concat!(
|
||||
"\"flush+accurate+key-unit+segment+trickmode+snap-before",
|
||||
"+snap-after+trickmode-key-units+trickmode-no-audio",
|
||||
"+trickmode-forward-predicted+instant-rate-change\""
|
||||
)
|
||||
);
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_deserialize!(
|
||||
crate::SegmentFlags,
|
||||
crate::SegmentFlags::all(),
|
||||
concat!(
|
||||
"\"reset+trickmode+segment+trickmode-key-units",
|
||||
"+trickmode-forward-predicted+trickmode-no-audio\""
|
||||
)
|
||||
);
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_deserialize!(
|
||||
crate::SerializeFlags,
|
||||
crate::SerializeFlags::all(),
|
||||
"\"backward-compat\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::StackTraceFlags,
|
||||
crate::StackTraceFlags::all(),
|
||||
"\"full\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::StreamFlags,
|
||||
crate::StreamFlags::all(),
|
||||
"\"sparse+select+unselect\""
|
||||
);
|
||||
check_deserialize!(
|
||||
crate::StreamType,
|
||||
crate::StreamType::all(),
|
||||
"\"unknown+audio+video+container+text\""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
crate::init().unwrap();
|
||||
|
||||
check_roundtrip!(crate::BinFlags, crate::BinFlags::empty());
|
||||
check_roundtrip!(crate::BinFlags, crate::BinFlags::all());
|
||||
check_roundtrip!(crate::BufferCopyFlags, crate::BufferCopyFlags::all());
|
||||
check_roundtrip!(crate::BufferFlags, crate::BufferFlags::all());
|
||||
check_roundtrip!(
|
||||
crate::BufferPoolAcquireFlags,
|
||||
crate::BufferPoolAcquireFlags::all()
|
||||
);
|
||||
check_roundtrip!(crate::ClockFlags, crate::ClockFlags::all());
|
||||
|
||||
check_roundtrip!(crate::DebugColorFlags, crate::DebugColorFlags::all());
|
||||
check_roundtrip!(
|
||||
crate::DebugColorFlags,
|
||||
crate::DebugColorFlags::FG_MAGENTA | crate::DebugColorFlags::BOLD
|
||||
);
|
||||
check_roundtrip!(
|
||||
crate::DebugColorFlags,
|
||||
crate::DebugColorFlags::FG_RED
|
||||
| crate::DebugColorFlags::FG_BLUE
|
||||
| crate::DebugColorFlags::BG_BLACK
|
||||
);
|
||||
|
||||
check_roundtrip!(crate::DebugGraphDetails, crate::DebugGraphDetails::all());
|
||||
check_roundtrip!(
|
||||
crate::DebugGraphDetails,
|
||||
crate::DebugGraphDetails::MEDIA_TYPE
|
||||
| crate::DebugGraphDetails::CAPS_DETAILS
|
||||
| crate::DebugGraphDetails::NON_DEFAULT_PARAMS
|
||||
| crate::DebugGraphDetails::STATES
|
||||
| crate::DebugGraphDetails::FULL_PARAMS
|
||||
| crate::DebugGraphDetails::ALL
|
||||
);
|
||||
check_roundtrip!(
|
||||
crate::DebugGraphDetails,
|
||||
crate::DebugGraphDetails::MEDIA_TYPE
|
||||
| crate::DebugGraphDetails::CAPS_DETAILS
|
||||
| crate::DebugGraphDetails::NON_DEFAULT_PARAMS
|
||||
| crate::DebugGraphDetails::STATES
|
||||
| crate::DebugGraphDetails::FULL_PARAMS
|
||||
);
|
||||
|
||||
check_roundtrip!(crate::ElementFlags, crate::ElementFlags::all());
|
||||
check_roundtrip!(crate::EventTypeFlags, crate::EventTypeFlags::all());
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(crate::GapFlags, crate::GapFlags::all());
|
||||
check_roundtrip!(crate::MemoryFlags, crate::MemoryFlags::all());
|
||||
check_roundtrip!(crate::MetaFlags, crate::MetaFlags::all());
|
||||
check_roundtrip!(crate::ObjectFlags, crate::ObjectFlags::all());
|
||||
check_roundtrip!(crate::PadFlags, crate::PadFlags::all());
|
||||
check_roundtrip!(crate::PadLinkCheck, crate::PadLinkCheck::all());
|
||||
check_roundtrip!(crate::PadProbeType, crate::PadProbeType::all());
|
||||
check_roundtrip!(crate::ParseFlags, crate::ParseFlags::all());
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_roundtrip!(crate::PluginAPIFlags, crate::PluginAPIFlags::all());
|
||||
check_roundtrip!(
|
||||
crate::PluginDependencyFlags,
|
||||
crate::PluginDependencyFlags::all()
|
||||
);
|
||||
check_roundtrip!(crate::PluginFlags, crate::PluginFlags::all());
|
||||
check_roundtrip!(crate::SchedulingFlags, crate::SchedulingFlags::all());
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_roundtrip!(crate::SeekFlags, crate::SeekFlags::all());
|
||||
#[cfg(feature = "v1_18")]
|
||||
check_roundtrip!(crate::SegmentFlags, crate::SegmentFlags::all());
|
||||
#[cfg(feature = "v1_20")]
|
||||
check_roundtrip!(crate::SerializeFlags, crate::SerializeFlags::all());
|
||||
check_roundtrip!(crate::StackTraceFlags, crate::StackTraceFlags::all());
|
||||
check_roundtrip!(crate::StreamFlags, crate::StreamFlags::all());
|
||||
check_roundtrip!(crate::StreamType, crate::StreamType::all());
|
||||
}
|
||||
}
|
|
@ -40,6 +40,12 @@ pub use crate::auto::*;
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[macro_use]
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod serde_macros;
|
||||
#[cfg(feature = "ser_de")]
|
||||
pub use crate::serde_macros::*;
|
||||
|
||||
#[macro_use]
|
||||
mod log;
|
||||
pub use crate::log::*;
|
||||
|
@ -62,6 +68,9 @@ pub use crate::value::{
|
|||
#[macro_use]
|
||||
mod value_serde;
|
||||
|
||||
#[cfg(feature = "ser_de")]
|
||||
mod flag_serde;
|
||||
|
||||
pub mod structure;
|
||||
pub use crate::structure::{Structure, StructureRef};
|
||||
#[cfg(feature = "ser_de")]
|
||||
|
|
|
@ -142,9 +142,7 @@ mod tests {
|
|||
" duration: Some(4),",
|
||||
" offset: 0,",
|
||||
" offset_end: 4,",
|
||||
" flags: (",
|
||||
" bits: 0,",
|
||||
" ),",
|
||||
" flags: \"\",",
|
||||
" buffer: \"AQIDBA==\",",
|
||||
" )),",
|
||||
" buffer_list: None,",
|
||||
|
@ -155,9 +153,7 @@ mod tests {
|
|||
" ]), None),",
|
||||
" ])),",
|
||||
" segment: Some((",
|
||||
" flags: (",
|
||||
" bits: 9,",
|
||||
" ),",
|
||||
" flags: \"reset+segment\",",
|
||||
" rate: 1,",
|
||||
" applied_rate: 0.9,",
|
||||
" format: Time,",
|
||||
|
@ -202,17 +198,13 @@ mod tests {
|
|||
" duration: Some(4),",
|
||||
" offset: 0,",
|
||||
" offset_end: 4,",
|
||||
" flags: (",
|
||||
" bits: 0,",
|
||||
" ),",
|
||||
" flags: \"\",",
|
||||
" buffer: \"AQIDBA==\",",
|
||||
" )),",
|
||||
" buffer_list: None,",
|
||||
" caps: None,",
|
||||
" segment: Some((",
|
||||
" flags: (",
|
||||
" bits: 0,",
|
||||
" ),",
|
||||
" flags: \"\",",
|
||||
" rate: 1,",
|
||||
" applied_rate: 1,",
|
||||
" format: Time,",
|
||||
|
@ -244,9 +236,7 @@ mod tests {
|
|||
duration: Some(4),
|
||||
offset: 0,
|
||||
offset_end: 4,
|
||||
flags: (
|
||||
bits: 0,
|
||||
),
|
||||
flags: "",
|
||||
buffer: "AQIDBA==",
|
||||
)),
|
||||
buffer_list: None,
|
||||
|
@ -257,9 +247,7 @@ mod tests {
|
|||
]), None),
|
||||
])),
|
||||
segment: Some((
|
||||
flags: (
|
||||
bits: 0,
|
||||
),
|
||||
flags: "",
|
||||
rate: 1,
|
||||
applied_rate: 0.9,
|
||||
format: Time,
|
||||
|
@ -298,9 +286,7 @@ mod tests {
|
|||
duration: Some(4),
|
||||
offset: 0,
|
||||
offset_end: 4,
|
||||
flags: (
|
||||
bits: 0,
|
||||
),
|
||||
flags: "",
|
||||
buffer: "AQIDBA==",
|
||||
),
|
||||
]),
|
||||
|
|
|
@ -138,9 +138,7 @@ mod tests {
|
|||
assert_eq!(
|
||||
Ok(concat!(
|
||||
"(",
|
||||
" flags: (",
|
||||
" bits: 9,",
|
||||
" ),",
|
||||
" flags: \"reset+segment\",",
|
||||
" rate: 1,",
|
||||
" applied_rate: 0.9,",
|
||||
" format: Time,",
|
||||
|
@ -164,9 +162,7 @@ mod tests {
|
|||
|
||||
let segment_ron = r#"
|
||||
(
|
||||
flags: (
|
||||
bits: 9,
|
||||
),
|
||||
flags: "reset+segment",
|
||||
rate: 1,
|
||||
applied_rate: 0.9,
|
||||
format: Time,
|
||||
|
@ -228,9 +224,7 @@ mod tests {
|
|||
|
||||
let segment_ron = r#"
|
||||
(
|
||||
flags: (
|
||||
bits: 9,
|
||||
),
|
||||
flags: "reset+segment",
|
||||
rate: 1,
|
||||
applied_rate: 0.9,
|
||||
format: Time,
|
||||
|
|
145
gstreamer/src/serde_macros.rs
Normal file
145
gstreamer/src/serde_macros.rs
Normal file
|
@ -0,0 +1,145 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! bitflags_serialize_impl {
|
||||
// this implementation serializes only flags using only one bit,
|
||||
// ignoring all other flags
|
||||
($type:ty, single_bit_flags$(, $feature:expr)?) => {
|
||||
$(#[cfg(any(feature = $feature, feature = "dox"))]
|
||||
#[cfg_attr(feature = "dox", doc(cfg(feature = $feature)))])?
|
||||
impl serde::Serialize for $type {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let class = FlagsClass::new(Self::static_type()).unwrap();
|
||||
let this = self.to_value();
|
||||
|
||||
let mut handled = Self::empty().to_value();
|
||||
let mut res = String::new();
|
||||
|
||||
for v in class.values() {
|
||||
let value = v.value();
|
||||
if value.count_ones() == 1 && class.is_set(&this, value) && !class.is_set(&handled, value) {
|
||||
if !res.is_empty() {
|
||||
res.push('+');
|
||||
}
|
||||
res.push_str(v.nick());
|
||||
handled = class.set(handled, value).expect("Failed to set flag");
|
||||
}
|
||||
}
|
||||
|
||||
serializer.serialize_str(&res)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// considers the flags using the most bits first
|
||||
($type:ty, by_ones_decreasing$(, $feature:expr)?) => {
|
||||
$(#[cfg(any(feature = $feature, feature = "dox"))]
|
||||
#[cfg_attr(feature = "dox", doc(cfg(feature = $feature)))])?
|
||||
impl serde::Serialize for $type {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
let mut handled = Self::empty();
|
||||
let mut res = String::new();
|
||||
|
||||
static SORTED_VALUES: Lazy<Vec<(u32, String)>> = Lazy::new(|| {
|
||||
let class = FlagsClass::new(<$type>::static_type()).unwrap();
|
||||
let mut sorted_values: Vec<(u32, String)> =
|
||||
class.values().iter()
|
||||
.map(|f| (f.value(), f.nick().to_owned()))
|
||||
.collect();
|
||||
|
||||
sorted_values.sort_by(|(a, _), (b, _)| {
|
||||
b.count_ones().cmp(&a.count_ones())
|
||||
});
|
||||
|
||||
sorted_values
|
||||
});
|
||||
|
||||
for (bits, nick) in SORTED_VALUES.iter() {
|
||||
// not all values defined in the class are always also defined
|
||||
// in the bitflags struct, see RTPBufferFlags for example
|
||||
if let Some(value) = Self::from_bits(*bits) {
|
||||
if !value.is_empty() && self.contains(value) && !handled.intersects(value) {
|
||||
if !res.is_empty() {
|
||||
res.push('+');
|
||||
}
|
||||
res.push_str(nick);
|
||||
handled.insert(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializer.serialize_str(&res)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! bitflags_deserialize_impl {
|
||||
($type:ty$(, $feature:expr)?) => {
|
||||
$(#[cfg(any(feature = $feature, feature = "dox"))]
|
||||
#[cfg_attr(feature = "dox", doc(cfg(feature = $feature)))])?
|
||||
impl<'de> serde::Deserialize<'de> for $type {
|
||||
fn deserialize<D: serde::de::Deserializer<'de>>(
|
||||
deserializer: D,
|
||||
) -> std::result::Result<Self, D::Error> {
|
||||
skip_assert_initialized!();
|
||||
|
||||
struct FlagsVisitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for FlagsVisitor {
|
||||
type Value = $type;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str(
|
||||
"one or more mask names separated by plus signs, or the empty string",
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_str<E: serde::de::Error>(
|
||||
self,
|
||||
value: &str,
|
||||
) -> std::result::Result<Self::Value, E> {
|
||||
if value.is_empty() {
|
||||
return Ok(Self::Value::empty());
|
||||
}
|
||||
|
||||
let mut gvalue = glib::Value::from_type(Self::Value::static_type());
|
||||
let tokens = value.split('+');
|
||||
let class = FlagsClass::new(Self::Value::static_type()).unwrap();
|
||||
|
||||
for token in tokens {
|
||||
gvalue = class.set_by_nick(gvalue, token).map_err(|_| {
|
||||
serde::de::Error::custom(&format!("Invalid value: {}", token))
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(unsafe {
|
||||
from_glib(glib::gobject_ffi::g_value_get_flags(
|
||||
gvalue.to_glib_none().0,
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(FlagsVisitor)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! bitflags_serde_impl {
|
||||
($type:ty$(, $feature:expr)?) => {
|
||||
$crate::bitflags_serialize_impl!($type, single_bit_flags$(, $feature)?);
|
||||
$crate::bitflags_deserialize_impl!($type$(, $feature)?);
|
||||
};
|
||||
}
|
|
@ -387,17 +387,13 @@ mod tests {
|
|||
r#" duration: None,"#,
|
||||
r#" offset: 0,"#,
|
||||
r#" offset_end: 0,"#,
|
||||
r#" flags: ("#,
|
||||
r#" bits: 0,"#,
|
||||
r#" ),"#,
|
||||
r#" flags: "","#,
|
||||
r#" buffer: "AQIDBA==","#,
|
||||
r#" )),"#,
|
||||
r#" buffer_list: None,"#,
|
||||
r#" caps: None,"#,
|
||||
r#" segment: Some(("#,
|
||||
r#" flags: ("#,
|
||||
r#" bits: 0,"#,
|
||||
r#" ),"#,
|
||||
r#" flags: "","#,
|
||||
r#" rate: 1,"#,
|
||||
r#" applied_rate: 1,"#,
|
||||
r#" format: Time,"#,
|
||||
|
@ -449,9 +445,7 @@ mod tests {
|
|||
duration: None,
|
||||
offset: 0,
|
||||
offset_end: 0,
|
||||
flags: (
|
||||
bits: 0,
|
||||
),
|
||||
flags: "",
|
||||
buffer: "AQIDBA==",
|
||||
)),
|
||||
buffer_list: None,
|
||||
|
@ -500,7 +494,7 @@ mod tests {
|
|||
["replaygain-track-gain", [1.0]],
|
||||
["date",[{"YMD":[2018,5,28]}]],
|
||||
["datetime",[{"YMD":[2018,5,28]}]],
|
||||
["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}]]
|
||||
["image",[{"buffer":{"pts":null,"dts":null,"duration":null,"offset":0,"offset_end":0,"flags":"","buffer":[1,2,3,4]},"buffer_list":null,"caps":null,"segment":null,"info":null}]]
|
||||
]
|
||||
}
|
||||
"#;
|
||||
|
|
Loading…
Reference in a new issue