// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package filedesc

import (
	"bytes"
	"fmt"
	"strings"
	"sync"
	"sync/atomic"

	"google.golang.org/protobuf/internal/descfmt"
	"google.golang.org/protobuf/internal/descopts"
	"google.golang.org/protobuf/internal/encoding/defval"
	"google.golang.org/protobuf/internal/encoding/messageset"
	"google.golang.org/protobuf/internal/genid"
	"google.golang.org/protobuf/internal/pragma"
	"google.golang.org/protobuf/internal/strs"
	"google.golang.org/protobuf/reflect/protoreflect"
)

// Edition is an Enum for proto2.Edition
type Edition int32

// These values align with the value of Enum in descriptor.proto which allows
// direct conversion between the proto enum and this enum.
const (
	EditionUnknown     Edition = 0
	EditionProto2      Edition = 998
	EditionProto3      Edition = 999
	Edition2023        Edition = 1000
	Edition2024        Edition = 1001
	EditionUnsupported Edition = 100000
)

// The types in this file may have a suffix:
//	• L0: Contains fields common to all descriptors (except File) and
//	must be initialized up front.
//	• L1: Contains fields specific to a descriptor and
//	must be initialized up front. If the associated proto uses Editions, the
//  Editions features must always be resolved. If not explicitly set, the
//  appropriate default must be resolved and set.
//	• L2: Contains fields that are lazily initialized when constructing
//	from the raw file descriptor. When constructing as a literal, the L2
//	fields must be initialized up front.
//
// The types are exported so that packages like reflect/protodesc can
// directly construct descriptors.

type (
	File struct {
		fileRaw
		L1 FileL1

		once uint32     // atomically set if L2 is valid
		mu   sync.Mutex // protects L2
		L2   *FileL2
	}
	FileL1 struct {
		Syntax  protoreflect.Syntax
		Edition Edition // Only used if Syntax == Editions
		Path    string
		Package protoreflect.FullName

		Enums      Enums
		Messages   Messages
		Extensions Extensions
		Services   Services

		EditionFeatures EditionFeatures
	}
	FileL2 struct {
		Options   func() protoreflect.ProtoMessage
		Imports   FileImports
		Locations SourceLocations
	}

	// EditionFeatures is a frequently-instantiated struct, so please take care
	// to minimize padding when adding new fields to this struct (add them in
	// the right place/order).
	EditionFeatures struct {
		// StripEnumPrefix determines if the plugin generates enum value
		// constants as-is, with their prefix stripped, or both variants.
		StripEnumPrefix int

		// IsFieldPresence is true if field_presence is EXPLICIT
		// https://protobuf.dev/editions/features/#field_presence
		IsFieldPresence bool

		// IsFieldPresence is true if field_presence is LEGACY_REQUIRED
		// https://protobuf.dev/editions/features/#field_presence
		IsLegacyRequired bool

		// IsOpenEnum is true if enum_type is OPEN
		// https://protobuf.dev/editions/features/#enum_type
		IsOpenEnum bool

		// IsPacked is true if repeated_field_encoding is PACKED
		// https://protobuf.dev/editions/features/#repeated_field_encoding
		IsPacked bool

		// IsUTF8Validated is true if utf_validation is VERIFY
		// https://protobuf.dev/editions/features/#utf8_validation
		IsUTF8Validated bool

		// IsDelimitedEncoded is true if message_encoding is DELIMITED
		// https://protobuf.dev/editions/features/#message_encoding
		IsDelimitedEncoded bool

		// IsJSONCompliant is true if json_format is ALLOW
		// https://protobuf.dev/editions/features/#json_format
		IsJSONCompliant bool

		// GenerateLegacyUnmarshalJSON determines if the plugin generates the
		// UnmarshalJSON([]byte) error method for enums.
		GenerateLegacyUnmarshalJSON bool
		// APILevel controls which API (Open, Hybrid or Opaque) should be used
		// for generated code (.pb.go files).
		APILevel int
	}
)

func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
func (fd *File) Parent() protoreflect.Descriptor         { return nil }
func (fd *File) Index() int                              { return 0 }
func (fd *File) Syntax() protoreflect.Syntax             { return fd.L1.Syntax }

