From 0439a1e8dbad94f07724ab1a750db35192504473 Mon Sep 17 00:00:00 2001 From: "Harry T. Vennik" Date: Sun, 4 Jun 2017 18:00:25 +0200 Subject: [PATCH 1/4] Added support for object path type --- source/ddbus/conv.d | 16 ++++++++++++++-- source/ddbus/thin.d | 39 +++++++++++++++++++++++++++++++++++++++ source/ddbus/util.d | 5 ++++- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/source/ddbus/conv.d b/source/ddbus/conv.d index 9b07c4b..dab1628 100644 --- a/source/ddbus/conv.d +++ b/source/ddbus/conv.d @@ -14,6 +14,9 @@ void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) { static if(is(T == string)) { immutable(char)* cStr = arg.toStringz(); dbus_message_iter_append_basic(iter,typeCode!T,&cStr); + } else static if(is(T == ObjectPath)) { + immutable(char)* cStr = arg.toString().toStringz(); + dbus_message_iter_append_basic(iter,typeCode!T,&cStr); } else static if(is(T==bool)) { dbus_bool_t longerBool = arg; // dbus bools are ints dbus_message_iter_append_basic(iter,typeCode!T,&longerBool); @@ -71,6 +74,8 @@ void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) { dbus_message_iter_open_container(iter, 'v', sig.ptr, sub); if(val.type == 's') { buildIter(sub, val.str); + } else if(val.type == 'o') { + buildIter(sub, val.obj); } else if(val.type == 'b') { buildIter(sub,val.boolean); } else if(dbus_type_is_basic(val.type)) { @@ -136,10 +141,14 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!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)) { + static if(is(T==string) || is(T==ObjectPath)) { const(char)* cStr; dbus_message_iter_get_basic(iter, &cStr); - ret = cStr.fromStringz().idup; // copy string + string str = cStr.fromStringz().idup; // copy string + static if(is(T==string)) + ret = str; + else + ret = ObjectPath(str); } else static if(is(T==bool)) { dbus_bool_t longerBool; dbus_message_iter_get_basic(iter, &longerBool); @@ -183,6 +192,9 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) { if(ret.type == 's') { ret.str = readIter!string(iter); return ret; + } else if(ret.type == 'o') { + ret.obj = readIter!ObjectPath(iter); + return ret; } else if(ret.type == 'b') { ret.boolean = readIter!bool(iter); return ret; diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index b0c5da3..667bd37 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -30,6 +30,28 @@ T wrapErrors(T)(T delegate(DBusError *err) del) { return ret; } +struct ObjectPath { + private string _value; + + this(string objPath) { + enforce(_isValid(objPath)); + _value = objPath; + } + + string toString() const { + return _value; + } + + bool opEquals(const ObjectPath b) const { + return _value == b._value; + } + + private static bool _isValid(string objPath) { + import std.regex : matchFirst, ctRegex; + return cast(bool) objPath.matchFirst(ctRegex!("^((/[0-9A-Za-z_]+)+|/)$")); + } +} + /// Structure allowing typeless parameters struct DBusAny { /// DBus type of the value (never 'v'), see typeSig!T @@ -63,6 +85,8 @@ struct DBusAny { /// bool boolean; /// + ObjectPath obj; + /// DBusAny[] array; /// DBusAny[] tuple; @@ -112,6 +136,9 @@ struct DBusAny { } else static if(is(T == bool)) { this(typeCode!bool, null, false); boolean = cast(bool) value; + } else static if(is(T == ObjectPath)) { + this(typeCode!ObjectPath, null, false); + obj = value; } else static if(is(T == Variant!R, R)) { static if(is(R == DBusAny)) { type = value.data.type; @@ -207,6 +234,9 @@ struct DBusAny { case typeCode!string: valueStr = '"' ~ str ~ '"'; break; + case typeCode!ObjectPath: + valueStr = '"' ~ obj.to!string ~ '"'; + break; case typeCode!bool: valueStr = boolean ? "true" : "false"; break; @@ -285,6 +315,13 @@ struct DBusAny { } else static if(isSomeString!T) { if(type == 's') return str.to!T; + else if(type == 'o') + return obj.toString(); + else + throw new Exception("Can't convert type " ~ cast(char) type ~ " to " ~ T.stringof); + } else static if(is(T == ObjectPath)) { + if(type == 'o') + return obj; else throw new Exception("Can't convert type " ~ cast(char) type ~ " to " ~ T.stringof); } else static if(isDynamicArray!T) { @@ -332,6 +369,8 @@ struct DBusAny { return tuple == b.tuple; else if(type == 's') return str == b.str; + else if(type == 'o') + return obj == b.obj; else if(type == 'e') return entry == b.entry || (entry && b.entry && *entry == *b.entry); else diff --git a/source/ddbus/util.d b/source/ddbus/util.d index 8f6a506..2754063 100644 --- a/source/ddbus/util.d +++ b/source/ddbus/util.d @@ -44,7 +44,8 @@ template allCanDBus(TS...) { template basicDBus(T) { static if(is(T == byte) || is(T == short) || is (T == ushort) || is (T == int) || is (T == uint) || is (T == long) || is (T == ulong) - || is (T == double) || is (T == string) || is(T == bool)) { + || is (T == double) || is (T == string) || is(T == bool) + || is (T == ObjectPath)) { enum basicDBus = true; } else { enum basicDBus = false; @@ -101,6 +102,8 @@ string typeSig(T)() if(canDBus!T) { return "d"; } else static if(is(T == string)) { return "s"; + } else static if(is(T == ObjectPath)) { + return "o"; } else static if(isVariant!T) { return "v"; } else static if(is(T == DBusAny)) { From 884b31fa9f1b7380730c570760b9d5b5b3586e37 Mon Sep 17 00:00:00 2001 From: "Harry T. Vennik" Date: Sun, 25 Jun 2017 17:00:55 +0200 Subject: [PATCH 2/4] Added toHash function for usage of ObjectPath as KeyType in AAs --- source/ddbus/thin.d | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index 667bd37..ed64073 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -42,6 +42,10 @@ struct ObjectPath { return _value; } + size_t toHash() const pure nothrow @trusted { + return hashOf(_value); + } + bool opEquals(const ObjectPath b) const { return _value == b._value; } From 7e46fb64013110d75c6cd1b448bbe1dbb073dbbd Mon Sep 17 00:00:00 2001 From: "Harry T. Vennik" Date: Sun, 25 Jun 2017 17:01:59 +0200 Subject: [PATCH 3/4] Fixup opEquals method signature to match D specification --- source/ddbus/thin.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index ed64073..944f3df 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -46,7 +46,7 @@ struct ObjectPath { return hashOf(_value); } - bool opEquals(const ObjectPath b) const { + bool opEquals(ref const typeof(this) b) const pure nothrow @safe { return _value == b._value; } From 16efa3a6c38372c044b4d03be7041be9f14ac203 Mon Sep 17 00:00:00 2001 From: "Harry T. Vennik" Date: Sun, 25 Jun 2017 18:30:34 +0200 Subject: [PATCH 4/4] Add unittest for ObjectPath --- source/ddbus/thin.d | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index 944f3df..3268c6b 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -56,6 +56,17 @@ struct ObjectPath { } } +unittest { + import dunit.toolkit; + + ObjectPath("some.invalid/object_path").assertThrow(); + ObjectPath("/path/with/TrailingSlash/").assertThrow(); + string path = "/org/freedesktop/DBus"; + auto obj = ObjectPath(path); + obj.toString().assertEqual(path); + obj.toHash().assertEqual(path.hashOf); +} + /// Structure allowing typeless parameters struct DBusAny { /// DBus type of the value (never 'v'), see typeSig!T