diff --git a/entproto/adapter.go b/entproto/adapter.go index 3c42e16c7..4232ab982 100644 --- a/entproto/adapter.go +++ b/entproto/adapter.go @@ -39,6 +39,7 @@ const ( var ( ErrSchemaSkipped = errors.New("entproto: schema not annotated with Generate=true") repeatedFieldLabel = descriptorpb.FieldDescriptorProto_LABEL_REPEATED + optionalFieldLabel = descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL wktsPaths = map[string]string{ // TODO: handle more Well-Known proto types "google.protobuf.Timestamp": "google/protobuf/timestamp.proto", @@ -324,8 +325,7 @@ func (a *Adapter) toProtoMessageDescriptor(genType *gen.Type) (*descriptorpb.Des if _, ok := f.Annotations[SkipAnnotation]; ok { continue } - - protoField, err := toProtoFieldDescriptor(f) + protoField, err := toProtoFieldDescriptor(f, msgAnnot.EnableOptionalLabel) if err != nil { return nil, err } @@ -453,7 +453,7 @@ func toProtoEnumDescriptor(fld *gen.Field) (*descriptorpb.EnumDescriptorProto, e return dp, nil } -func toProtoFieldDescriptor(f *gen.Field) (*descriptorpb.FieldDescriptorProto, error) { +func toProtoFieldDescriptor(f *gen.Field, enableOptionalLabel bool) (*descriptorpb.FieldDescriptorProto, error) { fieldDesc := &descriptorpb.FieldDescriptorProto{ Name: &f.Name, } @@ -473,7 +473,7 @@ func toProtoFieldDescriptor(f *gen.Field) (*descriptorpb.FieldDescriptorProto, e } return fieldDesc, nil } - typeDetails, err := extractProtoTypeDetails(f) + typeDetails, err := extractProtoTypeDetails(f, enableOptionalLabel) if err != nil { return nil, err } @@ -483,19 +483,21 @@ func toProtoFieldDescriptor(f *gen.Field) (*descriptorpb.FieldDescriptorProto, e } if typeDetails.repeated { fieldDesc.Label = &repeatedFieldLabel + } else if typeDetails.optional { + fieldDesc.Label = &optionalFieldLabel } return fieldDesc, nil } -func extractProtoTypeDetails(f *gen.Field) (fieldType, error) { +func extractProtoTypeDetails(f *gen.Field, enableOptionalLabel bool) (fieldType, error) { if f.Type.Type == field.TypeJSON { - return extractJSONDetails(f) + return extractJSONDetails(f) // repeat fields are not required for optional label. } cfg, ok := typeMap[f.Type.Type] if !ok || cfg.unsupported { return fieldType{}, unsupportedTypeError{Type: f.Type} } - if f.Optional { + if f.Optional && !enableOptionalLabel { if cfg.optionalType == "" { return fieldType{}, unsupportedTypeError{Type: f.Type} } @@ -511,6 +513,7 @@ func extractProtoTypeDetails(f *gen.Field) (fieldType, error) { return fieldType{ protoType: cfg.pbType, messageName: name, + optional: f.Optional && enableOptionalLabel, }, nil } @@ -549,6 +552,7 @@ type fieldType struct { messageName string protoType descriptorpb.FieldDescriptorProto_Type repeated bool + optional bool } func strptr(s string) *string { diff --git a/entproto/message.go b/entproto/message.go index b386547ae..30c357171 100644 --- a/entproto/message.go +++ b/entproto/message.go @@ -55,9 +55,18 @@ func PackageName(pkg string) MessageOption { } } +// EnableOptionalLabel enables the optional label in the generated protobuf message instead of google/protobuf/wrappers.proto +func EnableOptionalLabel() MessageOption { + return func(msg *message) { + msg.EnableOptionalLabel = true + } +} + type message struct { Generate bool Package string + + EnableOptionalLabel bool } func (m message) Name() string { diff --git a/entproto/service.go b/entproto/service.go index bf8dec67b..6a5a88b44 100644 --- a/entproto/service.go +++ b/entproto/service.go @@ -123,7 +123,7 @@ var plural = gen.Funcs["plural"].(func(string) string) func (a *Adapter) genMethodProtos(genType *gen.Type, m Method) (methodResources, error) { input := &descriptorpb.DescriptorProto{} - idField, err := toProtoFieldDescriptor(genType.ID) + idField, err := toProtoFieldDescriptor(genType.ID, false) if err != nil { return methodResources{}, err }