// Not exported and just used to reconstruct the original FileDescriptor proto
func (fd *File) Edition() int32                  { return int32(fd.L1.Edition) }
func (fd *File) Name() protoreflect.Name         { return fd.L1.Package.Name() }
func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package }
func (fd *File) IsPlaceholder() bool             { return false }
func (fd *File) Options() protoreflect.ProtoMessage {
	if f := fd.lazyInit().Options; f != nil {
		return f()
	}
	return descopts.File
}
func (fd *File) Path() string                                  { return fd.L1.Path }
func (fd *File) Package() protoreflect.FullName                { return fd.L1.Package }
func (fd *File) Imports() protoreflect.FileImports             { return &fd.lazyInit().Imports }
func (fd *File) Enums() protoreflect.EnumDescriptors           { return &fd.L1.Enums }
func (fd *File) Messages() protoreflect.MessageDescriptors     { return &fd.L1.Messages }
func (fd *File) Extensions() protoreflect.ExtensionDescriptors { return &fd.L1.Extensions }
func (fd *File) Services() protoreflect.ServiceDescriptors     { return &fd.L1.Services }
func (fd *File) SourceLocations() protoreflect.SourceLocations { return &fd.lazyInit().Locations }
func (fd *File) Format(s fmt.State, r rune)                    { descfmt.FormatDesc(s, r, fd) }
func (fd *File) ProtoType(protoreflect.FileDescriptor)         {}
func (fd *File) ProtoInternal(pragma.DoNotImplement)           {}

func (fd *File) lazyInit() *FileL2 {
	if atomic.LoadUint32(&fd.once) == 0 {
		fd.lazyInitOnce()
	}
	return fd.L2
}

func (fd *File) lazyInitOnce() {
	fd.mu.Lock()
	if fd.L2 == nil {
		fd.lazyRawInit() // recursively initializes all L2 structures
	}
	atomic.StoreUint32(&fd.once, 1)
	fd.mu.Unlock()
}

// GoPackagePath is a pseudo-internal API for determining the Go package path
// that this file descriptor is declared in.
//
// WARNING: This method is exempt from the compatibility promise and may be
// removed in the future without warning.
func (fd *File) GoPackagePath() string {
	return fd.builder.GoPackagePath
}

type (
	Enum struct {
		Base
		L1 EnumL1
		L2 *EnumL2 // protected by fileDesc.once
	}
	EnumL1 struct {
		eagerValues bool // controls whether EnumL2.Values is already populated

		EditionFeatures EditionFeatures
	}
	EnumL2 struct {
		Options        func() protoreflect.ProtoMessage
		Values         EnumValues
		ReservedNames  Names
		ReservedRanges EnumRanges
	}

	EnumValue struct {
		Base
		L1 EnumValueL1
	}
	EnumValueL1 struct {
		Options func() protoreflect.ProtoMessage
		Number  protoreflect.EnumNumber
	}
)

func (ed *Enum) Options() protoreflect.ProtoMessage {
	if f := ed.lazyInit().Options; f != nil {
		return f()
	}
	return descopts.Enum
}
func (ed *Enum) Values() protoreflect.EnumValueDescriptors {
	if ed.L1.eagerValues {
		return &ed.L2.Values
	}
	return &ed.lazyInit().Values
}
func (ed *Enum) ReservedNames() protoreflect.Names       { return &ed.lazyInit().ReservedNames }
func (ed *Enum) ReservedRanges() protoreflect.EnumRanges { return &ed.lazyInit().ReservedRanges }
func (ed *Enum) Format(s fmt.State, r rune)              { descfmt.FormatDesc(s, r, ed) }
func (ed *Enum) ProtoType(protoreflect.EnumDescriptor)   {}
func (ed *Enum) lazyInit() *EnumL2 {
	ed.L0.ParentFile.lazyInit() // implicitly initializes L2
	return ed.L2
}
func (ed *Enum) IsClosed() bool {
	return !ed.L1.EditionFeatures.IsOpenEnum
}

func (ed *EnumValue) Options() protoreflect.ProtoMessage {
	if f := ed.L1.Options; f != nil {
		return f()
	}
	return descopts.EnumValue
}
func (ed *EnumValue) Number() protoreflect.EnumNumber            { return ed.L1.Number }
func (ed *EnumValue) Format(s fmt.State, r rune)                 { descfmt.FormatDesc(s, r, ed) }
func (ed *EnumValue) ProtoType(protoreflect.EnumValueDescriptor) {}

