Skip to content

Instantly share code, notes, and snippets.

@ModProg
Created July 29, 2024 09:13
Show Gist options
  • Save ModProg/62f39e8a2595f980c4a2ede49163d01e to your computer and use it in GitHub Desktop.
Save ModProg/62f39e8a2595f980c4a2ede49163d01e to your computer and use it in GitHub Desktop.
use dbus::arg::{Append, Arg, IterAppend, Variant};
pub trait AppendToDict {
fn append_to_dict(&self, key: &'static str, i: &mut IterAppend);
fn append_to_dict_as_variant(&self, key: &'static str, i: &mut IterAppend);
}
pub struct Wrap<T>(pub T);
impl<T: Append + Arg> AppendToDict for &Wrap<&T> {
fn append_to_dict(&self, key: &'static str, i: &mut IterAppend) {
i.append_dict_entry(|i| {
i.append(key);
i.append(self.0);
});
}
fn append_to_dict_as_variant(&self, key: &'static str, i: &mut IterAppend) {
i.append_dict_entry(|i| {
i.append(key);
i.append_variant(&T::signature(), |i| i.append(self.0));
});
}
}
impl<T: Append + Arg> AppendToDict for Wrap<&Option<T>> {
fn append_to_dict(&self, key: &'static str, i: &mut IterAppend) {
if let Some(v) = self.0 {
i.append_dict_entry(|i| {
i.append(key);
i.append(v);
});
}
}
fn append_to_dict_as_variant(&self, key: &'static str, i: &mut IterAppend) {
if let Some(v) = self.0 {
i.append_dict_entry(|i| {
i.append(key);
i.append_variant(&T::signature(), |i| i.append(v));
});
}
}
}
impl<T: Append + Arg> Wrap<&Option<Variant<T>>> {
pub fn append_to_dict(&self, key: &'static str, i: &mut IterAppend) {
if let Some(v) = self.0 {
i.append_dict_entry(|i| {
i.append(key);
i.append(v);
});
}
}
pub fn append_to_dict_as_variant(&self, key: &'static str, i: &mut IterAppend) {
if let Some(v) = self.0 {
i.append_dict_entry(|i| {
i.append(key);
i.append(v);
});
}
}
}
impl<T: Append + Arg> Wrap<&Variant<T>> {
pub fn append_to_dict(&self, key: &'static str, i: &mut IterAppend) {
i.append_dict_entry(|i| {
i.append(key);
i.append(self.0);
});
}
pub fn append_to_dict_as_variant(&self, key: &'static str, i: &mut IterAppend) {
i.append_dict_entry(|i| {
i.append(key);
i.append(self.0);
});
}
}
#[test]
#[allow(clippy::needless_borrow)]
fn test() {
use dbus::arg::{IterAppend, PropMap};
use dbus::Message;
let mut message = Message::new_method_call("a.b", "/a/b", "a.b", "C").unwrap();
let i = &mut IterAppend::new(&mut message);
i.append_dict(&"s".into(), &"v".into(), |i| {
(&Wrap(&"a")).append_to_dict_as_variant("a", i); // calls general implementation for T: Append + Arg
(&Wrap(&Some("b"))).append_to_dict_as_variant("b", i); // calls implementation for Option<T: Append + Arg>
(&Wrap(&Variant("c"))).append_to_dict_as_variant("c", i); // calls implementation for Variant<T: Append + Arg>
(&Wrap(&Some(Variant("d")))).append_to_dict_as_variant("d", i); // calls implementation for Option<Variant<T: Append + Arg>
});
let dict: PropMap = message.read1().unwrap();
assert_eq!(dict.get("a").unwrap().0.signature(), "s".into());
assert_eq!(dict.get("b").unwrap().0.signature(), "s".into());
assert_eq!(dict.get("c").unwrap().0.signature(), "s".into());
assert_eq!(dict.get("d").unwrap().0.signature(), "s".into());
}
@ModProg
Copy link
Author

ModProg commented Jul 29, 2024

Variant impls Arg and Append, but I don't want to layer the Variant twice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment