Git Product home page Git Product logo

dbus-rs's People

Contributors

1wilkens avatar a1ien avatar albel727 avatar amezin avatar coolreader18 avatar danieldulaney avatar deifactor avatar diwic avatar hoodie avatar hugoduncan avatar ids1024 avatar infinityb avatar iovxw avatar jcristau avatar koalo avatar landhb avatar manuels avatar mulkieran avatar not-jan avatar paulvt avatar poletaevvlad avatar qwandor avatar sherlock-holo avatar snarpix avatar toqozz avatar valpackett avatar xaeroxe avatar xkr47 avatar zeenix avatar zevweiss avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dbus-rs's Issues

arg_type should be an enum

...rather than an i32. This is a small breaking change, but I'm keeping it here so I remember it next time I do breaking changes.

Serde support for msgarg

It would be nice if there was a way to serialize/deserialize directly between structs and DBus arguments/messages.

Given that serde seems to be the future rather than rustc_serialize, that's the proposed framework to use for serializing/deserializing.

Make MethodHandler FnMut?

Hi (again)

Is it possible to make MethodHandler FnMut? I want to be able to change the state of my program from the method callback but this is not possible if Fn is used for the closure..

"cargo test" fails on 1.5.0+

It runs just fine on 1.4.0-nightly, but fails on 1.5.0-stable and 1.7.0-nightly.