type (
	Message struct {
		Base
		L1 MessageL1
		L2 *MessageL2 // protected by fileDesc.once
	}
	MessageL1 struct {
		Enums        Enums
		Messages     Messages
		Extensions   Extensions
		IsMapEntry   bool // promoted from google.protobuf.MessageOptions
		IsMessageSet bool // promoted from google.protobuf.MessageOptions

		EditionFeatures EditionFeatures
	}
	MessageL2 struct {
		Options               func() protoreflect.ProtoMessage
		Fields                Fields
		Oneofs                Oneofs
		ReservedNames         Names
		ReservedRanges        FieldRanges
		RequiredNumbers       FieldNumbers // must be consistent with Fields.Cardinality
		ExtensionRanges       FieldRanges
		ExtensionRangeOptions []func() protoreflect.ProtoMessage // must be same length as ExtensionRanges
	}

	Field struct {
		Base
		L1 FieldL1
	}
	FieldL1 struct {
		Options          func() protoreflect.ProtoMessage
		Number           protoreflect.FieldNumber
		Cardinality      protoreflect.Cardinality // must be consistent with Message.RequiredNumbers
		Kind             protoreflect.Kind
		StringName       stringName
		IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
		IsLazy           bool // promoted from google.protobuf.FieldOptions
		Default          defaultValue
		ContainingOneof  protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
		Enum             protoreflect.EnumDescriptor
		Message          protoreflect.MessageDescriptor

		EditionFeatures EditionFeatures
	}

	Oneof struct {
		Base
		L1 OneofL1
	}
	OneofL1 struct {
		Options func() protoreflect.ProtoMessage
		Fields  OneofFields // must be consistent with Message.Fields.ContainingOneof

		EditionFeatures EditionFeatures
	}
)

func (md *Message) Options() protoreflect.ProtoMessage {
	if f := md.lazyInit().Options; f != nil {
		return f()
	}
	return descopts.Message
}
func (md *Message) IsMapEntry() bool                           { return md.L1.IsMapEntry }
func (md *Message) Fields() protoreflect.FieldDescriptors      { return &md.lazyInit().Fields }
func (md *Message) Oneofs() protoreflect.OneofDescriptors      { return &md.lazyInit().Oneofs }
func (md *Message) ReservedNames() protoreflect.Names          { return &md.lazyInit().ReservedNames }
func (md *Message) ReservedRanges() protoreflect.FieldRanges   { return &md.lazyInit().ReservedRanges }
func (md *Message) RequiredNumbers() protoreflect.FieldNumbers { return &md.lazyInit().RequiredNumbers }
func (md *Message) ExtensionRanges() protoreflect.FieldRanges  { return &md.lazyInit().ExtensionRanges }
func (md *Message) ExtensionRangeOptions(i int) protoreflect.ProtoMessage {
	if f := md.lazyInit().ExtensionRangeOptions[i]; f != nil {
		return f()
	}
	return descopts.ExtensionRange
}
func (md *Message) Enums() protoreflect.EnumDescriptors           { return &md.L1.Enums }
func (md *Message) Messages() protoreflect.MessageDescriptors     { return &md.L1.Messages }
func (md *Message) Extensions() protoreflect.ExtensionDescriptors { return &md.L1.Extensions }
func (md *Message) ProtoType(protoreflect.MessageDescriptor)      {}
func (md *Message) Format(s fmt.State, r rune)                    { descfmt.FormatDesc(s, r, md) }
func (md *Message) lazyInit() *MessageL2 {
	md.L0.ParentFile.lazyInit() // implicitly initializes L2
	return md.L2
}

// IsMessageSet is a pseudo-internal API for checking whether a message
// should serialize in the proto1 message format.
//
// WARNING: This method is exempt from the compatibility promise and may be
// removed in the future without warning.
func (md *Message) IsMessageSet() bool {
	return md.L1.IsMessageSet
}

