From 12b3b61c1b2e535191d3a9d5583f416e3cad50bd Mon Sep 17 00:00:00 2001 From: "Harry T. Vennik" Date: Sat, 8 Jul 2017 15:56:31 +0200 Subject: [PATCH 1/3] Move DBusException and wrapErrors to separate module Also improved its implemention. This prepares for new exception types to be added in later commits. --- source/ddbus/exception.d | 37 +++++++++++++++++++++++++++++++++++++ source/ddbus/thin.d | 19 ++----------------- 2 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 source/ddbus/exception.d diff --git a/source/ddbus/exception.d b/source/ddbus/exception.d new file mode 100644 index 0000000..e6e25d3 --- /dev/null +++ b/source/ddbus/exception.d @@ -0,0 +1,37 @@ +module ddbus.exception; + +import ddbus.c_lib; + +package T wrapErrors(T)( + T delegate(DBusError *err) del, + string file = __FILE__, + size_t line = __LINE__, + Throwable next = null +) { + DBusError error; + dbus_error_init(&error); + T ret = del(&error); + if(dbus_error_is_set(&error)) { + auto ex = new DBusException(&error, file, line, next); + dbus_error_free(&error); + throw ex; + } + return ret; +} + +/++ + Thrown when a DBus error code was returned by libdbus. ++/ +class DBusException : Exception { + private this( + scope DBusError *err, + string file = __FILE__, + size_t line = __LINE__, + Throwable next = null + ) pure nothrow { + import std.string : fromStringz; + + super(err.message.fromStringz().idup, file, line, next); + } +} + diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index 3268c6b..de60eba 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -12,23 +12,8 @@ import std.conv; import std.range; import std.algorithm; -class DBusException : Exception { - this(DBusError *err) { - super(err.message.fromStringz().idup); - } -} - -T wrapErrors(T)(T delegate(DBusError *err) del) { - DBusError error; - dbus_error_init(&error); - T ret = del(&error); - if(dbus_error_is_set(&error)) { - auto ex = new DBusException(&error); - dbus_error_free(&error); - throw ex; - } - return ret; -} +// This import is public for backwards compatibility +public import ddbus.exception : wrapErrors, DBusException; struct ObjectPath { private string _value; From 1690e2cfd8f2959ec0af563baef1d74dc66fe055 Mon Sep 17 00:00:00 2001 From: "Harry T. Vennik" Date: Sun, 9 Jul 2017 19:20:28 +0200 Subject: [PATCH 2/3] Gracefully handle unexpected types when reading a message. --- source/ddbus/conv.d | 17 +++++++++++------ source/ddbus/exception.d | 29 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/source/ddbus/conv.d b/source/ddbus/conv.d index dab1628..d75425e 100644 --- a/source/ddbus/conv.d +++ b/source/ddbus/conv.d @@ -1,8 +1,10 @@ module ddbus.conv; import ddbus.c_lib; +import ddbus.exception : TypeMismatchException; import ddbus.util; import ddbus.thin; +import std.exception : enforce; import std.string; import std.typecons; import std.range; @@ -134,12 +136,10 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) { return ret; } } - static if(isTuple!T) { - assert(dbus_message_iter_get_arg_type(iter) == 'r'); - } else static if(is(T == DictionaryEntry!(K1, V1), K1, V1)) { - assert(dbus_message_iter_get_arg_type(iter) == 'e'); - } else static if(!is(T == DBusAny) && !is(T == Variant!DBusAny)) { - assert(dbus_message_iter_get_arg_type(iter) == typeCode!T()); + static if(!is(T == DBusAny) && !is(T == Variant!DBusAny)) { + auto argType = dbus_message_iter_get_arg_type(iter); + enforce(argType == typeCode!T(), + new TypeMismatchException(argType, typeCode!T())); } static if(is(T==string) || is(T==ObjectPath)) { const(char)* cStr; @@ -272,6 +272,11 @@ unittest { auto args = tuple(5,true,"wow",var(5.9),[6,5],tuple(6.2,4,[["lol"]],emptyB,var([4,2])),map,anyVar,complexVar); msg.build(args.expand); msg.signature().assertEqual("ibsvai(diaasabv)a{ss}tv"); + + msg.read!string().assertThrow!TypeMismatchException(); + msg.readTuple!(Tuple!(int, bool, double)).assertThrow!TypeMismatchException(); + msg.readTuple!(Tuple!(int, bool, string, double)).assertEqual(tuple(5,true,"wow", 5.9)); + msg.readTuple!(typeof(args))().assertEqual(args); DBusMessageIter iter; dbus_message_iter_init(msg.msg, &iter); diff --git a/source/ddbus/exception.d b/source/ddbus/exception.d index e6e25d3..7e80bc1 100644 --- a/source/ddbus/exception.d +++ b/source/ddbus/exception.d @@ -35,3 +35,32 @@ class DBusException : Exception { } } +/++ + Thrown when the signature of a message does not match the requested types. ++/ +class TypeMismatchException : Exception { + package this( + int expectedType, + int actualType, + string file = __FILE__, + size_t line = __LINE__, + Throwable next = null + ) pure nothrow @safe { + _expectedType = expectedType; + _actualType = actualType; + super("The type of value at the current position in the message does not match the type of value to be read." + ~ " Expected: " ~ cast(char) expectedType ~ ", Got: " ~ cast(char) actualType); + } + + int expectedType() @property pure const nothrow @nogc { + return _expectedType; + } + + int actualType() @property pure const nothrow @nogc { + return _actualType; + } + + private: + int _expectedType; + int _actualType; +} From 9d54d41df4956bc24e86ef123a33582e13bd9737 Mon Sep 17 00:00:00 2001 From: thaven Date: Mon, 10 Jul 2017 11:55:13 +0200 Subject: [PATCH 3/3] Update Readme.md - Added `exception` module - Corrected typo - Removed DBus path support from TODO (already in master) --- Readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index af4c9f0..a37e0ac 100644 --- a/Readme.md +++ b/Readme.md @@ -11,7 +11,7 @@ It currently supports: - Calling methods - Creating wrapper objects for DBus interfaces -- Seamlessly converting too and from D types +- Seamlessly converting to and from D types - Handling method calls and signals (includes introspection support) # Installation @@ -130,6 +130,7 @@ msg.readTuple!(typeof(args))().assertEqual(args); - `simple`: simpler wrappers around other functionality. - `conv`: low level type marshaling methods. - `util`: templates for working with D type marshaling like `canDBus!T`. +- `exception`: exception classes - `c_lib`: a D translation of the DBus C headers. Importing `ddbus` publicly imports the `thin`,`router`,`bus` and `simple` modules. @@ -169,7 +170,7 @@ It would be better to watch a file descriptor asynchronously in the event loop i `ddbus` should be complete for everyday use but is missing some fanciness that it easily could and should have: - Support for adding file descriptors to event loops like vibe.d so that it only wakes up when messages arrive and not on a timer. -- Marshaling of DBus path and file descriptor objects +- Marshaling of file descriptor objects - Better efficiency in some places, particularly the object wrapping allocates tons of delegates for every method. Pull requests are welcome, the codebase is pretty small and other than the template metaprogramming for type marshaling is fairly straightforward.