From bb69d4de707e3122e0f60c3cf66a7d3492aa5a64 Mon Sep 17 00:00:00 2001 From: guochao Date: Fri, 27 Oct 2023 12:57:01 +0800 Subject: [PATCH] initial commit --- Makefile | 26 +++++ example.pb.go | 254 +++++++++++++++++++++++++++++++++++++++++++++++ example.proto | 18 ++++ go.mod | 5 + go.sum | 6 ++ oneof_test.go | 88 ++++++++++++++++ optional_test.go | 72 ++++++++++++++ 7 files changed, 469 insertions(+) create mode 100644 Makefile create mode 100644 example.pb.go create mode 100644 example.proto create mode 100644 go.mod create mode 100644 go.sum create mode 100644 oneof_test.go create mode 100644 optional_test.go diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..95804c2 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +PROTOC ?= $(shell which protoc) + +PROTOS := $(shell find -name '*.proto') +PROTO_GEN_PB := $(subst .proto,.pb.go,$(PROTOS)) +PROTO_GEN_GRPC := $(subst .proto,_grpc.pb.go,$(PROTOS)) + +GO_SRC := $(shell find -name '*.go') + +.PHONY: all +all: test + +.PHONY: build +build: + +.PHONY: tet +test: example.pb.go + go test -v ./... + +bin/%: $(GO_SRC) $(PROTO_GEN_PB) $(PROTO_GEN_GRPC) + go build -o $@ ./$< + +%_grpc.pb.go: %.proto + protoc --go-grpc_out=. --go-grpc_opt=paths=source_relative $< + +%.pb.go: %.proto + protoc --go_out=. --go_opt=paths=source_relative $< diff --git a/example.pb.go b/example.pb.go new file mode 100644 index 0000000..db2062b --- /dev/null +++ b/example.pb.go @@ -0,0 +1,254 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v4.24.3 +// source: example.proto + +package demo_protobuf3_optional + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type WithOptional struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + Userid *int64 `protobuf:"varint,2,opt,name=userid,proto3,oneof" json:"userid,omitempty"` +} + +func (x *WithOptional) Reset() { + *x = WithOptional{} + if protoimpl.UnsafeEnabled { + mi := &file_example_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WithOptional) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WithOptional) ProtoMessage() {} + +func (x *WithOptional) ProtoReflect() protoreflect.Message { + mi := &file_example_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WithOptional.ProtoReflect.Descriptor instead. +func (*WithOptional) Descriptor() ([]byte, []int) { + return file_example_proto_rawDescGZIP(), []int{0} +} + +func (x *WithOptional) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *WithOptional) GetUserid() int64 { + if x != nil && x.Userid != nil { + return *x.Userid + } + return 0 +} + +type WithOneof struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + // Types that are assignable to OptionalUserid: + // + // *WithOneof_Userid + OptionalUserid isWithOneof_OptionalUserid `protobuf_oneof:"optional_userid"` +} + +func (x *WithOneof) Reset() { + *x = WithOneof{} + if protoimpl.UnsafeEnabled { + mi := &file_example_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WithOneof) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WithOneof) ProtoMessage() {} + +func (x *WithOneof) ProtoReflect() protoreflect.Message { + mi := &file_example_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WithOneof.ProtoReflect.Descriptor instead. +func (*WithOneof) Descriptor() ([]byte, []int) { + return file_example_proto_rawDescGZIP(), []int{1} +} + +func (x *WithOneof) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (m *WithOneof) GetOptionalUserid() isWithOneof_OptionalUserid { + if m != nil { + return m.OptionalUserid + } + return nil +} + +func (x *WithOneof) GetUserid() int64 { + if x, ok := x.GetOptionalUserid().(*WithOneof_Userid); ok { + return x.Userid + } + return 0 +} + +type isWithOneof_OptionalUserid interface { + isWithOneof_OptionalUserid() +} + +type WithOneof_Userid struct { + Userid int64 `protobuf:"varint,2,opt,name=userid,proto3,oneof"` +} + +func (*WithOneof_Userid) isWithOneof_OptionalUserid() {} + +var File_example_proto protoreflect.FileDescriptor + +var file_example_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x17, 0x64, 0x65, 0x6d, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x33, 0x5f, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x52, 0x0a, 0x0c, 0x57, 0x69, 0x74, 0x68, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x69, 0x64, 0x88, 0x01, + 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x69, 0x64, 0x22, 0x54, 0x0a, 0x09, + 0x57, 0x69, 0x74, 0x68, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, + 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, + 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x69, 0x64, 0x42, + 0x11, 0x0a, 0x0f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x69, 0x64, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x2e, 0x6a, 0x65, 0x66, 0x66, 0x74, 0x68, + 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x78, 0x79, 0x7a, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x2f, 0x64, 0x65, 0x6d, 0x6f, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x33, + 0x2d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_example_proto_rawDescOnce sync.Once + file_example_proto_rawDescData = file_example_proto_rawDesc +) + +func file_example_proto_rawDescGZIP() []byte { + file_example_proto_rawDescOnce.Do(func() { + file_example_proto_rawDescData = protoimpl.X.CompressGZIP(file_example_proto_rawDescData) + }) + return file_example_proto_rawDescData +} + +var file_example_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_example_proto_goTypes = []interface{}{ + (*WithOptional)(nil), // 0: demo_protobuf3_optional.WithOptional + (*WithOneof)(nil), // 1: demo_protobuf3_optional.WithOneof +} +var file_example_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_example_proto_init() } +func file_example_proto_init() { + if File_example_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_example_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WithOptional); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_example_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WithOneof); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_example_proto_msgTypes[0].OneofWrappers = []interface{}{} + file_example_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*WithOneof_Userid)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_example_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_example_proto_goTypes, + DependencyIndexes: file_example_proto_depIdxs, + MessageInfos: file_example_proto_msgTypes, + }.Build() + File_example_proto = out.File + file_example_proto_rawDesc = nil + file_example_proto_goTypes = nil + file_example_proto_depIdxs = nil +} diff --git a/example.proto b/example.proto new file mode 100644 index 0000000..878111e --- /dev/null +++ b/example.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package demo_protobuf3_optional; + +option go_package = "git.jeffthecoder.xyz/public/demo-protobuf3-optional"; + +message WithOptional { + string username = 1; + optional int64 userid = 2; +} + +message WithOneof { + string username = 1; + oneof optional_userid { + int64 userid = 2; + } +} + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f9c534d --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module git.jeffthecoder.xyz/public/demo-protobuf3-optional + +go 1.20 + +require google.golang.org/protobuf v1.31.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..89f7f22 --- /dev/null +++ b/go.sum @@ -0,0 +1,6 @@ +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/oneof_test.go b/oneof_test.go new file mode 100644 index 0000000..b17725f --- /dev/null +++ b/oneof_test.go @@ -0,0 +1,88 @@ +package demo_protobuf3_optional + +import ( + "testing" + + "google.golang.org/protobuf/proto" +) + +func TestOneofNilId(t *testing.T) { + noid := &WithOneof { + Username: "me", + OptionalUserid: nil, + } + t.Log(noid.String()) + wiremessage, err := proto.Marshal(noid) + if err != nil { + t.Fatal("marshal failed: ", err) + } + + unmarshaled := &WithOneof{} + if err := proto.Unmarshal(wiremessage, unmarshaled); err != nil { + t.Fatal("failed to unmarshal message: ", err) + } + t.Log("id: ", unmarshaled.OptionalUserid) + if unmarshaled.OptionalUserid != nil { + t.Fatalf("expected userid is nil, got %v", unmarshaled.OptionalUserid) + } +} + +func TestOneofZeroId(t *testing.T) { + id := &WithOneof_Userid{ + Userid: 0, + } + noid := &WithOneof { + Username: "me", + OptionalUserid: id, + } + t.Log(noid.String()) + wiremessage, err := proto.Marshal(noid) + if err != nil { + t.Fatal("marshal failed: ", err) + } + + unmarshaled := &WithOneof{} + if err := proto.Unmarshal(wiremessage, unmarshaled); err != nil { + t.Fatal("failed to unmarshal message: ", err) + } + + if unmarshaled.OptionalUserid == nil { + t.Fatalf("expected userid is not nil, got %v", unmarshaled.OptionalUserid) + } else if userid, ok := unmarshaled.OptionalUserid.(*WithOneof_Userid); !ok { + t.Fatalf("expected userid is instance of type %T , got %T", &WithOneof_Userid{}, unmarshaled.OptionalUserid ) + } else if userid.Userid != 0 { + t.Errorf("expected userid is %v, got %v", id, userid.Userid) + } else { + t.Log("id: ", userid.Userid) + } +} + +func TestOneofNonZeroId(t *testing.T) { + id := &WithOneof_Userid{ + Userid: 1, + } + noid := &WithOneof { + Username: "me", + OptionalUserid: id, + } + t.Log(noid.String()) + wiremessage, err := proto.Marshal(noid) + if err != nil { + t.Fatal("marshal failed: ", err) + } + + unmarshaled := &WithOneof{} + if err := proto.Unmarshal(wiremessage, unmarshaled); err != nil { + t.Fatal("failed to unmarshal message: ", err) + } + + if unmarshaled.OptionalUserid == nil { + t.Fatalf("expected userid is not nil, got %v", unmarshaled.OptionalUserid) + } else if userid, ok := unmarshaled.OptionalUserid.(*WithOneof_Userid); !ok { + t.Fatalf("expected userid is instance of type %T , got %T", &WithOneof_Userid{}, unmarshaled.OptionalUserid ) + } else if userid.Userid != 1{ + t.Errorf("expected userid is %v, got %v", id, userid.Userid) + } else { + t.Log("id: ", userid.Userid) + } +} diff --git a/optional_test.go b/optional_test.go new file mode 100644 index 0000000..6118a6f --- /dev/null +++ b/optional_test.go @@ -0,0 +1,72 @@ +package demo_protobuf3_optional + +import ( + "testing" + + "google.golang.org/protobuf/proto" +) + +func TestOptionalNilId(t *testing.T) { + noid := &WithOptional { + Username: "me", + Userid: nil, + } + t.Log(noid.String()) + wiremessage, err := proto.Marshal(noid) + if err != nil { + t.Fatal("marshal failed: ", err) + } + + unmarshaled := &WithOptional{} + if err := proto.Unmarshal(wiremessage, unmarshaled); err != nil { + t.Fatal("failed to unmarshal message: ", err) + } + t.Log("id: ", unmarshaled.Userid) + if unmarshaled.Userid != nil { + t.Fatalf("expected userid is nil, got %v", unmarshaled.Userid) + } +} + +func TestOptionalZeroId(t *testing.T) { + id := int64(0) + noid := &WithOptional { + Username: "me", + Userid: &id, + } + t.Log(noid.String()) + wiremessage, err := proto.Marshal(noid) + if err != nil { + t.Fatal("marshal failed: ", err) + } + + unmarshaled := &WithOptional{} + if err := proto.Unmarshal(wiremessage, unmarshaled); err != nil { + t.Fatal("failed to unmarshal message: ", err) + } + if unmarshaled.Userid == nil || *unmarshaled.Userid != 0 { + t.Fatalf("expected userid is non nil 0, got %v", unmarshaled.Userid) + } + t.Log("id: ", unmarshaled.Userid) +} + +func TestOptionalNonZeroId(t *testing.T) { + id := int64(1) + noid := &WithOptional { + Username: "me", + Userid: &id, + } + t.Log(noid.String()) + wiremessage, err := proto.Marshal(noid) + if err != nil { + t.Fatal("marshal failed: ", err) + } + + unmarshaled := &WithOptional{} + if err := proto.Unmarshal(wiremessage, unmarshaled); err != nil { + t.Fatal("failed to unmarshal message: ", err) + } + if unmarshaled.Userid == nil || *unmarshaled.Userid != 1 { + t.Fatalf("expected userid is non nil 1, got %v", unmarshaled.Userid) + } + t.Log("id: ", unmarshaled.Userid) +}