Merge pull request #12 from WebFreak001/any-types

Memory & performance optimization for ubyte[]
This commit is contained in:
Tristan Hume 2017-04-23 15:07:57 -04:00 committed by GitHub
commit ec2d957ad8
2 changed files with 49 additions and 12 deletions

View file

@ -60,8 +60,12 @@ void buildIter(TS...)(DBusMessageIter *iter, TS args) if(allCanDBus!TS) {
} else if(val.type == 'a') { } else if(val.type == 'a') {
DBusMessageIter arr; DBusMessageIter arr;
dbus_message_iter_open_container(sub, 'a', sig[1 .. $].ptr, &arr); dbus_message_iter_open_container(sub, 'a', sig[1 .. $].ptr, &arr);
foreach(item; val.array) if (val.signature == ['y'])
buildIter(&arr, item); foreach (item; val.binaryData)
dbus_message_iter_append_basic(&arr, 'y', &item);
else
foreach(item; val.array)
buildIter(&arr, item);
dbus_message_iter_close_container(sub, &arr); dbus_message_iter_close_container(sub, &arr);
} else if(val.type == 'r') { } else if(val.type == 'r') {
DBusMessageIter arr; DBusMessageIter arr;
@ -170,9 +174,18 @@ T readIter(T)(DBusMessageIter *iter) if (canDBus!T) {
auto sig = dbus_message_iter_get_signature(&sub); auto sig = dbus_message_iter_get_signature(&sub);
ret.signature = sig.fromStringz.dup; ret.signature = sig.fromStringz.dup;
dbus_free(sig); dbus_free(sig);
while(dbus_message_iter_get_arg_type(&sub) != 0) { if (ret.signature == ['y'])
ret.array ~= readIter!DBusAny(&sub); while(dbus_message_iter_get_arg_type(&sub) != 0) {
} ubyte b;
assert(dbus_message_iter_get_arg_type(&sub) == 'y');
dbus_message_iter_get_basic(&sub, &b);
dbus_message_iter_next(&sub);
ret.binaryData ~= b;
}
else
while(dbus_message_iter_get_arg_type(&sub) != 0) {
ret.array ~= readIter!DBusAny(&sub);
}
} else if(ret.type == 'r') { } else if(ret.type == 'r') {
auto sig = dbus_message_iter_get_signature(iter); auto sig = dbus_message_iter_get_signature(iter);
ret.signature = sig.fromStringz.dup; ret.signature = sig.fromStringz.dup;
@ -218,7 +231,8 @@ unittest {
Variant!DBusAny complexVar = variant(DBusAny([ Variant!DBusAny complexVar = variant(DBusAny([
"hello world": variant(DBusAny(1337)), "hello world": variant(DBusAny(1337)),
"array value": variant(DBusAny([42, 64])), "array value": variant(DBusAny([42, 64])),
"tuple value": variant(tupleMember) "tuple value": variant(tupleMember),
"optimized binary data": variant(DBusAny(cast(ubyte[]) [1, 2, 3, 4, 5, 6]))
])); ]));
complexVar.data.type.assertEqual('a'); complexVar.data.type.assertEqual('a');
complexVar.data.signature.assertEqual("{sv}".dup); complexVar.data.signature.assertEqual("{sv}".dup);

View file

@ -68,6 +68,8 @@ struct DBusAny {
DBusAny[] tuple; DBusAny[] tuple;
/// ///
DictionaryEntry!(DBusAny, DBusAny)* entry; DictionaryEntry!(DBusAny, DBusAny)* entry;
///
ubyte[] binaryData;
} }
/// Manually creates a DBusAny object using a type, signature and implicit specifier. /// Manually creates a DBusAny object using a type, signature and implicit specifier.
@ -115,9 +117,12 @@ struct DBusAny {
type = value.data.type; type = value.data.type;
signature = value.data.signature; signature = value.data.signature;
explicitVariant = true; explicitVariant = true;
if(type == 'a' || type == 'r') if(type == 'a' || type == 'r') {
array = value.data.array; if(signature == ['y'])
if(type == 's') binaryData = value.data.binaryData;
else
array = value.data.array;
} else if(type == 's')
str = value.data.str; str = value.data.str;
else if(type == 'e') else if(type == 'e')
entry = value.data.entry; entry = value.data.entry;
@ -138,9 +143,13 @@ struct DBusAny {
entry.value = value.value; entry.value = value.value;
else else
entry.value = DBusAny(value.value); entry.value = DBusAny(value.value);
} else static if(is(T == ubyte[]) || is(T == byte[])) {
this('a', ['y'], false);
binaryData = cast(ubyte[]) value;
} else static if(isInputRange!T) { } else static if(isInputRange!T) {
this.type = 'a'; this.type = 'a';
static assert(!is(ElementType!T == DBusAny), "Array must consist of the same type, use Variant!DBusAny or DBusAny(tuple(...)) instead"); static assert(!is(ElementType!T == DBusAny), "Array must consist of the same type, use Variant!DBusAny or DBusAny(tuple(...)) instead");
static assert(typeSig!(ElementType!T) != "y");
this.signature = typeSig!(ElementType!T).dup; this.signature = typeSig!(ElementType!T).dup;
this.explicitVariant = false; this.explicitVariant = false;
foreach(elem; value) foreach(elem; value)
@ -202,7 +211,12 @@ struct DBusAny {
valueStr = boolean ? "true" : "false"; valueStr = boolean ? "true" : "false";
break; break;
case 'a': case 'a':
valueStr = '[' ~ array.map!(a => a.toString).join(", ") ~ ']'; import std.digest.digest : toHexString;
if(signature == ['y'])
valueStr = "binary(" ~ binaryData.toHexString ~ ')';
else
valueStr = '[' ~ array.map!(a => a.toString).join(", ") ~ ']';
break; break;
case 'r': case 'r':
valueStr = '(' ~ array.map!(a => a.toString).join(", ") ~ ')'; valueStr = '(' ~ array.map!(a => a.toString).join(", ") ~ ')';
@ -277,8 +291,13 @@ struct DBusAny {
if(type != 'a' && type != 'r') if(type != 'a' && type != 'r')
throw new Exception("Can't convert type " ~ cast(char) type ~ " to an array"); throw new Exception("Can't convert type " ~ cast(char) type ~ " to an array");
T ret; T ret;
foreach(elem; array) if(signature == ['y']) {
ret ~= elem.to!(ElementType!T); static if(isIntegral!(ElementType!T))
foreach(elem; binaryData)
ret ~= elem.to!(ElementType!T);
} else
foreach(elem; array)
ret ~= elem.to!(ElementType!T);
return ret; return ret;
} else static if(isTuple!T) { } else static if(isTuple!T) {
if(type != 'r') if(type != 'r')
@ -305,6 +324,8 @@ struct DBusAny {
return false; return false;
if((type == 'a' || type == 'r') && b.signature != signature) if((type == 'a' || type == 'r') && b.signature != signature)
return false; return false;
if(type == 'a' && signature == ['y'])
return binaryData == b.binaryData;
if(type == 'a') if(type == 'a')
return array == b.array; return array == b.array;
else if(type == 'r') else if(type == 'r')
@ -339,6 +360,7 @@ unittest {
test(cast(long) 184, set!"int64"(DBusAny('x', null, false), cast(long) 184)); test(cast(long) 184, set!"int64"(DBusAny('x', null, false), cast(long) 184));
test(cast(ulong) 184, set!"uint64"(DBusAny('t', null, false), cast(ulong) 184)); test(cast(ulong) 184, set!"uint64"(DBusAny('t', null, false), cast(ulong) 184));
test(true, set!"boolean"(DBusAny('b', null, false), true)); test(true, set!"boolean"(DBusAny('b', null, false), true));
test(cast(ubyte[]) [1, 2, 3], set!"binaryData"(DBusAny('a', ['y'], false), cast(ubyte[]) [1, 2, 3]));
test(variant(cast(ubyte) 184), set!"int8"(DBusAny('y', null, true), cast(byte) 184)); test(variant(cast(ubyte) 184), set!"int8"(DBusAny('y', null, true), cast(byte) 184));
test(variant(cast(short) 184), set!"int16"(DBusAny('n', null, true), cast(short) 184)); test(variant(cast(short) 184), set!"int16"(DBusAny('n', null, true), cast(short) 184));
@ -348,6 +370,7 @@ unittest {
test(variant(cast(long) 184), set!"int64"(DBusAny('x', null, true), cast(long) 184)); test(variant(cast(long) 184), set!"int64"(DBusAny('x', null, true), cast(long) 184));
test(variant(cast(ulong) 184), set!"uint64"(DBusAny('t', null, true), cast(ulong) 184)); test(variant(cast(ulong) 184), set!"uint64"(DBusAny('t', null, true), cast(ulong) 184));
test(variant(true), set!"boolean"(DBusAny('b', null, true), true)); test(variant(true), set!"boolean"(DBusAny('b', null, true), true));
test(variant(cast(ubyte[]) [1, 2, 3]), set!"binaryData"(DBusAny('a', ['y'], true), cast(ubyte[]) [1, 2, 3]));
test(variant(DBusAny(5)), set!"int32"(DBusAny('i', null, true), 5)); test(variant(DBusAny(5)), set!"int32"(DBusAny('i', null, true), 5));