func (fd *Field) Options() protoreflect.ProtoMessage {
	if f := fd.L1.Options; f != nil {
		return f()
	}
	return descopts.Field
}
func (fd *Field) Number() protoreflect.FieldNumber      { return fd.L1.Number }
func (fd *Field) Cardinality() protoreflect.Cardinality { return fd.L1.Cardinality }
func (fd *Field) Kind() protoreflect.Kind {
	return fd.L1.Kind
}
func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON }
func (fd *Field) JSONName() string  { return fd.L1.StringName.getJSON(fd) }
func (fd *Field) TextName() string  { return fd.L1.StringName.getText(fd) }
func (fd *Field) HasPresence() bool {
	if fd.L1.Cardinality == protoreflect.Repeated {
		return false
	}
	return fd.IsExtension() || fd.L1.EditionFeatures.IsFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil
}
func (fd *Field) HasOptionalKeyword() bool {
	return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional
}
func (fd *Field) IsPacked() bool {
	if fd.L1.Cardinality != protoreflect.Repeated {
		return false
	}
	switch fd.L1.Kind {
	case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
		return false
	}
	return fd.L1.EditionFeatures.IsPacked
}
func (fd *Field) IsExtension() bool { return false }
func (fd *Field) IsWeak() bool      { return false }
func (fd *Field) IsLazy() bool      { return fd.L1.IsLazy }
func (fd *Field) IsList() bool      { return fd.Cardinality() == protoreflect.Repeated && !fd.IsMap() }
func (fd *Field) IsMap() bool       { return fd.Message() != nil && fd.Message().IsMapEntry() }
func (fd *Field) MapKey() protoreflect.FieldDescriptor {
	if !fd.IsMap() {
		return nil
	}
	return fd.Message().Fields().ByNumber(genid.MapEntry_Key_field_number)
}
func (fd *Field) MapValue() protoreflect.FieldDescriptor {
	if !fd.IsMap() {
		return nil
	}
	return fd.Message().Fields().ByNumber(genid.MapEntry_Value_field_number)
}
func (fd *Field) HasDefault() bool                                   { return fd.L1.Default.has }
func (fd *Field) Default() protoreflect.Value                        { return fd.L1.Default.get(fd) }
func (fd *Field) DefaultEnumValue() protoreflect.EnumValueDescriptor { return fd.L1.Default.enum }
func (fd *Field) ContainingOneof() protoreflect.OneofDescriptor      { return fd.L1.ContainingOneof }
func (fd *Field) ContainingMessage() protoreflect.MessageDescriptor {
	return fd.L0.Parent.(protoreflect.MessageDescriptor)
}
func (fd *Field) Enum() protoreflect.EnumDescriptor {
	return fd.L1.Enum
}
func (fd *Field) Message() protoreflect.MessageDescriptor {
	return fd.L1.Message
}
func (fd *Field) IsMapEntry() bool {
	parent, ok := fd.L0.Parent.(protoreflect.MessageDescriptor)
	return ok && parent.IsMapEntry()
}
func (fd *Field) Format(s fmt.State, r rune)             { descfmt.FormatDesc(s, r, fd) }
func (fd *Field) ProtoType(protoreflect.FieldDescriptor) {}

// EnforceUTF8 is a pseudo-internal API to determine whether to enforce UTF-8
// validation for the string field. This exists for Google-internal use only
// since proto3 did not enforce UTF-8 validity prior to the open-source release.
// If this method does not exist, the default is to enforce valid UTF-8.
//
// WARNING: This method is exempt from the compatibility promise and may be
// removed in the future without warning.
func (fd *Field) EnforceUTF8() bool {
	return fd.L1.EditionFeatures.IsUTF8Validated
}

func (od *Oneof) IsSynthetic() bool {
	return od.L0.ParentFile.L1.Syntax == protoreflect.Proto3 && len(od.L1.Fields.List) == 1 && od.L1.Fields.List[0].HasOptionalKeyword()
}
func (od *Oneof) Options() protoreflect.ProtoMessage {
	if f := od.L1.Options; f != nil {
		return f()
	}
	return descopts.Oneof
}
func (od *Oneof) Fields() protoreflect.FieldDescriptors  { return &od.L1.Fields }
func (od *Oneof) Format(s fmt.State, r rune)             { descfmt.FormatDesc(s, r, od) }
func (od *Oneof) ProtoType(protoreflect.OneofDescriptor) {}

