diwic / dbus-rs

D-Bus binding for the Rust language
Other
589 stars 133 forks source link

Add signature iter methods to libdbus-sys #471

Closed jobfeikens closed 4 months ago

jobfeikens commented 4 months ago

I added some missing methods to the libdbus-sys crate.

diwic commented 4 months ago

LGTM. Curious what you're going to use it for?

jobfeikens commented 4 months ago

LGTM. Curious what you're going to use it for?

I wanted to implement Append for my custom type but I needed to know the inner signature before calling either append_dict or append_array.

impl Append for DBusValue {
    fn append_by_ref(&self, iter: &mut IterAppend) {
        match self {
            DBusValue::U8(value) => value.append_by_ref(iter),
            DBusValue::Bool(value) => value.append_by_ref(iter),
            DBusValue::I16(value) => value.append_by_ref(iter),
            DBusValue::U16(value) => value.append_by_ref(iter),
            DBusValue::I32(value) => value.append_by_ref(iter),
            DBusValue::U32(value) => value.append_by_ref(iter),
            DBusValue::I64(value) => value.append_by_ref(iter),
            DBusValue::U64(value) => value.append_by_ref(iter),
            DBusValue::F64(value) => value.append_by_ref(iter),
            DBusValue::UnixFd(value) => value.append_by_ref(iter),
            DBusValue::String(value) => value.append_by_ref(iter),
            DBusValue::ObjectPath(value) => value.deref().append_by_ref(iter),
            DBusValue::Signature(value) => value.deref().append_by_ref(iter),
            DBusValue::Variant(value) => iter.append_variant(
                &Signature::new(value_signature(&value)).unwrap(),
                |iter| {
                    value.append_by_ref(iter);
                },
            ),
            DBusValue::Array(value) => {
                let signature_iter = SignatureIter::new(&value.signature);
                let array_iter = signature_iter.recurse();

                if array_iter.current_type() == DBUS_TYPE_DICT_ENTRY {
                    let mut dict_entry_iter = array_iter.recurse();
                    let key_signature = dict_entry_iter.current_signature();
                    dict_entry_iter.next();
                    let value_signature = dict_entry_iter.current_signature();

                    iter.append_dict(&key_signature, &value_signature, |iter| {
                        for value in &value.values {
                            value.append_by_ref(iter);
                        }
                    })
                } else {
                    let inner_signature = array_iter.current_signature();

                    iter.append_array(&inner_signature, |iter| {
                        for value in &value.values {
                            value.append_by_ref(iter);
                        }
                    })
                }
            }
            DBusValue::Struct(values) => iter.append_struct(|iter| {
                for value in values {
                    value.append_by_ref(iter);
                }
            }),
            DBusValue::DictEntry { key, value } => {
                iter.append_dict_entry(|iter| {
                    key.append_by_ref(iter);
                    value.append_by_ref(iter);
                })
            }
        }
    }
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum DBusValue {
    #[serde(rename = "y")]
    U8(u8),

    #[serde(rename = "b")]
    Bool(bool),

    #[serde(rename = "n")]
    I16(i16),

    #[serde(rename = "q")]
    U16(u16),

    #[serde(rename = "i")]
    I32(i32),

    #[serde(rename = "u")]
    U32(u32),

    #[serde(rename = "x")]
    I64(i64),

    #[serde(rename = "t")]
    U64(u64),

    #[serde(rename = "d")]
    F64(f64),

    #[serde(rename = "h")]
    UnixFd(RawFd),

    #[serde(rename = "s")]
    String(String),

    #[serde(rename = "o")]
    ObjectPath(
        #[serde(
            serialize_with = "serialize::serialize_path",
            deserialize_with = "serialize::deserialize_path"
        )]
        dbus::Path<'static>,
    ),

    #[serde(rename = "g")]
    Signature(
        #[serde(
            serialize_with = "serialize::serialize_signature",
            deserialize_with = "serialize::deserialize_signature"
        )]
        dbus::Signature<'static>,
    ),

    #[serde(rename = "v")]
    Variant(Box<DBusValue>), // TODO: make sure inner value isnt a dict entry or append_by_ref will fail

    #[serde(rename = "a", rename_all = "camelCase")]
    Array(ArrayValue),

    #[serde(rename = "r")]
    Struct(Vec<DBusValue>),

    #[serde(rename = "e")]
    DictEntry {
        key: Box<DBusValue>,
        value: Box<DBusValue>,
    },
}

#[derive(Debug, Serialize)]
pub struct ArrayValue {
    // Signature of the contained values 
    // (This includes 'a' because dict entries' signatures are not valid on their own)
    #[serde(serialize_with = "serialize::serialize_inner_signature")]
    pub(crate) signature: dbus::Signature<'static>,

    #[serde(skip_serializing_if = "Vec::is_empty")]
    pub(crate) values: Vec<DBusValue>,
}