package mxgateway import ( "fmt" "time" pb "gitea.dohertylan.com/dohertj2/mxaccessgw/clients/go/internal/generated" "google.golang.org/protobuf/types/known/timestamppb" ) // BoolValue builds an MXAccess Boolean value. func BoolValue(value bool) *MxValue { return &pb.MxValue{ DataType: pb.MxDataType_MX_DATA_TYPE_BOOLEAN, VariantType: "VT_BOOL", Kind: &pb.MxValue_BoolValue{BoolValue: value}, } } // Int32Value builds an MXAccess Int32 value. func Int32Value(value int32) *MxValue { return &pb.MxValue{ DataType: pb.MxDataType_MX_DATA_TYPE_INTEGER, VariantType: "VT_I4", Kind: &pb.MxValue_Int32Value{Int32Value: value}, } } // Int64Value builds an MXAccess Int64 value. func Int64Value(value int64) *MxValue { return &pb.MxValue{ DataType: pb.MxDataType_MX_DATA_TYPE_INTEGER, VariantType: "VT_I8", Kind: &pb.MxValue_Int64Value{Int64Value: value}, } } // FloatValue builds an MXAccess Float value. func FloatValue(value float32) *MxValue { return &pb.MxValue{ DataType: pb.MxDataType_MX_DATA_TYPE_FLOAT, VariantType: "VT_R4", Kind: &pb.MxValue_FloatValue{FloatValue: value}, } } // DoubleValue builds an MXAccess Double value. func DoubleValue(value float64) *MxValue { return &pb.MxValue{ DataType: pb.MxDataType_MX_DATA_TYPE_DOUBLE, VariantType: "VT_R8", Kind: &pb.MxValue_DoubleValue{DoubleValue: value}, } } // StringValue builds an MXAccess String value. func StringValue(value string) *MxValue { return &pb.MxValue{ DataType: pb.MxDataType_MX_DATA_TYPE_STRING, VariantType: "VT_BSTR", Kind: &pb.MxValue_StringValue{StringValue: value}, } } // TimestampValue builds an MXAccess timestamp value from a Go time. func TimestampValue(value time.Time) *MxValue { return &pb.MxValue{ DataType: pb.MxDataType_MX_DATA_TYPE_TIME, VariantType: "VT_DATE", Kind: &pb.MxValue_TimestampValue{TimestampValue: timestamppb.New(value)}, } } // NativeValue converts a protobuf MxValue to the closest Go representation // without discarding raw fallback data. func NativeValue(value *MxValue) (any, error) { if value == nil || value.GetIsNull() { return nil, nil } switch kind := value.GetKind().(type) { case *pb.MxValue_BoolValue: return kind.BoolValue, nil case *pb.MxValue_Int32Value: return kind.Int32Value, nil case *pb.MxValue_Int64Value: return kind.Int64Value, nil case *pb.MxValue_FloatValue: return kind.FloatValue, nil case *pb.MxValue_DoubleValue: return kind.DoubleValue, nil case *pb.MxValue_StringValue: return kind.StringValue, nil case *pb.MxValue_TimestampValue: if kind.TimestampValue == nil { return nil, nil } return kind.TimestampValue.AsTime(), nil case *pb.MxValue_ArrayValue: return NativeArray(kind.ArrayValue) case *pb.MxValue_RawValue: return append([]byte(nil), kind.RawValue...), nil default: return nil, fmt.Errorf("mxgateway: unsupported value kind %T", kind) } } // NativeArray converts a protobuf MxArray to the closest Go slice // representation. func NativeArray(array *MxArray) (any, error) { if array == nil { return nil, nil } switch values := array.GetValues().(type) { case *pb.MxArray_BoolValues: return append([]bool(nil), values.BoolValues.GetValues()...), nil case *pb.MxArray_Int32Values: return append([]int32(nil), values.Int32Values.GetValues()...), nil case *pb.MxArray_Int64Values: return append([]int64(nil), values.Int64Values.GetValues()...), nil case *pb.MxArray_FloatValues: return append([]float32(nil), values.FloatValues.GetValues()...), nil case *pb.MxArray_DoubleValues: return append([]float64(nil), values.DoubleValues.GetValues()...), nil case *pb.MxArray_StringValues: return append([]string(nil), values.StringValues.GetValues()...), nil case *pb.MxArray_TimestampValues: result := make([]time.Time, 0, len(values.TimestampValues.GetValues())) for _, value := range values.TimestampValues.GetValues() { if value == nil { result = append(result, time.Time{}) continue } result = append(result, value.AsTime()) } return result, nil case *pb.MxArray_RawValues: rawValues := values.RawValues.GetValues() result := make([][]byte, 0, len(rawValues)) for _, value := range rawValues { result = append(result, append([]byte(nil), value...)) } return result, nil default: return nil, fmt.Errorf("mxgateway: unsupported array value kind %T", values) } }