type (
	Extension struct {
		Base
		L1 ExtensionL1
		L2 *ExtensionL2 // protected by fileDesc.once
	}
	ExtensionL1 struct {
		Number          protoreflect.FieldNumber
		Extendee        protoreflect.MessageDescriptor
		Cardinality     protoreflect.Cardinality
		Kind            protoreflect.Kind
		IsLazy          bool
		EditionFeatures EditionFeatures
	}
	ExtensionL2 struct {
		Options          func() protoreflect.ProtoMessage
		StringName       stringName
		IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
		Default          defaultValue
		Enum             protoreflect.EnumDescriptor
		Message          protoreflect.MessageDescriptor
	}
)

func (xd *Extension) Options() protoreflect.ProtoMessage {
	if f := xd.lazyInit().Options; f != nil {
		return f()
	}
	return descopts.Field
}
func (xd *Extension) Number() protoreflect.FieldNumber      { return xd.L1.Number }
func (xd *Extension) Cardinality() protoreflect.Cardinality { return xd.L1.Cardinality }
func (xd *Extension) Kind() protoreflect.Kind               { return xd.L1.Kind }
func (xd *Extension) HasJSONName() bool                     { return xd.lazyInit().StringName.hasJSON }
func (xd *Extension) JSONName() string                      { return xd.lazyInit().StringName.getJSON(xd) }
func (xd *Extension) TextName() string                      { return xd.lazyInit().StringName.getText(xd) }
func (xd *Extension) HasPresence() bool                     { return xd.L1.Cardinality != protoreflect.Repeated }
func (xd *Extension) HasOptionalKeyword() bool {
	return (xd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && xd.L1.Cardinality == protoreflect.Optional) || xd.lazyInit().IsProto3Optional
}
func (xd *Extension) IsPacked() bool {
	if xd.L1.Cardinality != protoreflect.Repeated {
		return false
	}
	switch xd.L1.Kind {
	case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
		return false
	}
	return xd.L1.EditionFeatures.IsPacked
}
func (xd *Extension) IsExtension() bool                      { return true }
func (xd *Extension) IsWeak() bool                           { return false }
func (xd *Extension) IsLazy() bool                           { return xd.L1.IsLazy }
func (xd *Extension) IsList() bool                           { return xd.Cardinality() == protoreflect.Repeated }
func (xd *Extension) IsMap() bool                            { return false }
func (xd *Extension) MapKey() protoreflect.FieldDescriptor   { return nil }
func (xd *Extension) MapValue() protoreflect.FieldDescriptor { return nil }
func (xd *Extension) HasDefault() bool                       { return xd.lazyInit().Default.has }
func (xd *Extension) Default() protoreflect.Value            { return xd.lazyInit().Default.get(xd) }
func (xd *Extension) DefaultEnumValue() protoreflect.EnumValueDescriptor {
	return xd.lazyInit().Default.enum
}
func (xd *Extension) ContainingOneof() protoreflect.OneofDescriptor     { return nil }
func (xd *Extension) ContainingMessage() protoreflect.MessageDescriptor { return xd.L1.Extendee }
func (xd *Extension) Enum() protoreflect.EnumDescriptor                 { return xd.lazyInit().Enum }
func (xd *Extension) Message() protoreflect.MessageDescriptor           { return xd.lazyInit().Message }
func (xd *Extension) Format(s fmt.State, r rune)                        { descfmt.FormatDesc(s, r, xd) }
func (xd *Extension) ProtoType(protoreflect.FieldDescriptor)            {}
func (xd *Extension) ProtoInternal(pragma.DoNotImplement)               {}
func (xd *Extension) lazyInit() *ExtensionL2 {
	xd.L0.ParentFile.lazyInit() // implicitly initializes L2
	return xd.L2
}

type (
	Service struct {
		Base
		L1 ServiceL1
		L2 *ServiceL2 // protected by fileDesc.once
	}
	ServiceL1 struct{}
	ServiceL2 struct {
		Options func() protoreflect.ProtoMessage
		Methods Methods
	}

	Method struct {
		Base
		L1 MethodL1
	}
	MethodL1 struct {
		Options           func() protoreflect.ProtoMessage
		Input             protoreflect.MessageDescriptor
		Output            protoreflect.MessageDescriptor
		IsStreamingClient bool
		IsStreamingServer bool
	}
)

