in src/Azure.IIoT.OpcUa/src/Encoders/JsonDecoderEx.cs [1384:1488]
private Variant ReadVariantFromArray(JArray array, bool unsigned = false)
{
if (array.Count == 0)
{
return Variant.Null; // Give up
}
// Try to decode non reversible encoding first.
var dimensions = GetDimensions(array, out var type);
if (dimensions.Length > 1)
{
var builtInType = BuiltInType.Variant;
switch (type)
{
case JTokenType.Integer:
builtInType = BuiltInType.Int64;
break;
case JTokenType.Boolean:
builtInType = BuiltInType.Boolean;
break;
case JTokenType.Bytes:
builtInType = BuiltInType.ByteString;
break;
case JTokenType.Date:
case JTokenType.TimeSpan:
builtInType = BuiltInType.DateTime;
break;
case JTokenType.Float:
builtInType = BuiltInType.Double;
break;
case JTokenType.Guid:
builtInType = BuiltInType.Guid;
break;
case JTokenType.String:
builtInType = BuiltInType.String;
break;
}
return ReadVariantMatrixBody(array, dimensions, builtInType);
}
if (type != JTokenType.Object && array.All(j => j.Type == type))
{
try
{
switch (array[0].Type)
{
case JTokenType.Integer:
return !unsigned ? new Variant(array
.Select(t => (long)t)
.ToArray()) : new Variant(array
.Select(t => (ulong)t)
.ToArray());
case JTokenType.Boolean:
return new Variant(array
.Select(t => (bool)t)
.ToArray());
case JTokenType.Bytes:
return new Variant(array
.Select(t => (byte[]?)t)
.ToArray());
case JTokenType.Date:
return new Variant(array
.Select(t => (DateTime)t)
.ToArray());
case JTokenType.TimeSpan:
return new Variant(array
.Select(t => ((TimeSpan)t).TotalMilliseconds)
.ToArray());
case JTokenType.Float:
return new Variant(array
.Select(t => (double)t)
.ToArray());
case JTokenType.Guid:
return new Variant(array
.Select(t => (Guid)t)
.ToArray());
case JTokenType.String:
return new Variant(array
.Select(t => (string?)t)
.ToArray());
}
}
catch
{
// TODO Log or throw for bad type
return Variant.Null; // Give up
}
}
var result = array
.Select(t => ReadVariantFromToken(t, unsigned))
.ToArray();
var validBuiltInType = Array.Find(result, v => v.TypeInfo?.BuiltInType != null).TypeInfo?.BuiltInType;
if (validBuiltInType == null)
{
return Variant.Null;
}
if (result
.Where(v => v != Variant.Null)
.All(v => v.TypeInfo.BuiltInType == validBuiltInType))
{
// TODO: This needs tests as it should not work.
return new Variant(result.Select(v => v.Value).ToArray());
}
return new Variant(result);
}