Skip to main content

zvariant/as_value/
serialize.rs

1use serde::ser::{SerializeStruct, Serializer};
2
3use crate::{Signature, Type};
4
5/// A wrapper to serialize `T: Type + serde::Serialize` as a value.
6///
7/// When the type of a value is well-known, you may avoid the cost and complexity of wrapping to a
8/// generic [`enum@crate::Value`] and instead use this wrapper.
9///
10/// ```
11/// # use zvariant::{to_bytes, serialized::Context, as_value::Serialize, LE};
12/// #
13/// # let ctxt = Context::new_dbus(LE, 0);
14/// let _ = to_bytes(ctxt, &Serialize(&[0, 1, 2])).unwrap();
15/// ```
16pub struct Serialize<'a, T: Type + serde::Serialize>(pub &'a T);
17
18impl<T: Type + serde::Serialize> serde::Serialize for Serialize<'_, T> {
19    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
20    where
21        S: Serializer,
22    {
23        // `Value`/`OwnedValue` (and any other type whose signature is already `v`) serialize
24        // themselves as a variant, so wrapping them here would emit a variant-of-variant. Just
25        // delegate to their own `Serialize` impl in that case.
26        if T::SIGNATURE == &Signature::Variant {
27            return self.0.serialize(serializer);
28        }
29
30        // Serializer implementation needs to ensure padding isn't added for Value.
31        let mut structure = serializer.serialize_struct("Variant", 2)?;
32
33        structure.serialize_field("signature", T::SIGNATURE)?;
34        structure.serialize_field("value", self.0)?;
35
36        structure.end()
37    }
38}
39
40impl<T: Type + serde::Serialize> Type for Serialize<'_, T> {
41    const SIGNATURE: &'static crate::Signature = &crate::Signature::Variant;
42}
43
44/// Serialize a value as a [`enum@zvariant::Value`].
45pub fn serialize<T, S>(value: &T, ser: S) -> std::result::Result<S::Ok, S::Error>
46where
47    S: Serializer,
48    T: Type + serde::Serialize,
49{
50    use serde::Serialize as _;
51
52    Serialize(value).serialize(ser)
53}
54
55/// Serialize an optional value as a [`enum@zvariant::Value`].
56pub fn serialize_optional<T, S>(value: &Option<T>, ser: S) -> std::result::Result<S::Ok, S::Error>
57where
58    S: Serializer,
59    T: Type + serde::Serialize,
60{
61    super::serialize(value.as_ref().unwrap(), ser)
62}