func (sd *Service) Options() protoreflect.ProtoMessage {
	if f := sd.lazyInit().Options; f != nil {
		return f()
	}
	return descopts.Service
}
func (sd *Service) Methods() protoreflect.MethodDescriptors  { return &sd.lazyInit().Methods }
func (sd *Service) Format(s fmt.State, r rune)               { descfmt.FormatDesc(s, r, sd) }
func (sd *Service) ProtoType(protoreflect.ServiceDescriptor) {}
func (sd *Service) ProtoInternal(pragma.DoNotImplement)      {}
func (sd *Service) lazyInit() *ServiceL2 {
	sd.L0.ParentFile.lazyInit() // implicitly initializes L2
	return sd.L2
}

func (md *Method) Options() protoreflect.ProtoMessage {
	if f := md.L1.Options; f != nil {
		return f()
	}
	return descopts.Method
}
func (md *Method) Input() protoreflect.MessageDescriptor   { return md.L1.Input }
func (md *Method) Output() protoreflect.MessageDescriptor  { return md.L1.Output }
func (md *Method) IsStreamingClient() bool                 { return md.L1.IsStreamingClient }
func (md *Method) IsStreamingServer() bool                 { return md.L1.IsStreamingServer }
func (md *Method) Format(s fmt.State, r rune)              { descfmt.FormatDesc(s, r, md) }
func (md *Method) ProtoType(protoreflect.MethodDescriptor) {}
func (md *Method) ProtoInternal(pragma.DoNotImplement)     {}

// Surrogate files are can be used to create standalone descriptors
// where the syntax is only information derived from the parent file.
var (
	SurrogateProto2      = &File{L1: FileL1{Syntax: protoreflect.Proto2}, L2: &FileL2{}}
	SurrogateProto3      = &File{L1: FileL1{Syntax: protoreflect.Proto3}, L2: &FileL2{}}
	SurrogateEdition2023 = &File{L1: FileL1{Syntax: protoreflect.Editions, Edition: Edition2023}, L2: &FileL2{}}
)

type (
	Base struct {
		L0 BaseL0
	}
	BaseL0 struct {
		FullName   protoreflect.FullName // must be populated
		ParentFile *File                 // must be populated
		Parent     protoreflect.Descriptor
		Index      int
	}
)

func (d *Base) Name() protoreflect.Name         { return d.L0.FullName.Name() }
func (d *Base) FullName() protoreflect.FullName { return d.L0.FullName }
func (d *Base) ParentFile() protoreflect.FileDescriptor {
	if d.L0.ParentFile == SurrogateProto2 || d.L0.ParentFile == SurrogateProto3 {
		return nil // surrogate files are not real parents
	}
	return d.L0.ParentFile
}
func (d *Base) Parent() protoreflect.Descriptor     { return d.L0.Parent }
func (d *Base) Index() int                          { return d.L0.Index }
func (d *Base) Syntax() protoreflect.Syntax         { return d.L0.ParentFile.Syntax() }
func (d *Base) IsPlaceholder() bool                 { return false }
func (d *Base) ProtoInternal(pragma.DoNotImplement) {}

type stringName struct {
	hasJSON  bool
	once     sync.Once
	nameJSON string
	nameText string
}

// InitJSON initializes the name. It is exported for use by other internal packages.
func (s *stringName) InitJSON(name string) {
	s.hasJSON = true
	s.nameJSON = name
}

// Returns true if this field is structured like the synthetic field of a proto2
// group. This allows us to expand our treatment of delimited fields without
// breaking proto2 files that have been upgraded to editions.
func isGroupLike(fd protoreflect.FieldDescriptor) bool {
	// Groups are always group types.
	if fd.Kind() != protoreflect.GroupKind {
		return false
	}

	// Group fields are always the lowercase type name.
	if strings.ToLower(string(fd.Message().Name())) != string(fd.Name()) {
		return false
	}

	// Groups could only be defined in the same file they're used.
	if fd.Message().ParentFile() != fd.ParentFile() {
		return false
	}

	// Group messages are always defined in the same scope as the field.  File
	// level extensions will compare NULL == NULL here, which is why the file
	// comparison above is necessary to ensure both come from the same file.
	if fd.IsExtension() {
		return fd.Parent() == fd.Message().Parent()
	}
	return fd.ContainingMessage() == fd.Message().Parent()
}

