package protodesc
import (
)
func ( []filedesc.Enum, []*descriptorpb.EnumDescriptorProto) error {
for , := range {
:= &[]
if := .L2.ReservedNames.CheckValid(); != nil {
return errors.New("enum %q reserved names has %v", .FullName(), )
}
if := .L2.ReservedRanges.CheckValid(); != nil {
return errors.New("enum %q reserved ranges has %v", .FullName(), )
}
if len(.GetValue()) == 0 {
return errors.New("enum %q must contain at least one value declaration", .FullName())
}
:= .GetOptions().GetAllowAlias()
:= false
for := 0; < .Values().Len(); ++ {
:= .Values().Get()
if := .Values().ByNumber(.Number()); != {
= true
if ! {
return errors.New("enum %q has conflicting non-aliased values on number %d: %q with %q", .FullName(), .Number(), .Name(), .Name())
}
}
}
if && ! {
return errors.New("enum %q allows aliases, but none were found", .FullName())
}
if .Syntax() == protoreflect.Proto3 {
if := .Values().Get(0); .Number() != 0 {
return errors.New("enum %q using proto3 semantics must have zero number for the first value", .FullName())
}
:= map[string]protoreflect.EnumValueDescriptor{}
:= strings.Replace(strings.ToLower(string(.Name())), "_", "", -1)
for := 0; < .Values().Len(); ++ {
:= .Values().Get()
:= strs.EnumValueName(strs.TrimEnumPrefix(string(.Name()), ))
if , := []; && .Number() != .Number() {
return errors.New("enum %q using proto3 semantics has conflict: %q with %q", .FullName(), .Name(), .Name())
}
[] =
}
}
for , := range .GetValue() {
:= &.L2.Values.List[]
if .Number == nil {
return errors.New("enum value %q must have a specified number", .FullName())
}
if .L2.ReservedNames.Has(.Name()) {
return errors.New("enum value %q must not use reserved name", .FullName())
}
if .L2.ReservedRanges.Has(.Number()) {
return errors.New("enum value %q must not use reserved number %d", .FullName(), .Number())
}
}
}
return nil
}
func ( []filedesc.Message, []*descriptorpb.DescriptorProto) error {
for , := range {
:= &[]
:= .GetOptions().GetMessageSetWireFormat()
if := .L2.ReservedNames.CheckValid(); != nil {
return errors.New("message %q reserved names has %v", .FullName(), )
}
if := .L2.ReservedRanges.CheckValid(); != nil {
return errors.New("message %q reserved ranges has %v", .FullName(), )
}
if := .L2.ExtensionRanges.CheckValid(); != nil {
return errors.New("message %q extension ranges has %v", .FullName(), )
}
if := (*filedesc.FieldRanges).CheckOverlap(&.L2.ReservedRanges, &.L2.ExtensionRanges); != nil {
return errors.New("message %q reserved and extension ranges has %v", .FullName(), )
}
for := 0; < .Fields().Len(); ++ {
:= .Fields().Get()
if := .Fields().ByNumber(.Number()); != {
return errors.New("message %q has conflicting fields: %q with %q", .FullName(), .Name(), .Name())
}
}
if && !flags.ProtoLegacy {
return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", .FullName())
}
if && (.Syntax() != protoreflect.Proto2 || .Fields().Len() > 0 || .ExtensionRanges().Len() == 0) {
return errors.New("message %q is an invalid proto1 MessageSet", .FullName())
}
if .Syntax() == protoreflect.Proto3 {
if .ExtensionRanges().Len() > 0 {
return errors.New("message %q using proto3 semantics cannot have extension ranges", .FullName())
}
:= map[string]protoreflect.FieldDescriptor{}
for := 0; < .Fields().Len(); ++ {
:= .Fields().Get()
:= strings.Replace(strings.ToLower(string(.Name())), "_", "", -1)
if , := []; {
return errors.New("message %q using proto3 semantics has conflict: %q with %q", .FullName(), .Name(), .Name())
}
[] =
}
}
for , := range .GetField() {
:= &.L2.Fields.List[]
if .L2.ReservedNames.Has(.Name()) {
return errors.New("message field %q must not use reserved name", .FullName())
}
if !.Number().IsValid() {
return errors.New("message field %q has an invalid number: %d", .FullName(), .Number())
}
if !.Cardinality().IsValid() {
return errors.New("message field %q has an invalid cardinality: %d", .FullName(), .Cardinality())
}
if .L2.ReservedRanges.Has(.Number()) {
return errors.New("message field %q must not use reserved number %d", .FullName(), .Number())
}
if .L2.ExtensionRanges.Has(.Number()) {
return errors.New("message field %q with number %d in extension range", .FullName(), .Number())
}
if .Extendee != nil {
return errors.New("message field %q may not have extendee: %q", .FullName(), .GetExtendee())
}
if .L1.IsProto3Optional {
if .Syntax() != protoreflect.Proto3 {
return errors.New("message field %q under proto3 optional semantics must be specified in the proto3 syntax", .FullName())
}
if .Cardinality() != protoreflect.Optional {
return errors.New("message field %q under proto3 optional semantics must have optional cardinality", .FullName())
}
if .ContainingOneof() != nil && .ContainingOneof().Fields().Len() != 1 {
return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", .FullName())
}
}
if .IsWeak() && !flags.ProtoLegacy {
return errors.New("message field %q is a weak field, which is a legacy proto1 feature that is no longer supported", .FullName())
}
if .IsWeak() && (.Syntax() != protoreflect.Proto2 || !isOptionalMessage() || .ContainingOneof() != nil) {
return errors.New("message field %q may only be weak for an optional message", .FullName())
}
if .IsPacked() && !isPackable() {
return errors.New("message field %q is not packable", .FullName())
}
if := checkValidGroup(); != nil {
return errors.New("message field %q is an invalid group: %v", .FullName(), )
}
if := checkValidMap(); != nil {
return errors.New("message field %q is an invalid map: %v", .FullName(), )
}
if .Syntax() == protoreflect.Proto3 {
if .Cardinality() == protoreflect.Required {
return errors.New("message field %q using proto3 semantics cannot be required", .FullName())
}
if .Enum() != nil && !.Enum().IsPlaceholder() && .Enum().Syntax() != protoreflect.Proto3 {
return errors.New("message field %q using proto3 semantics may only depend on a proto3 enum", .FullName())
}
}
}
:= false
for := range .GetOneofDecl() {
:= &.L2.Oneofs.List[]
if .Fields().Len() == 0 {
return errors.New("message oneof %q must contain at least one field declaration", .FullName())
}
if := .Fields().Len(); -1 != (.Fields().Get(-1).Index() - .Fields().Get(0).Index()) {
return errors.New("message oneof %q must have consecutively declared fields", .FullName())
}
if .IsSynthetic() {
= true
continue
}
if !.IsSynthetic() && {
return errors.New("message oneof %q must be declared before synthetic oneofs", .FullName())
}
for := 0; < .Fields().Len(); ++ {
:= .Fields().Get()
if .Cardinality() != protoreflect.Optional {
return errors.New("message field %q belongs in a oneof and must be optional", .FullName())
}
if .IsWeak() {
return errors.New("message field %q belongs in a oneof and must not be a weak reference", .FullName())
}
}
}
if := validateEnumDeclarations(.L1.Enums.List, .GetEnumType()); != nil {
return
}
if := (.L1.Messages.List, .GetNestedType()); != nil {
return
}
if := validateExtensionDeclarations(.L1.Extensions.List, .GetExtension()); != nil {
return
}
}
return nil
}
func ( []filedesc.Extension, []*descriptorpb.FieldDescriptorProto) error {
for , := range {
:= &[]
if := .Number(); < 0 || (protowire.FirstReservedNumber <= && <= protowire.LastReservedNumber) {
return errors.New("extension field %q has an invalid number: %d", .FullName(), .Number())
}
if !.Cardinality().IsValid() || .Cardinality() == protoreflect.Required {
return errors.New("extension field %q has an invalid cardinality: %d", .FullName(), .Cardinality())
}
if .JsonName != nil {
if .GetJsonName() != strs.JSONCamelCase(string(.Name())) {
return errors.New("extension field %q may not have an explicitly set JSON name: %q", .FullName(), .GetJsonName())
}
}
if .OneofIndex != nil {
return errors.New("extension field %q may not be part of a oneof", .FullName())
}
if := .ContainingMessage(); !.IsPlaceholder() {
if !.ExtensionRanges().Has(.Number()) {
return errors.New("extension field %q extends %q with non-extension field number: %d", .FullName(), .FullName(), .Number())
}
:= .Options().(*descriptorpb.MessageOptions).GetMessageSetWireFormat()
if && !isOptionalMessage() {
return errors.New("extension field %q extends MessageSet and must be an optional message", .FullName())
}
if ! && !.Number().IsValid() {
return errors.New("extension field %q has an invalid number: %d", .FullName(), .Number())
}
}
if .GetOptions().GetWeak() {
return errors.New("extension field %q cannot be a weak reference", .FullName())
}
if .IsPacked() && !isPackable() {
return errors.New("extension field %q is not packable", .FullName())
}
if := checkValidGroup(); != nil {
return errors.New("extension field %q is an invalid group: %v", .FullName(), )
}
if := .Message(); != nil && .IsMapEntry() {
return errors.New("extension field %q cannot be a map entry", .FullName())
}
if .Syntax() == protoreflect.Proto3 {
switch .ContainingMessage().FullName() {
case (*descriptorpb.FileOptions)(nil).ProtoReflect().Descriptor().FullName():
case (*descriptorpb.EnumOptions)(nil).ProtoReflect().Descriptor().FullName():
case (*descriptorpb.EnumValueOptions)(nil).ProtoReflect().Descriptor().FullName():
case (*descriptorpb.MessageOptions)(nil).ProtoReflect().Descriptor().FullName():
case (*descriptorpb.FieldOptions)(nil).ProtoReflect().Descriptor().FullName():
case (*descriptorpb.OneofOptions)(nil).ProtoReflect().Descriptor().FullName():
case (*descriptorpb.ExtensionRangeOptions)(nil).ProtoReflect().Descriptor().FullName():
case (*descriptorpb.ServiceOptions)(nil).ProtoReflect().Descriptor().FullName():
case (*descriptorpb.MethodOptions)(nil).ProtoReflect().Descriptor().FullName():
default:
return errors.New("extension field %q cannot be declared in proto3 unless extended descriptor options", .FullName())
}
}
}
return nil
}
func ( protoreflect.FieldDescriptor) bool {
return (.Kind() == 0 || .Kind() == protoreflect.MessageKind) && .Cardinality() == protoreflect.Optional
}
func ( protoreflect.FieldDescriptor) bool {
switch .Kind() {
case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
return false
}
return .IsList()
}
func ( protoreflect.FieldDescriptor) error {
:= .Message()
switch {
case .Kind() != protoreflect.GroupKind:
return nil
case .Syntax() != protoreflect.Proto2:
return errors.New("invalid under proto2 semantics")
case == nil || .IsPlaceholder():
return errors.New("message must be resolvable")
case .FullName().Parent() != .FullName().Parent():
return errors.New("message and field must be declared in the same scope")
case !unicode.IsUpper(rune(.Name()[0])):
return errors.New("message name must start with an uppercase")
case .Name() != protoreflect.Name(strings.ToLower(string(.Name()))):
return errors.New("field name must be lowercased form of the message name")
}
return nil
}
func ( protoreflect.FieldDescriptor) error {
:= .Message()
switch {
case == nil || !.IsMapEntry():
return nil
case .FullName().Parent() != .FullName().Parent():
return errors.New("message and field must be declared in the same scope")
case .Name() != protoreflect.Name(strs.MapEntryName(string(.Name()))):
return errors.New("incorrect implicit map entry name")
case .Cardinality() != protoreflect.Repeated:
return errors.New("field must be repeated")
case .Fields().Len() != 2:
return errors.New("message must have exactly two fields")
case .ExtensionRanges().Len() > 0:
return errors.New("message must not have any extension ranges")
case .Enums().Len()+.Messages().Len()+.Extensions().Len() > 0:
return errors.New("message must not have any nested declarations")
}
:= .Fields().Get(0)
:= .Fields().Get(1)
switch {
case .Name() != genid.MapEntry_Key_field_name || .Number() != genid.MapEntry_Key_field_number || .Cardinality() != protoreflect.Optional || .ContainingOneof() != nil || .HasDefault():
return errors.New("invalid key field")
case .Name() != genid.MapEntry_Value_field_name || .Number() != genid.MapEntry_Value_field_number || .Cardinality() != protoreflect.Optional || .ContainingOneof() != nil || .HasDefault():
return errors.New("invalid value field")
}
switch .Kind() {
case protoreflect.BoolKind:
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
case protoreflect.StringKind:
default:
return errors.New("invalid key kind: %v", .Kind())
}
if := .Enum(); != nil && .Values().Len() > 0 && .Values().Get(0).Number() != 0 {
return errors.New("map enum value must have zero number for the first value")
}
return nil
}