private void WriteVariantContents()

in src/Azure.IIoT.OpcUa/src/Encoders/JsonEncoderEx.cs [1331:1602]


        private void WriteVariantContents(object value, int valueRank,
            BuiltInType builtInType)
        {
            // Handle special value ranks
            if (valueRank is <= (-2) or 0)
            {
                if (valueRank < -3)
                {
                    throw new EncodingException(
                        $"Bad variant: Value rank '{valueRank}' is invalid.");
                }
                // Cannot deduce rank - write null
                if (value == null)
                {
                    WriteNull(null);
                    return;
                }
                // Handle one or more (0), Any (-2) or scalar or one dimension (-3)
                if (value.GetType().IsArray)
                {
                    var rank = value.GetType().GetArrayRank();
                    if (valueRank == -3 && rank != 1)
                    {
                        throw new EncodingException(
                            "Bad variant: Scalar or one dimension with matrix value.");
                    }
                    // Write as array or matrix
                    valueRank = rank;
                }
                else
                {
                    if (valueRank == 0)
                    {
                        throw new EncodingException(
                            "Bad variant: One or more dimension rank with scalar value.");
                    }
                    // Force write as scalar
                    valueRank = -1;
                }
            }

            // write scalar.
            if (valueRank == -1)
            {
                switch (builtInType)
                {
                    case BuiltInType.Null:
                        WriteNull(null);
                        return;
                    case BuiltInType.Boolean:
                        WriteBoolean(null, ToTypedScalar<bool>(value));
                        return;
                    case BuiltInType.SByte:
                        WriteSByte(null, ToTypedScalar<sbyte>(value));
                        return;
                    case BuiltInType.Byte:
                        WriteByte(null, ToTypedScalar<byte>(value));
                        return;
                    case BuiltInType.Int16:
                        WriteInt16(null, ToTypedScalar<short>(value));
                        return;
                    case BuiltInType.UInt16:
                        WriteUInt16(null, ToTypedScalar<ushort>(value));
                        return;
                    case BuiltInType.Int32:
                        WriteInt32(null, ToTypedScalar<int>(value));
                        return;
                    case BuiltInType.UInt32:
                        WriteUInt32(null, ToTypedScalar<uint>(value));
                        return;
                    case BuiltInType.Int64:
                        WriteInt64(null, ToTypedScalar<long>(value));
                        return;
                    case BuiltInType.UInt64:
                        WriteUInt64(null, ToTypedScalar<ulong>(value));
                        return;
                    case BuiltInType.Float:
                        WriteFloat(null, ToTypedScalar<float>(value));
                        return;
                    case BuiltInType.Double:
                        WriteDouble(null, ToTypedScalar<double>(value));
                        return;
                    case BuiltInType.String:
                        WriteString(null, ToTypedScalar<string>(value, null));
                        return;
                    case BuiltInType.DateTime:
                        WriteDateTime(null, ToTypedScalar<DateTime>(value));
                        return;
                    case BuiltInType.Guid:
                        WriteGuid(null, ToTypedScalar<Uuid>(value));
                        return;
                    case BuiltInType.ByteString:
                        WriteByteString(null, ToTypedScalar(value, Array.Empty<byte>()));
                        return;
                    case BuiltInType.XmlElement:
                        WriteXmlElement(null, ToTypedScalar<XmlElement>(value, null));
                        return;
                    case BuiltInType.NodeId:
                        WriteNodeId(null, ToTypedScalar<NodeId>(value, null));
                        return;
                    case BuiltInType.ExpandedNodeId:
                        WriteExpandedNodeId(null, ToTypedScalar<ExpandedNodeId>(value, null));
                        return;
                    case BuiltInType.StatusCode:
                        WriteStatusCode(null, ToTypedScalar<StatusCode>(value));
                        return;
                    case BuiltInType.QualifiedName:
                        WriteQualifiedName(null, ToTypedScalar<QualifiedName>(value, null));
                        return;
                    case BuiltInType.LocalizedText:
                        WriteLocalizedText(null, ToTypedScalar<LocalizedText>(value, null));
                        return;
                    case BuiltInType.ExtensionObject:
                        WriteExtensionObject(null, ToTypedScalar<ExtensionObject>(value, null));
                        return;
                    case BuiltInType.DataValue:
                        WriteDataValue(null, ToTypedScalar<DataValue>(value, null));
                        return;
                    case BuiltInType.Enumeration:
                        WriteInt32(null, ToTypedScalar<int>(value));
                        return;
                    case BuiltInType.Number:
                    case BuiltInType.Integer:
                    case BuiltInType.UInteger:
                    case BuiltInType.Variant:
                        throw new EncodingException(
                            "Bad variant: Unexpected type encountered while encoding " +
                            value.GetType());
                }
            }

            // write array.
            if (valueRank == 1)
            {
                switch (builtInType)
                {
                    case BuiltInType.Null:
                        WriteNull(null);
                        return;
                    case BuiltInType.Boolean:
                        WriteBooleanArray(null, ToTypedArray<bool>(value));
                        return;
                    case BuiltInType.SByte:
                        WriteSByteArray(null, ToTypedArray<sbyte>(value));
                        return;
                    case BuiltInType.Byte:
                        WriteByteArray(null, ToTypedArray<byte>(value));
                        return;
                    case BuiltInType.Int16:
                        WriteInt16Array(null, ToTypedArray<short>(value));
                        return;
                    case BuiltInType.UInt16:
                        WriteUInt16Array(null, ToTypedArray<ushort>(value));
                        return;
                    case BuiltInType.Int32:
                        WriteInt32Array(null, ToTypedArray<int>(value));
                        return;
                    case BuiltInType.UInt32:
                        WriteUInt32Array(null, ToTypedArray<uint>(value));
                        return;
                    case BuiltInType.Int64:
                        WriteInt64Array(null, ToTypedArray<long>(value));
                        return;
                    case BuiltInType.UInt64:
                        WriteUInt64Array(null, ToTypedArray<ulong>(value));
                        return;
                    case BuiltInType.Float:
                        WriteFloatArray(null, ToTypedArray<float>(value));
                        return;
                    case BuiltInType.Double:
                        WriteDoubleArray(null, ToTypedArray<double>(value));
                        return;
                    case BuiltInType.String:
                        WriteStringArray(null, ToTypedArray<string>(value, null));
                        return;
                    case BuiltInType.DateTime:
                        WriteDateTimeArray(null, ToTypedArray<DateTime>(value));
                        return;
                    case BuiltInType.Guid:
                        WriteGuidArray(null, ToTypedArray<Uuid>(value));
                        return;
                    case BuiltInType.ByteString:
                        WriteByteStringArray(null, ToTypedArray<byte[]>(value, null));
                        return;
                    case BuiltInType.XmlElement:
                        WriteXmlElementArray(null, ToTypedArray<XmlElement>(value, null));
                        return;
                    case BuiltInType.NodeId:
                        WriteNodeIdArray(null, ToTypedArray<NodeId>(value, null));
                        return;
                    case BuiltInType.ExpandedNodeId:
                        WriteExpandedNodeIdArray(null, ToTypedArray<ExpandedNodeId>(value, null));
                        return;
                    case BuiltInType.StatusCode:
                        WriteStatusCodeArray(null, ToTypedArray<StatusCode>(value));
                        return;
                    case BuiltInType.QualifiedName:
                        WriteQualifiedNameArray(null, ToTypedArray<QualifiedName>(value, null));
                        return;
                    case BuiltInType.LocalizedText:
                        WriteLocalizedTextArray(null, ToTypedArray<LocalizedText>(value, null));
                        return;
                    case BuiltInType.ExtensionObject:
                        WriteExtensionObjectArray(null, ToTypedArray<ExtensionObject>(value, null));
                        return;
                    case BuiltInType.DataValue:
                        WriteDataValueArray(null, ToTypedArray<DataValue>(value, null));
                        return;
                    case BuiltInType.Enumeration:
                        if (value is not Enum[] enums)
                        {
                            throw new EncodingException(
                                "Bad enum: Unexpected type encountered while encoding " +
                                $"enumeration type: {value.GetType()}");
                        }
                        var values = new string[enums.Length];
                        for (var index = 0; index < enums.Length; index++)
                        {
                            var text = enums[index].ToString();
                            text += "_";
                            text += ((int)(object)enums[index])
                                .ToString(CultureInfo.InvariantCulture);
                            values[index] = text;
                        }

                        WriteStringArray(null, values);
                        return;
                    case BuiltInType.Number:
                    case BuiltInType.UInteger:
                    case BuiltInType.Integer:
                    case BuiltInType.Variant:
                        if (value is Variant[] variants)
                        {
                            WriteVariantArray(null, variants);
                            return;
                        }
                        if (value is object[] objects)
                        {
                            WriteObjectArray(null, objects);
                            return;
                        }
                        throw new EncodingException(
                            "Bad variant: Unexpected type encountered while encoding an array" +
                            $" of Variants: {value.GetType()}");
                }
            }

            if (valueRank > 1)
            {
                // Write matrix
                if (value == null)
                {
                    WriteNull(null);
                    return;
                }

                // TODO: JSON array encoding only for
                // non reversible encoding, otherwise
                // flatten array and add Dimension.
                // if (!UseReversibleEncoding) {
                if (value is Matrix matrix)
                {
                    var index = 0;
                    WriteMatrix(matrix, 0, ref index, builtInType);
                    return;
                }
            }

            // Should never happen.
            throw new EncodingException(
                $"Bad variant: Type '{value.GetType().FullName}' is not allowed in Variant.");
        }