func (s *stringName) lazyInit(fd protoreflect.FieldDescriptor) *stringName {
	s.once.Do(func() {
		if fd.IsExtension() {
			// For extensions, JSON and text are formatted the same way.
			var name string
			if messageset.IsMessageSetExtension(fd) {
				name = string("[" + fd.FullName().Parent() + "]")
			} else {
				name = string("[" + fd.FullName() + "]")
			}
			s.nameJSON = name
			s.nameText = name
		} else {
			// Format the JSON name.
			if !s.hasJSON {
				s.nameJSON = strs.JSONCamelCase(string(fd.Name()))
			}

			// Format the text name.
			s.nameText = string(fd.Name())
			if isGroupLike(fd) {
				s.nameText = string(fd.Message().Name())
			}
		}
	})
	return s
}

func (s *stringName) getJSON(fd protoreflect.FieldDescriptor) string { return s.lazyInit(fd).nameJSON }
func (s *stringName) getText(fd protoreflect.FieldDescriptor) string { return s.lazyInit(fd).nameText }

func DefaultValue(v protoreflect.Value, ev protoreflect.EnumValueDescriptor) defaultValue {
	dv := defaultValue{has: v.IsValid(), val: v, enum: ev}
	if b, ok := v.Interface().([]byte); ok {
		// Store a copy of the default bytes, so that we can detect
		// accidental mutations of the original value.
		dv.bytes = append([]byte(nil), b...)
	}
	return dv
}

func unmarshalDefault(b []byte, k protoreflect.Kind, pf *File, ed protoreflect.EnumDescriptor) defaultValue {
	var evs protoreflect.EnumValueDescriptors
	if k == protoreflect.EnumKind {
		// If the enum is declared within the same file, be careful not to
		// blindly call the Values method, lest we bind ourselves in a deadlock.
		if e, ok := ed.(*Enum); ok && e.L0.ParentFile == pf {
			evs = &e.L2.Values
		} else {
			evs = ed.Values()
		}

		// If we are unable to resolve the enum dependency, use a placeholder
		// enum value since we will not be able to parse the default value.
		if ed.IsPlaceholder() && protoreflect.Name(b).IsValid() {
			v := protoreflect.ValueOfEnum(0)
			ev := PlaceholderEnumValue(ed.FullName().Parent().Append(protoreflect.Name(b)))
			return DefaultValue(v, ev)
		}
	}

	v, ev, err := defval.Unmarshal(string(b), k, evs, defval.Descriptor)
	if err != nil {
		panic(err)
	}
	return DefaultValue(v, ev)
}

type defaultValue struct {
	has   bool
	val   protoreflect.Value
	enum  protoreflect.EnumValueDescriptor
	bytes []byte
}

func (dv *defaultValue) get(fd protoreflect.FieldDescriptor) protoreflect.Value {
	// Return the zero value as the default if unpopulated.
	if !dv.has {
		if fd.Cardinality() == protoreflect.Repeated {
			return protoreflect.Value{}
		}
		switch fd.Kind() {
		case protoreflect.BoolKind:
			return protoreflect.ValueOfBool(false)
		case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
			return protoreflect.ValueOfInt32(0)
		case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
			return protoreflect.ValueOfInt64(0)
		case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
			return protoreflect.ValueOfUint32(0)
		case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
			return protoreflect.ValueOfUint64(0)
		case protoreflect.FloatKind:
			return protoreflect.ValueOfFloat32(0)
		case protoreflect.DoubleKind:
			return protoreflect.ValueOfFloat64(0)
		case protoreflect.StringKind:
			return protoreflect.ValueOfString("")
		case protoreflect.BytesKind:
			return protoreflect.ValueOfBytes(nil)
		case protoreflect.EnumKind:
			if evs := fd.Enum().Values(); evs.Len() > 0 {
				return protoreflect.ValueOfEnum(evs.Get(0).Number())
			}
			return protoreflect.ValueOfEnum(0)
		}
	}

	if len(dv.bytes) > 0 && !bytes.Equal(dv.bytes, dv.val.Bytes()) {
		// TODO: Avoid panic if we're running with the race detector
		// and instead spawn a goroutine that periodically resets
		// this value back to the original to induce a race.
		panic(fmt.Sprintf("detected mutation on the default bytes for %v", fd.FullName()))
	}
	return dv.val
}
