From f56aed3eefbfb71921899844b30a4e28722ca4b8 Mon Sep 17 00:00:00 2001 From: Street <5597260+MStreet3@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:02:49 -0400 Subject: [PATCH] [CAPPL-31] feat(values): adds support for time.Time as value (#787) * feat(values): adds support for time.Time as value * chore(deps): updates .tool-versions * refactor(values): uses primitive type in protos --- .tool-versions | 4 +- pkg/values/pb/values.go | 11 +++ pkg/values/pb/values.pb.go | 150 +++++++++++++++++++++---------------- pkg/values/pb/values.proto | 15 ++-- pkg/values/time.go | 41 ++++++++++ pkg/values/time_test.go | 89 ++++++++++++++++++++++ pkg/values/value.go | 2 + pkg/values/value_test.go | 16 ++++ 8 files changed, 256 insertions(+), 72 deletions(-) create mode 100644 pkg/values/time.go create mode 100644 pkg/values/time_test.go diff --git a/.tool-versions b/.tool-versions index 2e04a2b63..b82d197d7 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,5 @@ -golang 1.21.4 +golang 1.22.7 +protoc 25.1 +protoc-gen-go-grpc 1.3.0 golangci-lint 1.55.2 mockery 2.43.2 diff --git a/pkg/values/pb/values.go b/pkg/values/pb/values.go index 59755cfa8..f0e303de0 100644 --- a/pkg/values/pb/values.go +++ b/pkg/values/pb/values.go @@ -1,7 +1,10 @@ package pb import ( + "time" + "github.com/shopspring/decimal" + "google.golang.org/protobuf/types/known/timestamppb" ) func NewBoolValue(b bool) *Value { @@ -80,3 +83,11 @@ func NewBigIntValue(sign int, bib []byte) *Value { }, } } + +func NewTime(t time.Time) *Value { + return &Value{ + Value: &Value_TimeValue{ + TimeValue: timestamppb.New(t), + }, + } +} diff --git a/pkg/values/pb/values.pb.go b/pkg/values/pb/values.pb.go index 5db8a5a26..17df74c6e 100644 --- a/pkg/values/pb/values.pb.go +++ b/pkg/values/pb/values.pb.go @@ -9,6 +9,7 @@ package pb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -35,6 +36,7 @@ type Value struct { // *Value_DecimalValue // *Value_Int64Value // *Value_BigintValue + // *Value_TimeValue Value isValue_Value `protobuf_oneof:"value"` } @@ -133,6 +135,13 @@ func (x *Value) GetBigintValue() *BigInt { return nil } +func (x *Value) GetTimeValue() *timestamppb.Timestamp { + if x, ok := x.GetValue().(*Value_TimeValue); ok { + return x.TimeValue + } + return nil +} + type isValue_Value interface { isValue_Value() } @@ -169,6 +178,10 @@ type Value_BigintValue struct { BigintValue *BigInt `protobuf:"bytes,9,opt,name=bigint_value,json=bigintValue,proto3,oneof"` } +type Value_TimeValue struct { + TimeValue *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=time_value,json=timeValue,proto3,oneof"` +} + func (*Value_StringValue) isValue_Value() {} func (*Value_BoolValue) isValue_Value() {} @@ -185,6 +198,8 @@ func (*Value_Int64Value) isValue_Value() {} func (*Value_BigintValue) isValue_Value() {} +func (*Value_TimeValue) isValue_Value() {} + type BigInt struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -394,54 +409,60 @@ var File_values_pb_values_proto protoreflect.FileDescriptor var file_values_pb_values_proto_rawDesc = []byte{ 0x0a, 0x16, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x70, 0x62, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x22, 0xea, 0x02, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x21, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, - 0x4d, 0x61, 0x70, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x2d, 0x0a, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x48, 0x00, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, - 0x0a, 0x0d, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x44, - 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x0c, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, - 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0a, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x33, 0x0a, 0x0c, 0x62, 0x69, 0x67, - 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x42, 0x69, 0x67, 0x49, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x0b, 0x62, 0x69, 0x67, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x22, 0x35, 0x0a, - 0x06, 0x42, 0x69, 0x67, 0x49, 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x62, 0x73, 0x5f, 0x76, - 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x61, 0x62, 0x73, 0x56, 0x61, 0x6c, - 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, - 0x73, 0x69, 0x67, 0x6e, 0x22, 0x80, 0x01, 0x0a, 0x03, 0x4d, 0x61, 0x70, 0x12, 0x2f, 0x0a, 0x06, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x4d, 0x61, 0x70, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x48, 0x0a, - 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x23, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x2d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x25, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x0d, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x22, 0x57, 0x0a, 0x07, 0x44, 0x65, 0x63, 0x69, 0x6d, 0x61, - 0x6c, 0x12, 0x30, 0x0a, 0x0b, 0x63, 0x6f, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, - 0x42, 0x69, 0x67, 0x49, 0x6e, 0x74, 0x52, 0x0b, 0x63, 0x6f, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, - 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x42, - 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, - 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0xa7, 0x03, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x2e, 0x4d, 0x61, 0x70, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x2d, 0x0a, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x48, 0x00, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x36, 0x0a, 0x0d, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, + 0x44, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x0c, 0x64, 0x65, 0x63, 0x69, 0x6d, + 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x36, 0x34, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0a, + 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x33, 0x0a, 0x0c, 0x62, 0x69, + 0x67, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x42, 0x69, 0x67, 0x49, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x0b, 0x62, 0x69, 0x67, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x3b, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, + 0x00, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x22, 0x35, 0x0a, 0x06, 0x42, + 0x69, 0x67, 0x49, 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x62, 0x73, 0x5f, 0x76, 0x61, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x61, 0x62, 0x73, 0x56, 0x61, 0x6c, 0x12, 0x12, + 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, + 0x67, 0x6e, 0x22, 0x80, 0x01, 0x0a, 0x03, 0x4d, 0x61, 0x70, 0x12, 0x2f, 0x0a, 0x06, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x2e, 0x4d, 0x61, 0x70, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x48, 0x0a, 0x0b, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x2d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x25, 0x0a, + 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x22, 0x57, 0x0a, 0x07, 0x44, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x12, + 0x30, 0x0a, 0x0b, 0x63, 0x6f, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x42, 0x69, + 0x67, 0x49, 0x6e, 0x74, 0x52, 0x0b, 0x63, 0x6f, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x42, 0x3c, 0x5a, + 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, 0x61, 0x72, + 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -458,27 +479,29 @@ func file_values_pb_values_proto_rawDescGZIP() []byte { var file_values_pb_values_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_values_pb_values_proto_goTypes = []interface{}{ - (*Value)(nil), // 0: values.Value - (*BigInt)(nil), // 1: values.BigInt - (*Map)(nil), // 2: values.Map - (*List)(nil), // 3: values.List - (*Decimal)(nil), // 4: values.Decimal - nil, // 5: values.Map.FieldsEntry + (*Value)(nil), // 0: values.Value + (*BigInt)(nil), // 1: values.BigInt + (*Map)(nil), // 2: values.Map + (*List)(nil), // 3: values.List + (*Decimal)(nil), // 4: values.Decimal + nil, // 5: values.Map.FieldsEntry + (*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp } var file_values_pb_values_proto_depIdxs = []int32{ 2, // 0: values.Value.map_value:type_name -> values.Map 3, // 1: values.Value.list_value:type_name -> values.List 4, // 2: values.Value.decimal_value:type_name -> values.Decimal 1, // 3: values.Value.bigint_value:type_name -> values.BigInt - 5, // 4: values.Map.fields:type_name -> values.Map.FieldsEntry - 0, // 5: values.List.fields:type_name -> values.Value - 1, // 6: values.Decimal.coefficient:type_name -> values.BigInt - 0, // 7: values.Map.FieldsEntry.value:type_name -> values.Value - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 6, // 4: values.Value.time_value:type_name -> google.protobuf.Timestamp + 5, // 5: values.Map.fields:type_name -> values.Map.FieldsEntry + 0, // 6: values.List.fields:type_name -> values.Value + 1, // 7: values.Decimal.coefficient:type_name -> values.BigInt + 0, // 8: values.Map.FieldsEntry.value:type_name -> values.Value + 9, // [9:9] is the sub-list for method output_type + 9, // [9:9] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_values_pb_values_proto_init() } @@ -557,6 +580,7 @@ func file_values_pb_values_proto_init() { (*Value_DecimalValue)(nil), (*Value_Int64Value)(nil), (*Value_BigintValue)(nil), + (*Value_TimeValue)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/pkg/values/pb/values.proto b/pkg/values/pb/values.proto index 7eb3e65a4..946c7ae81 100644 --- a/pkg/values/pb/values.proto +++ b/pkg/values/pb/values.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +import "google/protobuf/timestamp.proto"; + option go_package = "github.com/smartcontractkit/chainlink-common/pkg/values/pb"; package values; @@ -15,21 +17,18 @@ message Value { Decimal decimal_value = 6; int64 int64_value = 7; BigInt bigint_value = 9; + google.protobuf.Timestamp time_value = 10; } } message BigInt { - bytes abs_val = 1; - int64 sign = 2; + bytes abs_val = 1; + int64 sign = 2; } -message Map { - map fields = 1; -} +message Map { map fields = 1; } -message List { - repeated Value fields = 2; -} +message List { repeated Value fields = 2; } message Decimal { BigInt coefficient = 1; diff --git a/pkg/values/time.go b/pkg/values/time.go new file mode 100644 index 000000000..7280021a8 --- /dev/null +++ b/pkg/values/time.go @@ -0,0 +1,41 @@ +package values + +import ( + "errors" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/values/pb" +) + +type Time struct { + Underlying time.Time +} + +func NewTime(t time.Time) *Time { + return &Time{Underlying: t} +} + +func (t *Time) UnwrapTo(to any) error { + if t == nil { + return errors.New("could not unwrap nil values.Time") + } + + return unwrapTo(t.Underlying, to) +} + +func (t *Time) Unwrap() (any, error) { + tt := new(time.Time) + return *tt, t.UnwrapTo(tt) +} + +func (t *Time) copy() Value { + if t == nil { + return nil + } + + return NewTime(t.Underlying) +} + +func (t *Time) proto() *pb.Value { + return pb.NewTime(t.Underlying) +} diff --git a/pkg/values/time_test.go b/pkg/values/time_test.go new file mode 100644 index 000000000..d33db109e --- /dev/null +++ b/pkg/values/time_test.go @@ -0,0 +1,89 @@ +package values + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func Test_TimeUnwrapTo(t *testing.T) { + expected, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + assert.NoError(t, err) + + // Unwraps to a time.Time pointer + v := NewTime(expected) + got := new(time.Time) + err = v.UnwrapTo(got) + assert.NoError(t, err) + assert.Equal(t, expected, *got) + + // Fails to unwrap to nil time.Time pointer + gotTime := (*time.Time)(nil) + err = v.UnwrapTo(gotTime) + assert.Error(t, err) + assert.ErrorContains(t, err, "cannot unwrap to nil pointer") + + // Unwraps to an any pointer + var varAny any + err = v.UnwrapTo(&varAny) + assert.NoError(t, err) + assert.Equal(t, expected, varAny) + + // Fails to unwrap to a string pointer + var varStr string + err = v.UnwrapTo(&varStr) + assert.Error(t, err) + assert.ErrorContains(t, err, "cannot unwrap to value of type: *string") + + // Fails to unwrap nil value of Time + nilVal := (*Time)(nil) + _, err = nilVal.Unwrap() + assert.Error(t, err) + assert.ErrorContains(t, err, "could not unwrap nil") + + // Unwraps zero value of Time + zeroTime := &Time{} + unwrapped, err := zeroTime.Unwrap() + assert.NoError(t, err) + assert.Equal(t, time.Time{}, unwrapped) + + // Unwraps an alias + type aliasTime time.Time + alias := aliasTime(time.Time{}) + err = v.UnwrapTo(&alias) + assert.NoError(t, err) + assert.Equal(t, expected, time.Time(alias)) +} + +// Test_Time tests that Time values can be converted to and from protobuf representations. +func Test_Time(t *testing.T) { + testCases := []struct { + name string + t time.Time + }{ + { + name: "zero", + t: time.Time{}, + }, + { + name: "some time", + t: func() time.Time { + someTime, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + assert.NoError(t, err) + return someTime + }(), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + v := NewTime(tc.t) + + vp := Proto(v) + got, err := FromProto(vp) + assert.NoError(t, err) + assert.Equal(t, tc.t, got.(*Time).Underlying) + }) + } +} diff --git a/pkg/values/value.go b/pkg/values/value.go index c0014d049..46f271efa 100644 --- a/pkg/values/value.go +++ b/pkg/values/value.go @@ -209,6 +209,8 @@ func FromProto(val *pb.Value) (Value, error) { return FromMapValueProto(val.GetMapValue()) case *pb.Value_BigintValue: return fromBigIntValueProto(val.GetBigintValue()), nil + case *pb.Value_TimeValue: + return NewTime(val.GetTimeValue().AsTime()), nil } return nil, fmt.Errorf("unsupported type %T: %+v", val, val) diff --git a/pkg/values/value_test.go b/pkg/values/value_test.go index a628bccea..1ca020fc0 100644 --- a/pkg/values/value_test.go +++ b/pkg/values/value_test.go @@ -5,6 +5,7 @@ import ( "math/big" "reflect" "testing" + "time" "github.com/go-viper/mapstructure/v2" "github.com/shopspring/decimal" @@ -101,6 +102,14 @@ func Test_Value(t *testing.T) { return b, bv, nil }, }, + { + name: "time", + newValue: func() (any, Value, error) { + t, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + tv := NewTime(t) + return t, tv, err + }, + }, { name: "recursive map", newValue: func() (any, Value, error) { @@ -379,6 +388,9 @@ func Test_Copy(t *testing.T) { { value: mp, }, + { + value: NewTime(time.Time{}), + }, { value: (*String)(nil), isNil: true, @@ -407,6 +419,10 @@ func Test_Copy(t *testing.T) { value: (*Map)(nil), isNil: true, }, + { + value: (*Time)(nil), + isNil: true, + }, } for _, tc := range tcs {