src/methoddisp.rs:793:88: 797:6 error: `count` does not live long enough
src/methoddisp.rs:793     let _setme = i.add_p_ref(f.property("setme", 0u8).access(Access::ReadWrite).on_set(|_,_,_| {
src/methoddisp.rs:794         let v: i32 = count.get_value().inner().unwrap();
src/methoddisp.rs:795         count.set_value((v + 1).into()).unwrap();
src/methoddisp.rs:796         Ok(vec!())
src/methoddisp.rs:797     }));
src/methoddisp.rs:787:27: 798:2 note: reference must be valid for the block at 787:26...
src/methoddisp.rs:787 fn prop_lifetime_simple() {
src/methoddisp.rs:788     let count;
src/methoddisp.rs:789     let f = Factory::new_fnmut();
src/methoddisp.rs:790     let mut i = f.interface("com.example.dbus.rs");
src/methoddisp.rs:791     count = i.add_p_ref(f.property("changes", 0i32));
src/methoddisp.rs:792 
                  ...
src/methoddisp.rs:788:15: 798:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 788:14
src/methoddisp.rs:788     let count;
src/methoddisp.rs:789     let f = Factory::new_fnmut();
src/methoddisp.rs:790     let mut i = f.interface("com.example.dbus.rs");
src/methoddisp.rs:791     count = i.add_p_ref(f.property("changes", 0i32));
src/methoddisp.rs:792 
src/methoddisp.rs:793     let _setme = i.add_p_ref(f.property("setme", 0u8).access(Access::ReadWrite).on_set(|_,_,_| {

Puzzled about how to emit PropertiesChanged signal for a RO property

Hi!

We have a bunch of properties that are RO by intention (can not be set via the D-Bus interface).
But the value of a RO property may still change. This change could result from side-effects from other procedure calls or any number of reasons.

When this happens, it is still desirable to emit a PropertiesChanged signal which includes the information about the property changed in a reasonably timely manner. We're not sure if we want to just invalidate or actually give the new value.

Are there currently recommended ways to go about doing this, i.e., emitting a PropertiesChanged signal with information for a RO property?

Just a Question

I'm writing a GUI front-end to systemd for managing system services and although I am able to get a list of unit files from dbus using this wrapper, I'm not quite sure how to go about sending the information needed to disable and enable services through dbus. The following is what I'm using to get the information I need, and this works perfectly.

let connection = dbus::Connection::get_private(dbus::BusType::System).unwrap();
let message = dbus::Message::new_method_call("org.freedesktop.systemd1",
    "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "ListUnitFiles").
    unwrap_or_else(|e| panic!("{}", e));
let reply = connection.send_with_reply_and_block(message, 1000).unwrap();

Now I need to call the EnableUnitFiles() and DisableUnitFiles() methods with information I've gained from the first method, which requires a list of pathnames (I'll only do one at a time) with two booleans, yet I'm not quite sure how to accomplish this.

publish to crates.io for bugfix?

Hello,

I also commented in the now-closed issue #33, which fixed the bug, but wasn't sure if you'd be notified.

But I was wondering if you could publish a new version to crates with the bugfix. I'd like to publish my secret service library, which depends on the bugfix.

I don't think I can use your github repo as the dependency source for crates.io, but if there's another workaround for now I'd be happy to do it.

Why is it not possible to verify that values sent by a service match the published signature?

Hi!

This is more of a question than a bug as it seems like all the dbus implementations that I have looked at work the same.

Basically, it seems that a service writes some code that determines the introspection information that can be obtained over the dbus via the Introspect method. Also, it writes some code that puts messages on the dbus. These messages are supposed to conform to the signature information that the client can get via the Introspect method. But the dbus libraries, including yours, don't seem to have any mechanism in place for ensuring that this happens correctly, or for detecting errors. Basically, making sure that the actual values match the published signature seems to be entirely up to the programmer.

I am wondering if there is a way of fixing this problem in a library written in a language which is statically checked and has a fairly flexible type system like Rust does.

Question about asynchronous server.

Couldn't find if there were any other venues to ask question, sorry for the issue noise.

I'm working on a screensaver and I'd like to use DBus for communication, so I can have a server that creates a DBus interface and whatnot and wait for requests like to start the screensaver or lock the screen.

Since there are also other things involved the design from the example with the closures seems rather complicated to fit into my design.

What I'm trying to achieve is having a Server struct that contains the connection/tree/whatever which spawns a thread, and this thread sends the DBus calls being received through a channel, then the loop in main reads from the channel, does some thing and calls the proper stuff to respond to the request and writes back to another channel, and then the thread spawned by Server responds back through DBus.

Is this currently possible without hacking it up using the Factory::method closures? Are there any examples to do this I missed?

Thanks.

Refactor to be more Rust-ic

What, IMHO, needs to be done:

  • Create a single Interface trait, that a server would have to implement (the library should implement this for a RegisteredInterface struct that a client would get from a Connection)
  • A signle Property enum, with branches of trait ROProperty, WOProperty and type RWProperty = ROProperty + WOProperty
  • Write a macro for implementing said Interface trait from a dbus xml file
  • Fix #10
    etc. (to be added as comments)

Move to being a pure Rust library?

Cutting external dependencies is always nice and it looks like there is a pure Rust DBus implementation here and a useful looking utility lib here. Any reason to not make use of them?

Unable to build dbus-rs for ARM

Hi,

I am working on a Yocto/OE recipe for building RVI SOTA client which is written in the Rust programming language and depends on crate dbus-rs version 0.1.2. I noticed that the crate fails to build for ARM due to mismatched types. In my opinion c_char raw pointers should be cast correctly to make it work for ARM. I have already created a patch for version 0.1.2 as part of the Yocto/OE recipe. In my opinion similar patches have to be applied to the latest versions of files src/lib.rs and src/message.rs.

Best regards, Leon

Inexplicable Variant wrapping of D-Bus property.

Hi,

I'm experiencing an artefact where some tools that interrogate the D-Bus service think that the signature of a property is a Variant containing a type X, and others think that it is the bare type X.

Compare the following:

[mulhern@dhcp-25-209 stratisd-client-dbus]$ busctl --user get-property org.storage.stratis1 /org/storage/stratis1 org.storage.stratis1.Manager RedundancyCodes
a(sq) 1 "RAID0" 0

From QT5DbusViewer

Received reply from :1.6899
  Arguments: [Variant: [Argument: a(sq) {[Argument: (sq) "RAID0", 0]}]]

From dbus-python

(Pdb) Manager.Properties.RedundancyCodes(self._proxy)
dbus.Array([dbus.Struct((dbus.String('RAID0'), dbus.UInt16(0)), signature=None)], signature=dbus.Signature('(sq)'), variant_level=1)

Note how the bottom 2 think that they're dealing with a variant type, while busctl does not seem to.
Note also that it is not the type within the array that is a variant, but the array itself.

Have you heard of this and do you think it's likely that it is a result of some dbus-rs behavior? I had originally ruled that out, because busctl does not indicate that the result is a variant. But I have also noticed that you have a publicly defined get_as_variant() method on the Property, and I'm not sure of its purpose or when it might be called.

Please let me know if you have any thoughts,

Thanks!

Getting associated data from an object path obtained as an argument of a method.

This question is somewhat related to the problem of method dispatch on multiple parameters (rather than just the first).

I am planning to have a method, m, which accepts object paths as arguments. The client has identified the appropriate object paths to pass as arguments by examining the result of GetManagedObjects() and identifying the correct object paths by matching on the interface and property values. The arguments as received by the service have been constructed as MessageItem::ObjectPath<some Path>. So, while the first argument, on which the method has been dispatched, contains the actual object path with associated data, the other object path arguments do not.

It is desirable, from my point of view, to use the Path argument to obtain the corresponding ObjectPath from the tree. The reason for this is that I plan to have decorated the ObjectPath with essential data which my method requires for its operation. At this time, it is not possible to lookup an ObjectPath in the tree in order to discover its data.

Is that a fundamental limitation, or could it be removed by means of a get method on the tree?

Note: It would also be possible to have a look-aside table attached to the tree which mapped Paths to the appropriate data and to choose not to decorate the ObjectPath at all. But that seems to be working a bit outside the expectations of this library and seems kind of clumsy.

Arguments to dbus_message_iter_open_container are incorrect

process 11575: arguments to dbus_message_iter_open_container() were incorrect, assertion "(type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || _dbus_check_is_valid_signature (contained_signature))" failed in file dbus-message.c line 2878. This is normally a bug in some application using the D-Bus library. D-Bus not built with -rdynamic so unable to print a backtrace

Looks like this is in iter_append_array. The typesig for the failing operation is {sv} and the a parameter is [DictEntry(Str("BlockDevices"), Variant(Array([Struct([Str("/dev/vdd"), UInt32(0)]), Struct([Str("/dev/vdb"), UInt32(0)]), Struct([Str("/dev/vdc"), UInt32(0)])], "(su)")))]

For reference, the code where I'm building the MessageItem is https://github.com/agrover/froyo/blob/master/src/dbus_api.rs#L38 in case the error lies there.

Arg, trait object version

To get/append arguments to a message, we can currently to it the enum way (MessageItem) or the generics way (msgarg::Arg). But we're missing the trait object way. It would be very helpful, e g, if one could append, say, an Box<Arg + Append>, but that doesn't work today, because Arg is not object safe.

Problems installing dbus-rs via cargo on Travis-CI

Hi!

Here's a link to my failure: https://travis-ci.org/stratis-storage/stratisd/builds/174912560. Let me know if you aren't able to view it.

The failure is here:

Build failed, waiting for other jobs to finish...
error: failed to run custom build command for `dbus v0.4.1`
process didn't exit successfully: `/home/travis/build/stratis-storage/stratisd/target/debug/build/dbus-5e9bab8f37d6caf2/build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: "`\"pkg-config\" \"--libs\" \"--cflags\" \"dbus-1\"` did not exit successfully: exit code: 1\n--- stdout\nPackage dbus-1 was not found in the pkg-config search path.\nPerhaps you should add the directory containing `dbus-1.pc\'\nto the PKG_CONFIG_PATH environment variable\nNo package \'dbus-1\' found\n"', ../src/libcore/result.rs:79

The problem is, possibly, a question around Ubuntu which doesn't seem to actually have a package called dbus-1. See: http://packages.ubuntu.com/search?keywords=dbus. Have you heard about install issues on Ubuntu before or could you offer any suggestions?

Thanks and let me know if I can give you more information.

dbus-rs set a illegal signature 'r'

When sending a struct in an array like this

extern crate dbus;
use dbus::{Connection, BusType, MessageItem, Message};

fn main() {
    let c = Connection::get_private(BusType::Session).unwrap();
    let mut m = Message::new_method_call("org.test.rust",
                                        "/", "org.test.rust",
                                        "Test").unwrap();

    let a = MessageItem::from("test".to_string());
    let b = MessageItem::from("test".to_string());
    let foo = MessageItem::Struct(vec!(a, b));
    let bar = foo.clone();

    let args = [MessageItem::new_array(vec!(foo, bar)).unwrap()];
    println!("{:?}", args);

    m.append_items(&args);
    c.send(m).unwrap();
}

The signature is set to "r", which, according to the D-Bus documentation, "is reserved for use in bindings and implementations to represent the general concept of a struct, and must not appear in signatures used on D-Bus".

Trying to send such a Message results in

arguments to dbus_message_iter_open_container() were incorrect, assertion "(type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || _dbus_check_is_valid_signature (contained_signature))" failed in file dbus-message.c line 2914.

This could or could not be a bug in the dbus library according to this and this.

Anyways manually setting the signature works around the issue:

extern crate dbus;
use dbus::{Connection, BusType, MessageItem, Message};
use std::borrow::Cow;

fn main() {
    let c = Connection::get_private(BusType::Session).unwrap();
    let mut m = Message::new_method_call("org.test.rust",
                                        "/", "org.test.rust",
                                        "Test").unwrap();

    let a = MessageItem::from("test".to_string());
    let b = MessageItem::from("test".to_string());
    let foo = MessageItem::Struct(vec!(a, b));
    let bar = foo.clone();

    let args = [MessageItem::Array(vec!(foo, bar), Cow::Owned("(ss)".to_string()))];

    m.append_items(&args);
    c.send(m).unwrap();
}

Adding authentication to interfaces/methods

Hey there, sorry if this is a dumb question, but the docs for D-Bus are very technical and there doesn't seem to be much else out there on the web.

If I want to only allow certain clients to use an interface/method, how would I go about doing that through this crate? I saw this question on stackexchange that mentioned a ~/.dbus-keyrings folder, but wasn't sure how that relates to having different interfaces/methods exposed to clients.

I could do something application side (e.g with tokens/a listing of whitelisted clients), but I wanted to see if there was an easier and more idiomatic way before going down that route.

Rename the Cargo package to simply "dbus"

Two reasons:

  1. The -rs suffix is redundant, since the fact that it's on crates.io already tells us it's Rust.
  2. The extra hyphen means I have to rename the crate every time I use it: extern crate "dbus-rs" as dbus;.

dbus is still free on crates.io, so now's a great opportunity to grab the name.

Help needed! Creating and populating a new dbus::arg::Dict

How can I create new dbus::arg::Dict with the type dbus::arg::Dict<&str, dbus::arg::Dict<&str, dbus::arg::Variant<_> containing data that looks like this...

{
'802-11-wireless': {'mac-address': [228, 179, 24, 77, 64, 139],
                     'mac-address-blacklist': [],
                     'mode': 'infrastructure',
                     'security': '802-11-wireless-security',
                     'seen-bssids': ['EC:1F:72:1C:60:36'],
                     'ssid': [106, 111, 101]},
 '802-11-wireless-security': {'auth-alg': 'open',
                              'group': [],
                              'key-mgmt': 'wpa-psk',
                              'pairwise': [],
                              'proto': []},
 'connection': {'id': 'joe',
                'permissions': [],
                'secondaries': [],
                'timestamp': 1484488610,
                'type': '802-11-wireless',
                'uuid': '347aa082-8846-4e8d-be99-bd527c65eef1'}
}

So far I have this...

fn main() {
    let mut settings = std::collections::HashMap::new();

    settings.insert("connection",
                std::collections::HashMap::<&str, dbus::arg::Variant<_>>::new());
    settings.insert("802-11-wireless",
                std::collections::HashMap::<&str, dbus::arg::Variant<_>>::new());
    settings.insert("802-11-wireless-security",
                std::collections::HashMap::<&str, dbus::arg::Variant<_>>::new());

    settings.get_mut("connection").unwrap().insert("id", dbus::arg::Variant("resin_io"));
    settings.get_mut("connection").unwrap().insert("type", dbus::arg::Variant("802-11-wireless"));

    settings.get_mut("802-11-wireless").unwrap().insert("ssid", dbus::arg::Variant(vec![10, 20, 30]));

    let test = dbus::arg::Dict::new(settings.iter());
    println!("{:?}", settings);
}

which throws some errors...

error[E0308]: mismatched types
  --> src/main.rs:18:84
   |
18 |     settings.get_mut("802-11-wireless").unwrap().insert("ssid", dbus::arg::Variant(vec![10, 20, 30]));
   |                                                                                    ^^^^^^^^^^^^^^^^ expected &str, found struct `std::vec::Vec`
   |
   = note: expected type `&str`
   = note:    found type `std::vec::Vec<{integer}>`
   = help: here are some functions which might fulfill your needs:
           - .remove(...)
           - .swap_remove(...)
   = note: this error originates in a macro outside of the current crate

error[E0277]: the trait bound `std::collections::HashMap<&str, dbus::arg::Variant<&str>>: dbus::arg::Arg` is not satisfied
  --> src/main.rs:20:16
   |
20 |     let test = dbus::arg::Dict::new(settings.iter());
   |                ^^^^^^^^^^^^^^^^^^^^ the trait `dbus::arg::Arg` is not implemented for `std::collections::HashMap<&str, dbus::arg::Variant<&str>>`
   |
   = note: required because of the requirements on the impl of `dbus::arg::Arg` for `&std::collections::HashMap<&str, dbus::arg::Variant<&str>>`
   = note: required by `dbus::arg::Dict`

error[E0277]: the trait bound `std::collections::HashMap<&str, dbus::arg::Variant<&str>>: dbus::arg::Append` is not satisfied
  --> src/main.rs:20:16
   |
20 |     let test = dbus::arg::Dict::new(settings.iter());
   |                ^^^^^^^^^^^^^^^^^^^^ the trait `dbus::arg::Append` is not implemented for `std::collections::HashMap<&str, dbus::arg::Variant<&str>>`
   |
   = note: required because of the requirements on the impl of `dbus::arg::Append` for `&std::collections::HashMap<&str, dbus::arg::Variant<&str>>`
   = note: required by `<dbus::arg::Dict<'a, K, V, I>>::new`

error[E0277]: the trait bound `std::collections::HashMap<&str, dbus::arg::Variant<&str>>: dbus::arg::Arg` is not satisfied
  --> src/main.rs:20:16
   |
20 |     let test = dbus::arg::Dict::new(settings.iter());
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `dbus::arg::Arg` is not implemented for `std::collections::HashMap<&str, dbus::arg::Variant<&str>>`
   |
   = note: required because of the requirements on the impl of `dbus::arg::Arg` for `&std::collections::HashMap<&str, dbus::arg::Variant<&str>>`
   = note: required by `dbus::arg::Dict`

error: aborting due to 4 previous errors

Am I am on right track or completely missing something?
Do you have any plans to enable conversion between structs and dbus types?

Thanks in advance.

Help with returning tuple of values

I'm trying to have a d-bus method return a tuple of two values (specifically a width and height) and I for some reason can't get the signature right.

Here's a snippet of the test code I have:

            .add_m(
                f.method("Resolution", (), |m| {
                    Ok(vec![m.msg.method_return()
                            .append2(1u32, 1u32)
                    ])
                }).outarg::<(u32, u32), _>("success")

But when trying to test it with a Python repl + pydbus I get the error:

Method 'Resolution' returned type '(uu)', but expected '((uu))' (13)

Nested dictionaries error

I might be making a mistake in implementation, but I have not been able to get nested dictionaries to work.

Building the dictionary with a nested dictionary:
https://github.com/hwchen/secret-service-rs/blob/master/src/collection.rs#L224

The method call interface:
https://github.com/hwchen/secret-service-rs/blob/master/src/util.rs#L64

The test:
https://github.com/hwchen/secret-service-rs/blob/master/src/item.rs#L272

The error:

---- item::test::should_create_get_and_set_item_attributes stdout ----
    thread 'item::test::should_create_get_and_set_item_attributes' panicked at 'assertion failed: unsafe {
    ffi::dbus_message_iter_open_container(i, ffi::DBUS_TYPE_VARIANT, atype.as_ptr(), &mut subiter)
} != 0',
/home/hwchen/.cargo/registry/src/github.com-88ac128001ac3a9a/dbus-0.2.1/src/message.rs:154

Please excuse messy code, I have a lot of refactoring to do.

Property method invoked with surprising object path

This occurs when I invoke GetManagedObjects.

I have a property defined for an interface called Pool.
As the properties are being listed a method belonging to the Pool interface is invoked. It extracts the object path, but that object path is the object path that was used to call GetManagedObjects originally, and it is not an object path for an object that implements the Pool interface. This causes an error in my method as this situation is unexpected.

Obtaining the value of the property on an object path that does implement the Pool interface works fine.

Running dbus-0.4.1.

Parse input arguments

Thank you for the great rust wrapper! I have a question.

I can't find any example on how to parse the input arguments and convert from MessageItem to for example String. Is this not implemented yet? If it is, how can get the incoming arguments as native types, ie, i32, String, etc?

Call to ObjectManager GetManagedObjects() fails

I get this error when calling GetManagedObjects from qdbusviewer-qt5. Here's my code for reference.

process 12282: Array or variant type requires that type object_path be written, but string was written.
The overall signature expected here was 'a{oa{sa{sv}}}' and we are on byte 2 of that signature.
  D-Bus not built with -rdynamic so unable to print a backtrace

Some ideas for improving the API.

Not sure if this is technically the best forum for this discussion, but I figured I'd post my ideas out in the open so that anyone looking at and using this library can help scrutinize them.

First, thanks for writing this library. FFI code is not one of my strong points in Rust, and so it helps to have a lot of that boilerplate out of the way. =) That said, I do have some suggestions for improving it. Your API is almost an exact mapping of some of the functions from the DBus API, which means that it's functional, but not very Rustic. The DBus API's design is largely constrained by C's relative simplicity, but I believe there are a few approaches worth considering to make it easier to use on the Rust side.

The first big change that I've been playing around with (in the sense that I don't yet have a working version) is newtyping Message into several different types like this:

// private newtype of DBusMessage, where shared functionality would be implemented
struct Message(*mut ffi::DBusMessage);

// public newtypes for specific message types
pub struct MethodCall(Message);
pub struct MethodReturn(Message);
// ...etc.

The advantage of this is that certain methods, such as for constructing return values, would only be available on the message types where it makes sense.

impl Message {
    // potential location for methods that are supported by multiple types
}

impl MethodCall {
    pub fn new_method_return(&self, ...) -> MethodReturn {
        ...
    }
}

impl MethodReturn {
    // notice how new_method_return() is missing
}

Then most of the Message methods could be implemented as instance methods on the type that supports them.

One other possibility I've been playing around with in my head is to group all of the public Message types under an enum, e.g.

struct msg(*mut ffi::DBusMessage); // notice the rename

pub enum Message {
    MethodCall(msg),
    MethodReturn(msg),
    // ...etc.
}

Lastly, a minor note is that instead of accepting &str parameters, it would be nice if these methods accepted anything implementing Str to eliminate the need to ever call .as_slice() outside of their implementation.

Maybe if I have some time in the coming weeks I'll try and get a working prototype together, but I just wanted to share my thoughts.

Cannot compile dbus on Raspberry Pi 3: Mismatched Types

I'm trying to use dbus as a dependency, but the build process fails with a type mismatch error in the invocation of cstring_wrapper!(). Am I doing something wrong?

   Compiling dbus v0.5.1
     Running `rustc --crate-name dbus /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.5.1/src/lib.rs --crate-type lib -g -C metadata=c7a44efa2351d871 -C extra-filename=-c7a44efa2351d871 --out-dir /home/pi/elyo/trunk/rust/test/target/debug/deps --emit=dep-info,link -L dependency=/home/pi/elyo/trunk/rust/test/target/debug/deps --extern libc=/home/pi/elyo/trunk/rust/test/target/debug/deps/liblibc-b4eee0616d69ca39.rlib --cap-lints allow -L native=/usr/lib/arm-linux-gnueabihf -l dbus-1`
error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.5.1/src/strings.rs:43:25
    |
43  |         $t::check_valid(s.as_ptr() as *const i8).map(|_| {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
...
128 | cstring_wrapper!(Signature, dbus_signature_validate_single);
    | ------------------------------------------------------------ in this macro invocation

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.5.1/src/strings.rs:43:25
    |
43  |         $t::check_valid(s.as_ptr() as *const i8).map(|_| {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
...
140 | cstring_wrapper!(Path, dbus_validate_path);
    | ------------------------------------------- in this macro invocation

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.5.1/src/strings.rs:43:25
    |
43  |         $t::check_valid(s.as_ptr() as *const i8).map(|_| {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
...
152 | cstring_wrapper!(Member, dbus_validate_member);
    | ----------------------------------------------- in this macro invocation

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.5.1/src/strings.rs:43:25
    |
43  |         $t::check_valid(s.as_ptr() as *const i8).map(|_| {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
...
159 | cstring_wrapper!(Interface, dbus_validate_interface);
    | ----------------------------------------------------- in this macro invocation

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.5.1/src/strings.rs:43:25
    |
43  |         $t::check_valid(s.as_ptr() as *const i8).map(|_| {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
...
166 | cstring_wrapper!(BusName, dbus_validate_bus_name);
    | -------------------------------------------------- in this macro invocation

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.5.1/src/strings.rs:43:25
    |
43  |         $t::check_valid(s.as_ptr() as *const i8).map(|_| {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
...
173 | cstring_wrapper!(ErrorName, dbus_validate_error_name);
    | ------------------------------------------------------ in this macro invocation

error: aborting due to 6 previous errors

error: Could not compile `dbus`.

Caused by:
  process didn't exit successfully: `rustc --crate-name dbus /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.5.1/src/lib.rs --crate-type lib -g -C metadata=c7a44efa2351d871 -C extra-filename=-c7a44efa2351d871 --out-dir /home/pi/elyo/trunk/rust/test/target/debug/deps --emit=dep-info,link -L dependency=/home/pi/elyo/trunk/rust/test/target/debug/deps --extern libc=/home/pi/elyo/trunk/rust/test/target/debug/deps/liblibc-b4eee0616d69ca39.rlib --cap-lints allow -L native=/usr/lib/arm-linux-gnueabihf -l dbus-1` (exit code: 101)

Convert Hashmap<String, u64> to MessageItem

Hi. I've a message of type

published_count: HashMap<String, u64>,

I want to broadcast a signal with above message. How do I do that?

I'm trying to do something like this.

let m3 = dbus::Message::new_signal("/com/tekjar/Test",  "com.tekjar.Test",  "TotalPublishCount").unwrap();
let m3 = m3.append(total_published_count.into());
connection.send(m3).unwrap();

Minimal dbus version?

I was trying to compile Servo in a CentOS 6.5 environment, which has dbus-1.2.24-7. Linking fails:

/home/djc/src/servo/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.3.3/src/strings.rs:28: error: undefined reference to 'dbus_validate_path'
/home/djc/src/servo/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.3.3/src/strings.rs:19: error: undefined reference to 'dbus_validate_path'
/home/djc/src/servo/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.3.3/src/strings.rs:28: error: undefined reference to 'dbus_validate_member'
/home/djc/src/servo/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.3.3/src/strings.rs:19: error: undefined reference to 'dbus_validate_member'
/home/djc/src/servo/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.3.3/src/strings.rs:28: error: undefined reference to 'dbus_validate_interface'
/home/djc/src/servo/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.3.3/src/strings.rs:19: error: undefined reference to 'dbus_validate_interface'
/home/djc/src/servo/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.3.3/src/strings.rs:28: error: undefined reference to 'dbus_validate_bus_name'
/home/djc/src/servo/.cargo/registry/src/github.com-1ecc6299db9ec823/dbus-0.3.3/src/strings.rs:19: error: undefined reference to 'dbus_validate_bus_name'

What versions of dbus are supported? Would it be viable to support this version of dbus?

New to Rust, how to retrieve Props content data?

Hi, I'm using your library to cut my teeth with Rust.

Namely I'm trying to retrieve metadata of the current song played by VLC:

let c = Connection::get_private(BusType::Session).unwrap();                                                   
let p = Props::new(&c, "org.mpris.MediaPlayer2.vlc",                                                          
                       "/org/mpris/MediaPlayer2",                                                             
                       "org.mpris.MediaPlayer2.Player",                                                       
                       10000);                                                                                
let res : Result<MessageItem, _> = p.get("Metadata");
match res {                                                                                                   
    dbus::arg::Array(res) => Ok(res),
    // ....
};                                                                                                            

However I can't use the dbus::arg::XXX methods as suggested in #39 to retrieve the item(s) from the Props, I have a casting error like mismatched types (expected enum 'std::result::Result', found struct 'dbus::arg::Array'). Dumping directly with a println! shows the correct content:

Ok(Array([DictEntry(Str("mpris:trackid"), Variant(ObjectPath(Path("/org/videolan/vlc/playlist/15")))), DictEntry(Str("xesam:url"), ....)

How do I iterate the std::result::Result to a dbus::arg::Array and friends (Variant, Dict, etc.)?

Thank you so much for a hint!

memory usage with large numbers of objects

Hi, my friend @tasleson did some work to find out the memory usage of using dbus, and saw high memory usage by dbus-rs, worse than when implemented in Python. His code is here:

https://github.com/tasleson/misc-tools/tree/master/dbus_memory/rust

My theory is this is because dbus-rs is not sharing identical strings, such as interface or property names, that sort of thing, which adds up when there are large numbers of each, but this is just a guess at the moment.

Handling runtime tree modifications

Object paths supported by a tree may come and go. Tree has an add() but lacks remove(). It's easy to add a remove() that just removes it from self.paths, but it looks like we also need to call c.unregister_object_path...but only if after set_registered() has been called. So basically I'm thinking to enable adding/removing object paths at runtime we need to either pass c to add() & remove() and register/unregister within those functions, but then we don't really need set_registered() any more? But then maybe we want to unregister any remaining paths from Drop?

Wanted to get your thoughts on what it would take to properly enable this.

Bytestrings (ay)

Hi,

I'm the creator of pydbus, DBus bindings for Python. I've stumbled upon the case of bytestrings - ay - which are commonly used to send non-Unicode data over DBus.

Because of the GDBus's API, apps commonly require these strings to be '\0'-terminated. And that's completely unintuitive for high-level languages, and something that requires the user to read API docs.

I'm thinking about solving the problem automatically, and I see two solutions:

  1. Auto-append and auto-strip the last character of "ay"s; [EDIT: impossible, some APIs use not-terminated strings]
  2. Decree (how?) that GDBus API is wrong, and strings sent over the wire should not be \0-terminated.
  3. [EDIT:] Create a new DBus annotation meaning "All "ay"s in the arguments of this method/signal are \0-terminated bytestrings" - and auto-append/auto-strip \0 if it's present.

Whatever we choose, the solution should be agreed upon by authors of bindings for all languages. That's why I'm here.

Do you have any experience with "ay"-encoded bytestrings?

Relevant discussion: LEW21/pydbus#27

Distinguish between missing args and bad arg types using get*() methods.

Is there a recommended way to do this?

I think that the get*() methods themselves do not distinguish; they return None if the arg is missing or has the wrong type.

I've come up with an approach that looks something like this:

    let message: &Message = m.msg;
    let item: MessageItem = try!(message.get1().ok_or_else(MethodErr::no_arg));
    let name: &str = try!(message.get1().ok_or_else(|| MethodErr::invalid_arg(&item)));
    ...

The results I get are nice and distinguish between the two situatons:

[mulhern@dhcp-25-209 stratisd]$ busctl --user call org.storage.stratis1 /org/storage/stratis1 org.storage.stratis1.Manager DestroyPool
Not enough arguments
[mulhern@dhcp-25-209 stratisd]$ busctl --user call org.storage.stratis1 /org/storage/stratis1 org.storage.stratis1.Manager DestroyPool i 2
Invalid argument Int32(2)
[mulhern@dhcp-25-209 stratisd]$ busctl --user call org.storage.stratis1 /org/storage/stratis1 org.storage.stratis1.Manager DestroyPool s name
qs 0 "Ok"

Notice, though, how I have to call get1() twice, one to detect if the argument is there at all, and once to detect if the item has the correct type. Should some one in need of this amount of specificity be doing something different?

There is another approach that just considers the entire message an invalid arg, that yields results something like this, if the message has too few args or if the args are ill-typed:

[mulhern@dhcp-25-209 stratisd]$ busctl --user call org.storage.stratis1 /org/storage/stratis1 org.storage.stratis1.Manager DestroyPool i 2
Invalid argument [Int32(2)]
[mulhern@dhcp-25-209 stratisd]$ busctl --user call org.storage.stratis1 /org/storage/stratis1 org.storage.stratis1.Manager DestroyPool
Invalid argument []
[mulhern@dhcp-25-209 stratisd]$ busctl --user call org.storage.stratis1 /org/storage/stratis1 org.storage.stratis1.Manager DestroyPool s name
qs 0 "Ok"

It is implemented kind of like this:

    let message: &Message = m.msg;
    let name: &str = try!(message.get1().ok_or_else(|| MethodErr::invalid_arg(&message.get_items())));
    ...

Thanks for any help you can give.

The trait bound `dbus::arg::Get` is not satisfied

I am trying to use this library to get connection info from NetworkManager using the GetSettings method. I used D-Feet to try out the function which has a signature of GetSettings() -> (Dict of {String, Dict of {String, Variant} } settings), the data returned by D-Feet is below:

{'802-11-wireless': {'mac-address': [228, 179, 24, 77, 64, 139],
                     'mac-address-blacklist': [],
                     'mode': 'infrastructure',
                     'security': '802-11-wireless-security',
                     'seen-bssids': ['02:1D:AA:80:1B:DA', '02:1D:AA:80:1D:12'],
                     'ssid': [80,
                              108,
                              111,
                              117,
                              103,
                              104,
                              32,
                              87,
                              97,
                              121,
                              32,
                              67,
                              97,
                              102,
                              101]},
 '802-11-wireless-security': {'auth-alg': 'open',
                              'group': [],
                              'key-mgmt': 'wpa-psk',
                              'pairwise': [],
                              'proto': []},
 'connection': {'id': 'Plough Way Cafe',
                'permissions': [],
                'secondaries': [],
                'timestamp': 1479304123,
                'type': '802-11-wireless',
                'uuid': 'ff9b7028-0911-491a-bfe8-53cba76069da'},
 'ipv4': {'address-data': [],
          'addresses': [],
          'dns': [],
          'dns-search': [],
          'method': 'auto',
          'route-data': [],
          'routes': []},
 'ipv6': {'address-data': [],
          'addresses': [],
          'dns': [],
          'dns-search': [],
          'method': 'auto',
          'route-data': [],
          'routes': []}}

and my code:

extern crate dbus;

fn main() {
    let message = dbus::Message::new_method_call("org.freedesktop.NetworkManager",
                                                 "/org/freedesktop/NetworkManager/Settings/0",
                                                 "org.freedesktop.NetworkManager.Settings.\
                                                  Connection",
                                                 "GetSettings")
        .unwrap();

    let response = dbus::Connection::get_private(dbus::BusType::System)
        .unwrap()
        .send_with_reply_and_block(message, 2000)
        .unwrap();

    println!("{:?}", response);

    let test: dbus::arg::Dict<&str, dbus::arg::Dict<&str, dbus::arg::Variant<()>, _>, _> =
        response.get1().unwrap();

    println!("{:?}", test);
}

which results in this error:

error[E0277]: the trait bound `(): dbus::arg::Get<'_>` is not satisfied
  --> src/main.rs:20:18
   |
20 |         response.get1().unwrap();
   |                  ^^^^ the trait `dbus::arg::Get<'_>` is not implemented for `()`
   |
   = note: required because of the requirements on the impl of `dbus::arg::Get<'_>` for `dbus::arg::Variant<()>`
   = note: required because of the requirements on the impl of `dbus::arg::Get<'_>` for `dbus::arg::Dict<'_, &str, dbus::arg::Variant<()>, dbus::arg::Iter<'_>>`
   = note: required because of the requirements on the impl of `dbus::arg::Get<'_>` for `dbus::arg::Dict<'_, &str, dbus::arg::Dict<'_, &str, dbus::arg::Variant<()>, dbus::arg::Iter<'_>>,     dbus::arg::Iter<'_>>`

How can I get the connection info?

I thought the whole point of Variant is that it can hold different types of data? What am I doing wrong?

If I substitute the Variant type () with &str it prints out Dict(Iter("Unknown?!", "Unknown?!", "Unknown?!", "Unknown?!", "Unknown?!"), PhantomData). What is the Unknown?! value?

The API for Dict also states

Creates a new Dict from an iterator. The iterator is consumed when appended.

How/should I use this instead?

UPDATE

I have managed to make some progress, perhaps naively?

My code now looks like this:

extern crate dbus;
extern crate network_manager;

#[derive(Default, Debug)]
struct Connection {
    path: String,
    id: String,
    uuid: String,
    ssid: String,
    interface: String,
    security: String,
    psk: String, // Only used when creating a new connection
}

fn main() {
    let connection = Connection {
        path: "/org/freedesktop/NetworkManager/Settings/0".to_string(),
        ..Default::default()
    };

    let message = dbus::Message::new_method_call("org.freedesktop.NetworkManager",
                                                 connection.path.clone(),
                                                 "org.freedesktop.NetworkManager.Settings.\
                                                  Connection",
                                                 "GetSettings")
        .unwrap();

    let response = dbus::Connection::get_private(dbus::BusType::System)
        .unwrap()
        .send_with_reply_and_block(message, 2000)
        .unwrap();

    let mut outer_array_iter = response.iter_init().recurse(97).unwrap();
    loop {
        let mut outer_dict_iter = outer_array_iter.recurse(101).unwrap();
        outer_dict_iter.next();

        let mut inner_array_iter = outer_dict_iter.recurse(97).unwrap();
        loop {
            let mut inner_dict_iter = inner_array_iter.recurse(101).unwrap();

            let key = inner_dict_iter.read::<&str>().unwrap();
            match key {
                "id" => {
                    let val: dbus::arg::Variant<&str> = inner_dict_iter.read().unwrap();
                    println!("id {:?}", val);
                }
                "uuid" => {
                    let val: dbus::arg::Variant<&str> = inner_dict_iter.read().unwrap();
                    println!("uuid {:?}", val);
                }
                "ssid" => {
                    let val: dbus::arg::Variant<dbus::arg::Array<i32, _>> = inner_dict_iter.read()
                        .unwrap();
                    println!("ssid {:?}", val);
                }
                "type" => {
                    let val: dbus::arg::Variant<&str> = inner_dict_iter.read().unwrap();
                    println!("interface {:?}", val);
                }
                "security" => {
                    let val: dbus::arg::Variant<&str> = inner_dict_iter.read().unwrap();
                    println!("security {:?}", val);
                }
                _ => (),
            }

            if !(inner_array_iter.next()) {
                break;
            }
        }

        if !(outer_array_iter.next()) {
            break;
        }
    }

    println!("{:?}", connection);
}

this prints out:

id Variant("Plough Way Cafe")
uuid Variant("e078808e-626f-4be9-bbb4-5e48b1d626de")
interface Variant("802-11-wireless")
ssid Variant(Array(Iter("u8", "u8", "u8", "u8", "u8", "u8", "u8", "u8"), PhantomData))
security Variant("802-11-wireless-security")
Connection { path: "/org/freedesktop/NetworkManager/Settings/0", id: "", uuid: "", ssid: "", interface: "", security: "", psk: "" }

How can I get the data out of Variant and into my connection struct?

Is there a better way to use iterators as this feels v.fragile?

Thanks

Handling adding and removing object paths from a single tree

Hiya,

We're still stuck on the issues raised by #40. We want the good stuff a tree provides (introspection, object manager, method dispatch) and also be able to add and remove object paths. This is important because we want to have our DBus interface create and remove objects and interfaces at runtime, and it's currently not possible, although we keep coming back to this as a natural way to want to design an API.

One easy thing would be to Add Tree::add_o_path() to tree/objectpath.rs Tree. This makes it possible to add an objectpath to the tree from a tree's method (although this requires an unsafe conversion of &m.tree to a &mut m.tree, it's a least possible) (This should not cause issues as long as it's always a different ObjectPath we're adding or removing than the objectpath/interface our method was invoked on)

Thinking longer-term, I'm wondering how hard it would be to make MethodInfo::tree a mutable ref (I tried it, 'as blossomed everywhere and I gave up, but you might have more luck) Or, I noticed that the only users of MethodInfo::tree are introspection and managed_objects, that call tree::children(), which then filters for children within the object path -- could there be a more distributed method of iterating and looking up object paths that would not require the entire &Tree? If so then an objectpath's method could be called without referencing the tree, and enclosing Tree in Rc<RefCell>> would let us close over and modify the tree without unsafe.

cc @tasleson @trgill @mulkieran

Documentation for Signals and Server-Side Properties

While writing an application making quite a bit of use of dbus i realized nowhere is documented how to use signals. Furthermore it is not documented how a server might implement properties. The rustdoc documentation is not really useful. Both of those are fairly important features of dbus, so documentation should be added.

tokio integration

It would be nice if it was easier to use this dbus library in an async fashion.

ObjectManager support

Don't know how much work this would be, but just wanted to open this issue to indicate it is desired 😄

Process requests asynchonously

I have requests that take a while until they are processed and a response can be given.
AFAIK, you would have to spawn a new process for each request to keep the dbus interface responsive while processing one request, so something like

            for n in conn.iter(1000) {
                    thread::spawn(|| {
                            match n {
                                    ConnectionItem::MethodCall(mut m) => {
                                                    o.handle_message(&mut m);
                                    },
                                    _ => (),
                            }
                    });
            }

However, n cannot be sent to another thread:

src/dbus_service.rs:51:4: 51:17 error: the trait `core::marker::Send` is not implemented for the type `alloc::rc::Rc<dbus::objpath::IObjectPath<'_>>` [E0277]
src/dbus_service.rs:51          thread::spawn(|| {
                                ^~~~~~~~~~~~~
note: in expansion of for loop expansion
src/dbus_service.rs:50:3: 59:4 note: expansion site
src/dbus_service.rs:51:4: 51:17 note: `alloc::rc::Rc<dbus::objpath::IObjectPath<'_>>` cannot be sent between threads safely
src/dbus_service.rs:51          thread::spawn(|| {
                                ^~~~~~~~~~~~~
note: in expansion of for loop expansion
src/dbus_service.rs:50:3: 59:4 note: expansion site
src/dbus_service.rs:51:4: 51:17 error: the trait `core::marker::Sync` is not implemented for the type `*mut libc::types::common::c95::c_void` [E0277]
src/dbus_service.rs:51          thread::spawn(|| {
                                ^~~~~~~~~~~~~
note: in expansion of for loop expansion
src/dbus_service.rs:50:3: 59:4 note: expansion site
src/dbus_service.rs:51:4: 51:17 note: `*mut libc::types::common::c95::c_void` cannot be shared between threads safely
src/dbus_service.rs:51          thread::spawn(|| {
                                ^~~~~~~~~~~~~
note: in expansion of for loop expansion
src/dbus_service.rs:50:3: 59:4 note: expansion site
error: aborting due to 2 previous errors

Is there a way to fix this?

question: is this dbus signal handling code idiomatic?

I’m prototyping a program which communicates with Avahi via dbus. Avahi sends signals for newly discovered services, so my code looks like this:

extern crate dbus;

#[derive(Debug)]
struct ServiceBrowserItemNew {
    interface: i32,
    protocol: i32,
    name: String,
    item_type: String,
    domain: String,
    flags: u32,
}

fn service_browser_item_new_msg(m: &dbus::Message) -> Option<ServiceBrowserItemNew> {
    let mut iter = m.iter_init();
    let interface = iter.get::<i32>().unwrap();

    assert!(iter.next());
    let protocol = iter.get::<i32>().unwrap();

    assert!(iter.next());
    let name = iter.get::<&str>().unwrap().to_string();

    assert!(iter.next());
    let item_type = iter.get::<&str>().unwrap().to_string();

    assert!(iter.next());
    let domain = iter.get::<&str>().unwrap().to_string();

    assert!(iter.next());
    let flags = iter.get::<u32>().unwrap();

    Some(ServiceBrowserItemNew {
        interface: interface,
        protocol: protocol,
        name: name,
        item_type: item_type,
        domain: domain,
        flags: flags,
    })
}
fn focus_msg(ci: &dbus::ConnectionItem) -> Option<ServiceBrowserItemNew> {
    let m = if let &dbus::ConnectionItem::Signal(ref s) = ci {
        s
    } else {
        return None;
    };

    if &*m.interface().unwrap() == "org.freedesktop.Avahi.ServiceBrowser" &&
       &*m.member().unwrap() == "ItemNew" {
        return service_browser_item_new_msg(m);
    }

    None
}

fn main() {
    let c = dbus::Connection::get_private(dbus::BusType::System).unwrap();
    let sbn = dbus::Message::new_method_call("org.freedesktop.Avahi",
                                             "/",
                                             "org.freedesktop.Avahi.Server",
                                             "ServiceBrowserNew").unwrap()
    .append1(-1i32) // interface: AVAHI_IF_UNSPEC
    .append1(-1i32) // protocol: AVAHI_PROTO_UNSPEC (ipv4+ipv6)
    .append1("_googlecast._tcp") // type
    .append1("") // TODO: is "" == null?
    .append1(0u32); // flags: 0

    let r = c.send_with_reply_and_block(sbn, 2000).unwrap();
    let path: dbus::Path = r.get1().unwrap();
    println!("returned path = {}", path);

    c.add_match("interface='org.freedesktop.Avahi'").unwrap();

    for i in c.iter(1000) {
        if let Some(app) = focus_msg(&i) {
            // e.g. ServiceBrowserItemNew { interface: 3, protocol: 0,
            // name: "Chromecast", item_type: "_googlecast._tcp", domain: "local", flags: 5 }
            println!("got a message: {:?}", app);
        } else {
            println!("got message which i do not understand");
        }
    }
}

The signal decoding part seems pretty cumbersome to me. I’m new to Rust, so it’s pretty likely that I’m missing something, hence I figured I’d ask.

In Go, I can imagine a design using reflection and tags (like JSON and XML decoding work):

type ServiceBrowserItemNew struct {
  Interface int32 `dbus:"1"`
  Protocol  int32 `dbus:"2"`
  // …
}

func main() {
  // …
  for {
    msg := <-conn.Items()
    if msg.Interface == "org.freedesktop.Avahi.ServiceBrowser" && msg.Member == "ItemNew" {
      var sbin ServiceBrowserItemNew
      if err := msg.Unmarshal(&sbin); err != nil {
        log.Fatal(err)
      }
      // …
    }
  }
}

Is something similar possible in Rust with this dbus library? Or is iterating through the individual message arguments really the idiomatic way?

Props doesn't work with arg

Props returns MessageItem, so one can't use dbus::arg::Array and friends, which I thought was recommended over MessageItem these days?

MessageItem::Array can have invalid typesig

I'm not happy with the design of MessageItem::Array, since it is possible to have an array that does not follow the type signature. However, fixing this would be a backwards incompatible change.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.