Refactor DBusAny.to!T()
This commit is contained in:
parent
137b3c36b7
commit
0570898602
|
@ -8,7 +8,7 @@ import ddbus.conv;
|
|||
import ddbus.exception : TypeMismatchException;
|
||||
import ddbus.util;
|
||||
|
||||
import std.meta : staticIndexOf;
|
||||
import std.meta : ApplyRight, Filter, staticIndexOf;
|
||||
import std.string;
|
||||
import std.typecons;
|
||||
import std.exception;
|
||||
|
@ -419,7 +419,7 @@ struct DBusAny {
|
|||
}
|
||||
|
||||
/// If the value is an array of DictionaryEntries this will return a HashMap
|
||||
DBusAny[DBusAny] toAA() {
|
||||
deprecated("Please use to!(V[K])") DBusAny[DBusAny] toAA() {
|
||||
enforce(type == 'a' && signature && signature[0] == '{');
|
||||
DBusAny[DBusAny] aa;
|
||||
|
||||
|
@ -451,8 +451,19 @@ struct DBusAny {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a basic type, a tuple or an array to the D type with type checking. Tuples can get converted to an array too.
|
||||
T to(T)() {
|
||||
/++
|
||||
Converts a basic type, a tuple or an array to the D type with type checking.
|
||||
|
||||
Tuples can be converted to an array of DBusAny, but not to any other array.
|
||||
+/
|
||||
T to(T)() @property const pure {
|
||||
// Just use `get` if possible
|
||||
static if (canDBus!T && __traits(compiles, get!T)) {
|
||||
if (this.typeSig == .typeSig!T)
|
||||
return get!T;
|
||||
}
|
||||
|
||||
// If we get here, we need some type conversion
|
||||
static if (is(T == Variant!R, R)) {
|
||||
static if (is(R == DBusAny)) {
|
||||
auto v = to!R;
|
||||
|
@ -463,92 +474,87 @@ struct DBusAny {
|
|||
}
|
||||
} else static if (is(T == DBusAny)) {
|
||||
return this;
|
||||
} else static if (isIntegral!T || isFloatingPoint!T) {
|
||||
switch (type) {
|
||||
case typeCode!byte:
|
||||
return cast(T) int8;
|
||||
case typeCode!short:
|
||||
return cast(T) int16;
|
||||
case typeCode!ushort:
|
||||
return cast(T) uint16;
|
||||
case typeCode!int:
|
||||
return cast(T) int32;
|
||||
case typeCode!uint:
|
||||
return cast(T) uint32;
|
||||
case typeCode!long:
|
||||
return cast(T) int64;
|
||||
case typeCode!ulong:
|
||||
return cast(T) uint64;
|
||||
case typeCode!double:
|
||||
return cast(T) float64;
|
||||
default:
|
||||
throw new Exception("Can't convert type " ~ cast(char) type ~ " to " ~ T.stringof);
|
||||
}
|
||||
} else static if (is(T == bool)) {
|
||||
if (type == 'b') {
|
||||
return boolean;
|
||||
} else {
|
||||
throw new Exception("Can't convert type " ~ cast(char) type ~ " to " ~ T.stringof);
|
||||
}
|
||||
} else static if (isSomeString!T) {
|
||||
if (type == 's') {
|
||||
return str.to!T;
|
||||
} else if (type == 'o') {
|
||||
return obj.toString();
|
||||
// In here are all static if blocks that may fall through to the throw
|
||||
// statement at the bottom of this block.
|
||||
|
||||
static if (is(T == DictionaryEntry!(K, V), K, V)) {
|
||||
if (type == 'e') {
|
||||
static if (is(T == typeof(entry))) {
|
||||
return entry;
|
||||
} 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) {
|
||||
if (type != 'a' && type != 'r') {
|
||||
throw new Exception("Can't convert type " ~ cast(char) type ~ " to an array");
|
||||
}
|
||||
|
||||
T ret;
|
||||
if (signature == ['y']) {
|
||||
static if (isIntegral!(ElementType!T)) {
|
||||
foreach (elem; binaryData) {
|
||||
ret ~= elem.to!(ElementType!T);
|
||||
return DictionaryEntry(entry.key.to!K, entry.value.to!V);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach (elem; array) {
|
||||
ret ~= elem.to!(ElementType!T);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else static if (isTuple!T) {
|
||||
if (type != 'r') {
|
||||
throw new Exception("Can't convert type " ~ cast(char) type ~ " to " ~ T.stringof);
|
||||
}
|
||||
|
||||
T ret;
|
||||
enforce(ret.Types.length == tuple.length, "Tuple length mismatch");
|
||||
foreach (index, T; ret.Types) {
|
||||
ret[index] = tuple[index].to!T;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else static if (isAssociativeArray!T) {
|
||||
if (type != 'a' || !signature || signature[0] != '{') {
|
||||
throw new Exception("Can't convert type " ~ cast(char) type ~ " to " ~ T.stringof);
|
||||
if (type == 'a' && (!array.length || array[0].type == 'e')) {
|
||||
alias K = Unqual!(KeyType!T);
|
||||
alias V = Unqual!(ValueType!T);
|
||||
V[K] ret;
|
||||
|
||||
foreach (pair; array) {
|
||||
assert(pair.type == 'e');
|
||||
ret[pair.entry.key.to!K] = pair.entry.value.to!V;
|
||||
}
|
||||
|
||||
T ret;
|
||||
foreach (pair; array) {
|
||||
enforce(pair.type == 'e');
|
||||
ret[pair.entry.key.to!(KeyType!T)] = pair.entry.value.to!(ValueType!T);
|
||||
return cast(T) ret;
|
||||
}
|
||||
} else static if (isDynamicArray!T && !isSomeString!T) {
|
||||
alias E = Unqual!(ElementType!T);
|
||||
|
||||
if (typeSig == "ay") {
|
||||
static if (is(E == ubyte) || is(E == byte)) {
|
||||
return cast(T) binaryData.dup;
|
||||
} else {
|
||||
T ret;
|
||||
ret.length = binaryData.length;
|
||||
|
||||
foreach (i, b; binaryData)
|
||||
ret[i] = b;
|
||||
|
||||
return ret;
|
||||
}
|
||||
} else if (type == 'a' || (type == 'r' && is(E == DBusAny))) {
|
||||
E[] ret;
|
||||
ret.length = array.length;
|
||||
|
||||
foreach (i, elem; array)
|
||||
ret[i] = elem.to!(ElementType!T);
|
||||
|
||||
return cast(T) ret;
|
||||
}
|
||||
} else static if (isTuple!T) {
|
||||
if (type == 'r') {
|
||||
T ret;
|
||||
|
||||
foreach (i, T; ret.Types)
|
||||
ret[i] = tuple[i].to!T;
|
||||
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
static assert(false, "Can't convert variant to " ~ T.stringof);
|
||||
alias isPreciselyConvertible = ApplyRight!(isImplicitlyConvertible, T);
|
||||
|
||||
template isUnpreciselyConvertible(S) {
|
||||
enum isUnpreciselyConvertible = !isPreciselyConvertible!S
|
||||
&& __traits(compiles, get!S.to!T);
|
||||
}
|
||||
|
||||
// Try to be precise
|
||||
foreach (B; Filter!(isPreciselyConvertible, BasicTypes)) {
|
||||
if (type == typeCode!B)
|
||||
return get!B;
|
||||
}
|
||||
|
||||
// Try to convert
|
||||
foreach (B; Filter!(isUnpreciselyConvertible, BasicTypes)) {
|
||||
if (type == typeCode!B)
|
||||
return get!B.to!T;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ConvException("Cannot convert from DBus type '" ~ this.typeSig ~ "' to "
|
||||
~ T.stringof);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue