Merge pull request #18 from trishume/ddbus/enhancement/exceptions
Error handling improvements
This commit is contained in:
commit
547705ae11
|
@ -11,7 +11,7 @@ It currently supports:
|
||||||
|
|
||||||
- Calling methods
|
- Calling methods
|
||||||
- Creating wrapper objects for DBus interfaces
|
- 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)
|
- Handling method calls and signals (includes introspection support)
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
@ -130,6 +130,7 @@ msg.readTuple!(typeof(args))().assertEqual(args);
|
||||||
- `simple`: simpler wrappers around other functionality.
|
- `simple`: simpler wrappers around other functionality.
|
||||||
- `conv`: low level type marshaling methods.
|
- `conv`: low level type marshaling methods.
|
||||||
- `util`: templates for working with D type marshaling like `canDBus!T`.
|
- `util`: templates for working with D type marshaling like `canDBus!T`.
|
||||||
|
- `exception`: exception classes
|
||||||
- `c_lib`: a D translation of the DBus C headers.
|
- `c_lib`: a D translation of the DBus C headers.
|
||||||
|
|
||||||
Importing `ddbus` publicly imports the `thin`,`router`,`bus` and `simple` modules.
|
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:
|
`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.
|
- 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.
|
- 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.
|
Pull requests are welcome, the codebase is pretty small and other than the template metaprogramming for type marshaling is fairly straightforward.
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
module ddbus.conv;
|
module ddbus.conv;
|
||||||
|
|
||||||
import ddbus.c_lib;
|
import ddbus.c_lib;
|
||||||
|
import ddbus.exception : TypeMismatchException;
|
||||||
import ddbus.util;
|
import ddbus.util;
|
||||||
import ddbus.thin;
|
import ddbus.thin;
|
||||||
|
import std.exception : enforce;
|
||||||
import std.string;
|
import std.string;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
import std.range;
|
import std.range;
|
||||||
|
@ -134,12 +136,10 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static if(isTuple!T) {
|
static if(!is(T == DBusAny) && !is(T == Variant!DBusAny)) {
|
||||||
assert(dbus_message_iter_get_arg_type(iter) == 'r');
|
auto argType = dbus_message_iter_get_arg_type(iter);
|
||||||
} else static if(is(T == DictionaryEntry!(K1, V1), K1, V1)) {
|
enforce(argType == typeCode!T(),
|
||||||
assert(dbus_message_iter_get_arg_type(iter) == 'e');
|
new TypeMismatchException(argType, typeCode!T()));
|
||||||
} else static if(!is(T == DBusAny) && !is(T == Variant!DBusAny)) {
|
|
||||||
assert(dbus_message_iter_get_arg_type(iter) == typeCode!T());
|
|
||||||
}
|
}
|
||||||
static if(is(T==string) || is(T==ObjectPath)) {
|
static if(is(T==string) || is(T==ObjectPath)) {
|
||||||
const(char)* cStr;
|
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);
|
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.build(args.expand);
|
||||||
msg.signature().assertEqual("ibsvai(diaasabv)a{ss}tv");
|
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);
|
msg.readTuple!(typeof(args))().assertEqual(args);
|
||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
dbus_message_iter_init(msg.msg, &iter);
|
dbus_message_iter_init(msg.msg, &iter);
|
||||||
|
|
66
source/ddbus/exception.d
Normal file
66
source/ddbus/exception.d
Normal 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;
|
||||||
|
}
|
|
@ -12,23 +12,8 @@ import std.conv;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.algorithm;
|
import std.algorithm;
|
||||||
|
|
||||||
class DBusException : Exception {
|
// This import is public for backwards compatibility
|
||||||
this(DBusError *err) {
|
public import ddbus.exception : wrapErrors, DBusException;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ObjectPath {
|
struct ObjectPath {
|
||||||
private string _value;
|
private string _value;
|
||||||
|
|
Loading…
Reference in a new issue