using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using MxGateway.Contracts.Proto; namespace MxGateway.Client; /// /// Creates and projects gateway MXAccess values without hiding the raw /// protobuf value carried by command replies and events. /// public static class MxValueExtensions { public static MxValue ToMxValue(this bool value) { return new MxValue { DataType = MxDataType.Boolean, VariantType = "VT_BOOL", BoolValue = value, }; } public static MxValue ToMxValue(this int value) { return new MxValue { DataType = MxDataType.Integer, VariantType = "VT_I4", Int32Value = value, }; } public static MxValue ToMxValue(this long value) { return new MxValue { DataType = MxDataType.Integer, VariantType = "VT_I8", Int64Value = value, }; } public static MxValue ToMxValue(this float value) { return new MxValue { DataType = MxDataType.Float, VariantType = "VT_R4", FloatValue = value, }; } public static MxValue ToMxValue(this double value) { return new MxValue { DataType = MxDataType.Double, VariantType = "VT_R8", DoubleValue = value, }; } public static MxValue ToMxValue(this string value) { ArgumentNullException.ThrowIfNull(value); return new MxValue { DataType = MxDataType.String, VariantType = "VT_BSTR", StringValue = value, }; } public static MxValue ToMxValue(this DateTimeOffset value) { return new MxValue { DataType = MxDataType.Time, VariantType = "VT_DATE", TimestampValue = Timestamp.FromDateTimeOffset(value), }; } public static MxValue ToMxValue(this DateTime value) { return new DateTimeOffset( value.Kind == DateTimeKind.Unspecified ? DateTime.SpecifyKind(value, DateTimeKind.Utc) : value.ToUniversalTime()) .ToMxValue(); } public static MxValue ToMxValue(this IReadOnlyList values) { ArgumentNullException.ThrowIfNull(values); var array = new BoolArray(); array.Values.Add(values); return CreateArrayValue(MxDataType.Boolean, "VT_ARRAY|VT_BOOL", values.Count, new MxArray { ElementDataType = MxDataType.Boolean, VariantType = "VT_ARRAY|VT_BOOL", BoolValues = array, }); } public static MxValue ToMxValue(this IReadOnlyList values) { ArgumentNullException.ThrowIfNull(values); var array = new Int32Array(); array.Values.Add(values); return CreateArrayValue(MxDataType.Integer, "VT_ARRAY|VT_I4", values.Count, new MxArray { ElementDataType = MxDataType.Integer, VariantType = "VT_ARRAY|VT_I4", Int32Values = array, }); } public static MxValue ToMxValue(this IReadOnlyList values) { ArgumentNullException.ThrowIfNull(values); var array = new Int64Array(); array.Values.Add(values); return CreateArrayValue(MxDataType.Integer, "VT_ARRAY|VT_I8", values.Count, new MxArray { ElementDataType = MxDataType.Integer, VariantType = "VT_ARRAY|VT_I8", Int64Values = array, }); } public static MxValue ToMxValue(this IReadOnlyList values) { ArgumentNullException.ThrowIfNull(values); var array = new FloatArray(); array.Values.Add(values); return CreateArrayValue(MxDataType.Float, "VT_ARRAY|VT_R4", values.Count, new MxArray { ElementDataType = MxDataType.Float, VariantType = "VT_ARRAY|VT_R4", FloatValues = array, }); } public static MxValue ToMxValue(this IReadOnlyList values) { ArgumentNullException.ThrowIfNull(values); var array = new DoubleArray(); array.Values.Add(values); return CreateArrayValue(MxDataType.Double, "VT_ARRAY|VT_R8", values.Count, new MxArray { ElementDataType = MxDataType.Double, VariantType = "VT_ARRAY|VT_R8", DoubleValues = array, }); } public static MxValue ToMxValue(this IReadOnlyList values) { ArgumentNullException.ThrowIfNull(values); var array = new StringArray(); array.Values.Add(values); return CreateArrayValue(MxDataType.String, "VT_ARRAY|VT_BSTR", values.Count, new MxArray { ElementDataType = MxDataType.String, VariantType = "VT_ARRAY|VT_BSTR", StringValues = array, }); } public static MxValue ToMxValue(this IReadOnlyList values) { ArgumentNullException.ThrowIfNull(values); var array = new TimestampArray(); array.Values.Add(values.Select(Timestamp.FromDateTimeOffset)); return CreateArrayValue(MxDataType.Time, "VT_ARRAY|VT_DATE", values.Count, new MxArray { ElementDataType = MxDataType.Time, VariantType = "VT_ARRAY|VT_DATE", TimestampValues = array, }); } public static string GetProjectionKind(this MxValue value) { ArgumentNullException.ThrowIfNull(value); return value.KindCase switch { MxValue.KindOneofCase.BoolValue => "boolValue", MxValue.KindOneofCase.Int32Value => "int32Value", MxValue.KindOneofCase.Int64Value => "int64Value", MxValue.KindOneofCase.FloatValue => "floatValue", MxValue.KindOneofCase.DoubleValue => "doubleValue", MxValue.KindOneofCase.StringValue => "stringValue", MxValue.KindOneofCase.TimestampValue => "timestampValue", MxValue.KindOneofCase.ArrayValue => "arrayValue", MxValue.KindOneofCase.RawValue => "rawValue", _ => value.IsNull ? "nullValue" : "unspecified", }; } public static object? ToClrValue(this MxValue value) { ArgumentNullException.ThrowIfNull(value); return value.KindCase switch { MxValue.KindOneofCase.BoolValue => value.BoolValue, MxValue.KindOneofCase.Int32Value => value.Int32Value, MxValue.KindOneofCase.Int64Value => value.Int64Value, MxValue.KindOneofCase.FloatValue => value.FloatValue, MxValue.KindOneofCase.DoubleValue => value.DoubleValue, MxValue.KindOneofCase.StringValue => value.StringValue, MxValue.KindOneofCase.TimestampValue => value.TimestampValue.ToDateTimeOffset(), MxValue.KindOneofCase.ArrayValue => value.ArrayValue.ToClrArrayValue(), MxValue.KindOneofCase.RawValue => value.RawValue.ToByteArray(), _ => value.IsNull ? null : value, }; } public static object? ToClrArrayValue(this MxArray array) { ArgumentNullException.ThrowIfNull(array); return array.ValuesCase switch { MxArray.ValuesOneofCase.BoolValues => array.BoolValues.Values.ToArray(), MxArray.ValuesOneofCase.Int32Values => array.Int32Values.Values.ToArray(), MxArray.ValuesOneofCase.Int64Values => array.Int64Values.Values.ToArray(), MxArray.ValuesOneofCase.FloatValues => array.FloatValues.Values.ToArray(), MxArray.ValuesOneofCase.DoubleValues => array.DoubleValues.Values.ToArray(), MxArray.ValuesOneofCase.StringValues => array.StringValues.Values.ToArray(), MxArray.ValuesOneofCase.TimestampValues => array.TimestampValues.Values .Select(timestamp => timestamp.ToDateTimeOffset()) .ToArray(), MxArray.ValuesOneofCase.RawValues => array.RawValues.Values .Select(value => value.ToByteArray()) .ToArray(), _ => null, }; } public static MxValue ToRawMxValue( byte[] value, string variantType, string rawDiagnostic, int rawDataType = 0) { ArgumentNullException.ThrowIfNull(value); return new MxValue { DataType = MxDataType.Unknown, VariantType = variantType, RawDiagnostic = rawDiagnostic, RawDataType = rawDataType, RawValue = ByteString.CopyFrom(value), }; } private static MxValue CreateArrayValue( MxDataType dataType, string variantType, int length, MxArray array) { array.Dimensions.Add((uint)length); return new MxValue { DataType = dataType, VariantType = variantType, ArrayValue = array, }; } }