Merge pull request #18 from trishume/ddbus/enhancement/exceptions

Error handling improvements
This commit is contained in:
Tristan Hume 2017-07-10 10:53:17 -07:00 committed by GitHub
commit 547705ae11
4 changed files with 82 additions and 25 deletions

View file

@ -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.

View file

@ -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);

66
source/ddbus/exception.d Normal file
View file

@ -0,0 +1,66 @@
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);
}
}
/++
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;
}

View file

@ -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;