gstreamer/
serde_macros.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#[macro_export]
4macro_rules! bitflags_serialize_impl {
5    // this implementation serializes only flags using only one bit,
6    // ignoring all other flags
7    ($type:ty, single_bit_flags$(, $feature:expr)?) => {
8        $(#[cfg(any(feature = $feature, docsrs))]
9        #[cfg_attr(docsrs, doc(cfg(feature = $feature)))])?
10        impl serde::Serialize for $type {
11            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
12            where
13                S: serde::Serializer,
14            {
15                let class = FlagsClass::with_type(Self::static_type()).unwrap();
16                let this = self.to_value();
17
18                let mut handled = Self::empty().to_value();
19                let mut res = String::new();
20
21                for v in class.values() {
22                    let value = v.value();
23                    if value.count_ones() == 1 && class.is_set(&this, value) && !class.is_set(&handled, value) {
24                        if !res.is_empty() {
25                            res.push('+');
26                        }
27                        res.push_str(v.nick());
28                        handled = class.set(handled, value).expect("Failed to set flag");
29                    }
30                }
31
32                serializer.serialize_str(&res)
33            }
34        }
35    };
36
37    // considers the flags using the most bits first
38    ($type:ty, by_ones_decreasing$(, $feature:expr)?) => {
39        $(#[cfg(any(feature = $feature, docsrs))]
40        #[cfg_attr(docsrs, doc(cfg(feature = $feature)))])?
41        impl serde::Serialize for $type {
42            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
43            where
44                S: serde::Serializer,
45            {
46                let mut handled = Self::empty();
47                let mut res = String::new();
48
49                static SORTED_VALUES: std::sync::OnceLock<Vec<(u32, String)>> = std::sync::OnceLock::new();
50
51                let sorted_values = SORTED_VALUES.get_or_init(|| {
52                    let class = FlagsClass::with_type(<$type>::static_type()).unwrap();
53                    let mut sorted_values: Vec<(u32, String)> =
54                        class.values().iter()
55                            .map(|f| (f.value(), f.nick().to_owned()))
56                            .collect();
57
58                    sorted_values.sort_by(|(a, _), (b, _)| {
59                        b.count_ones().cmp(&a.count_ones())
60                    });
61
62                    sorted_values
63                });
64
65                for (bits, nick) in sorted_values.iter() {
66                    // not all values defined in the class are always also defined
67                    // in the bitflags struct, see RTPBufferFlags for example
68                    if let Some(value) = Self::from_bits(*bits) {
69                        if !value.is_empty() && self.contains(value) && !handled.intersects(value) {
70                            if !res.is_empty() {
71                                res.push('+');
72                            }
73                            res.push_str(nick);
74                            handled.insert(value);
75                        }
76                    }
77                }
78
79                serializer.serialize_str(&res)
80            }
81        }
82    };
83}
84
85#[macro_export]
86macro_rules! bitflags_deserialize_impl {
87    ($type:ty$(, $feature:expr)?) => {
88        $(#[cfg(any(feature = $feature, docsrs))]
89        #[cfg_attr(docsrs, doc(cfg(feature = $feature)))])?
90        impl<'de> serde::Deserialize<'de> for $type {
91            fn deserialize<D: serde::de::Deserializer<'de>>(
92                deserializer: D,
93            ) -> std::result::Result<Self, D::Error> {
94                skip_assert_initialized!();
95
96                struct FlagsVisitor;
97
98                impl<'de> serde::de::Visitor<'de> for FlagsVisitor {
99                    type Value = $type;
100
101                    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
102                        formatter.write_str(
103                            "one or more mask names separated by plus signs, or the empty string",
104                        )
105                    }
106
107                    fn visit_str<E: serde::de::Error>(
108                        self,
109                        value: &str,
110                    ) -> std::result::Result<Self::Value, E> {
111                        if value.is_empty() {
112                            return Ok(Self::Value::empty());
113                        }
114
115                        let mut gvalue = unsafe { glib::Value::from_type_unchecked(Self::Value::static_type()) };
116                        let tokens = value.split('+');
117                        let class = FlagsClass::with_type(Self::Value::static_type()).unwrap();
118
119                        for token in tokens {
120                            gvalue = class.set_by_nick(gvalue, token).map_err(|_| {
121                                serde::de::Error::custom(&format!("Invalid value: {}", token))
122                            })?;
123                        }
124
125                        Ok(unsafe {
126                            from_glib(glib::gobject_ffi::g_value_get_flags(
127                                gvalue.to_glib_none().0,
128                            ))
129                        })
130                    }
131                }
132
133                deserializer.deserialize_str(FlagsVisitor)
134            }
135        }
136    };
137}
138
139#[macro_export]
140macro_rules! bitflags_serde_impl {
141    ($type:ty$(, $feature:expr)?) => {
142        $crate::bitflags_serialize_impl!($type, single_bit_flags$(, $feature)?);
143        $crate::bitflags_deserialize_impl!($type$(, $feature)?);
144    };
145}