2019-06-06 13:01:53 -07:00
|
|
|
// 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"
|
2024-04-02 12:59:48 -07:00
|
|
|
"strings"
|
2019-06-06 13:01:53 -07:00
|
|
|
"sync"
|
|
|
|
"sync/atomic"
|
|
|
|
|
|
|
|
"google.golang.org/protobuf/internal/descfmt"
|
|
|
|
"google.golang.org/protobuf/internal/descopts"
|
|
|
|
"google.golang.org/protobuf/internal/encoding/defval"
|
2020-06-24 16:47:32 -07:00
|
|
|
"google.golang.org/protobuf/internal/encoding/messageset"
|
2020-06-19 13:17:06 -07:00
|
|
|
"google.golang.org/protobuf/internal/genid"
|
2019-06-06 13:01:53 -07:00
|
|
|
"google.golang.org/protobuf/internal/pragma"
|
2019-07-07 01:49:59 -07:00
|
|
|
"google.golang.org/protobuf/internal/strs"
|
2022-05-24 05:12:23 +09:00
|
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
2019-08-05 13:41:37 -07:00
|
|
|
"google.golang.org/protobuf/reflect/protoregistry"
|
2019-06-06 13:01:53 -07:00
|
|
|
)
|
|
|
|
|
2023-12-04 15:57:11 +01:00
|
|
|
// 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
|
|
|
|
EditionUnsupported Edition = 100000
|
|
|
|
)
|
|
|
|
|
2019-06-06 13:01:53 -07:00
|
|
|
// 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
|
2023-12-04 15:57:11 +01:00
|
|
|
// 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.
|
2019-06-06 13:01:53 -07:00
|
|
|
// • 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 {
|
2022-05-24 05:12:23 +09:00
|
|
|
Syntax protoreflect.Syntax
|
2023-12-04 15:57:11 +01:00
|
|
|
Edition Edition // Only used if Syntax == Editions
|
2019-06-06 13:01:53 -07:00
|
|
|
Path string
|
2022-05-24 05:12:23 +09:00
|
|
|
Package protoreflect.FullName
|
2019-06-06 13:01:53 -07:00
|
|
|
|
|
|
|
Enums Enums
|
|
|
|
Messages Messages
|
|
|
|
Extensions Extensions
|
|
|
|
Services Services
|
2023-12-04 15:57:11 +01:00
|
|
|
|
2024-01-16 10:33:13 +01:00
|
|
|
EditionFeatures EditionFeatures
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
FileL2 struct {
|
2022-05-24 05:12:23 +09:00
|
|
|
Options func() protoreflect.ProtoMessage
|
2019-06-18 01:02:13 -07:00
|
|
|
Imports FileImports
|
|
|
|
Locations SourceLocations
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
2023-12-04 15:57:11 +01:00
|
|
|
|
2024-01-16 10:33:13 +01:00
|
|
|
EditionFeatures struct {
|
2023-12-04 15:57:11 +01:00
|
|
|
// IsFieldPresence is true if field_presence is EXPLICIT
|
|
|
|
// https://protobuf.dev/editions/features/#field_presence
|
|
|
|
IsFieldPresence bool
|
2024-01-16 16:30:22 +01:00
|
|
|
// IsFieldPresence is true if field_presence is LEGACY_REQUIRED
|
|
|
|
// https://protobuf.dev/editions/features/#field_presence
|
|
|
|
IsLegacyRequired bool
|
2023-12-04 15:57:11 +01:00
|
|
|
// 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
|
2024-02-08 09:38:30 +01:00
|
|
|
// GenerateLegacyUnmarshalJSON determines if the plugin generates the
|
|
|
|
// UnmarshalJSON([]byte) error method for enums.
|
|
|
|
GenerateLegacyUnmarshalJSON bool
|
2023-12-04 15:57:11 +01:00
|
|
|
}
|
2019-06-06 13:01:53 -07:00
|
|
|
)
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
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 }
|
2024-03-20 13:23:30 +01:00
|
|
|
|
|
|
|
// 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 }
|
2022-05-24 05:12:23 +09:00
|
|
|
func (fd *File) Options() protoreflect.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := fd.lazyInit().Options; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.File
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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) {}
|
2019-06-06 13:01:53 -07:00
|
|
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2019-07-14 23:04:40 -07:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2019-06-06 13:01:53 -07:00
|
|
|
type (
|
|
|
|
Enum struct {
|
|
|
|
Base
|
|
|
|
L1 EnumL1
|
|
|
|
L2 *EnumL2 // protected by fileDesc.once
|
|
|
|
}
|
reflect/protoreflect: register all desciptors in Files
This change makes it such that Files now functionally registers all
descriptors in a file (not just enums, messages, extensions, and services),
but also including enum values, messages fields/oneofs, and service methods.
The ability to look up any descriptor by full name is needed to:
1) properly detect namespace conflicts on enum values
2) properly implement the relative name lookup logic in reflect/protodesc
The approach taken:
1) Assumes that a FileDescriptor has no internal name conflicts.
This will (in a future CL) be guaranteed by reflect/protodesc and
is guaranteed today by protoc for generated descriptors.
2) Observes that the only declarations that can possibly conflict
with another file are top-level declarations (i.e., enums, enum values,
messages, extensions, and services). Enum values are annoying
since they live in the same scope as the parent enum, rather than
being under the enum.
For the internal data structure of Files, we only register the top-level
declarations. This is the bare minimum needed to detect whether the file
being registered has any namespace conflicts with previously registered files.
We shift the effort to lookups, where we now need to peel off the end fragments
of a full name until we find a match in the internal registry. If a match
is found, we may need to descend into that declaration to find a nested
declaration by name.
For initialization, we modify internal/filedesc to initialize the
enum values for all top-level enums. This performance cost is offsetted
by the fact that Files.Register now avoids internally registering
nested enums, messages, and extensions.
For lookup, the cost has shifted from O(1) to O(N),
where N is the number of segments in the full name.
Top-level descriptors still have O(1) lookup times.
Nested descriptors have O(M) lookup times,
where M is the level of nesting within a single file.
Change-Id: I950163423431f04a503b6201ddcc20a62ccba017
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/183697
Reviewed-by: Damien Neil <dneil@google.com>
2019-06-21 14:25:16 -07:00
|
|
|
EnumL1 struct {
|
|
|
|
eagerValues bool // controls whether EnumL2.Values is already populated
|
2024-01-16 10:33:13 +01:00
|
|
|
|
|
|
|
EditionFeatures EditionFeatures
|
reflect/protoreflect: register all desciptors in Files
This change makes it such that Files now functionally registers all
descriptors in a file (not just enums, messages, extensions, and services),
but also including enum values, messages fields/oneofs, and service methods.
The ability to look up any descriptor by full name is needed to:
1) properly detect namespace conflicts on enum values
2) properly implement the relative name lookup logic in reflect/protodesc
The approach taken:
1) Assumes that a FileDescriptor has no internal name conflicts.
This will (in a future CL) be guaranteed by reflect/protodesc and
is guaranteed today by protoc for generated descriptors.
2) Observes that the only declarations that can possibly conflict
with another file are top-level declarations (i.e., enums, enum values,
messages, extensions, and services). Enum values are annoying
since they live in the same scope as the parent enum, rather than
being under the enum.
For the internal data structure of Files, we only register the top-level
declarations. This is the bare minimum needed to detect whether the file
being registered has any namespace conflicts with previously registered files.
We shift the effort to lookups, where we now need to peel off the end fragments
of a full name until we find a match in the internal registry. If a match
is found, we may need to descend into that declaration to find a nested
declaration by name.
For initialization, we modify internal/filedesc to initialize the
enum values for all top-level enums. This performance cost is offsetted
by the fact that Files.Register now avoids internally registering
nested enums, messages, and extensions.
For lookup, the cost has shifted from O(1) to O(N),
where N is the number of segments in the full name.
Top-level descriptors still have O(1) lookup times.
Nested descriptors have O(M) lookup times,
where M is the level of nesting within a single file.
Change-Id: I950163423431f04a503b6201ddcc20a62ccba017
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/183697
Reviewed-by: Damien Neil <dneil@google.com>
2019-06-21 14:25:16 -07:00
|
|
|
}
|
2019-06-06 13:01:53 -07:00
|
|
|
EnumL2 struct {
|
2022-05-24 05:12:23 +09:00
|
|
|
Options func() protoreflect.ProtoMessage
|
2019-06-06 13:01:53 -07:00
|
|
|
Values EnumValues
|
|
|
|
ReservedNames Names
|
|
|
|
ReservedRanges EnumRanges
|
|
|
|
}
|
|
|
|
|
|
|
|
EnumValue struct {
|
|
|
|
Base
|
|
|
|
L1 EnumValueL1
|
|
|
|
}
|
|
|
|
EnumValueL1 struct {
|
2022-05-24 05:12:23 +09:00
|
|
|
Options func() protoreflect.ProtoMessage
|
|
|
|
Number protoreflect.EnumNumber
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func (ed *Enum) Options() protoreflect.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := ed.lazyInit().Options; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.Enum
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
func (ed *Enum) Values() protoreflect.EnumValueDescriptors {
|
reflect/protoreflect: register all desciptors in Files
This change makes it such that Files now functionally registers all
descriptors in a file (not just enums, messages, extensions, and services),
but also including enum values, messages fields/oneofs, and service methods.
The ability to look up any descriptor by full name is needed to:
1) properly detect namespace conflicts on enum values
2) properly implement the relative name lookup logic in reflect/protodesc
The approach taken:
1) Assumes that a FileDescriptor has no internal name conflicts.
This will (in a future CL) be guaranteed by reflect/protodesc and
is guaranteed today by protoc for generated descriptors.
2) Observes that the only declarations that can possibly conflict
with another file are top-level declarations (i.e., enums, enum values,
messages, extensions, and services). Enum values are annoying
since they live in the same scope as the parent enum, rather than
being under the enum.
For the internal data structure of Files, we only register the top-level
declarations. This is the bare minimum needed to detect whether the file
being registered has any namespace conflicts with previously registered files.
We shift the effort to lookups, where we now need to peel off the end fragments
of a full name until we find a match in the internal registry. If a match
is found, we may need to descend into that declaration to find a nested
declaration by name.
For initialization, we modify internal/filedesc to initialize the
enum values for all top-level enums. This performance cost is offsetted
by the fact that Files.Register now avoids internally registering
nested enums, messages, and extensions.
For lookup, the cost has shifted from O(1) to O(N),
where N is the number of segments in the full name.
Top-level descriptors still have O(1) lookup times.
Nested descriptors have O(M) lookup times,
where M is the level of nesting within a single file.
Change-Id: I950163423431f04a503b6201ddcc20a62ccba017
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/183697
Reviewed-by: Damien Neil <dneil@google.com>
2019-06-21 14:25:16 -07:00
|
|
|
if ed.L1.eagerValues {
|
|
|
|
return &ed.L2.Values
|
|
|
|
}
|
|
|
|
return &ed.lazyInit().Values
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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) {}
|
2019-06-06 13:01:53 -07:00
|
|
|
func (ed *Enum) lazyInit() *EnumL2 {
|
|
|
|
ed.L0.ParentFile.lazyInit() // implicitly initializes L2
|
|
|
|
return ed.L2
|
|
|
|
}
|
2024-03-19 09:14:46 +01:00
|
|
|
func (ed *Enum) IsClosed() bool {
|
|
|
|
return !ed.L1.EditionFeatures.IsOpenEnum
|
|
|
|
}
|
2019-06-06 13:01:53 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func (ed *EnumValue) Options() protoreflect.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := ed.L1.Options; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.EnumValue
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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) {}
|
2019-06-06 13:01:53 -07:00
|
|
|
|
|
|
|
type (
|
|
|
|
Message struct {
|
|
|
|
Base
|
|
|
|
L1 MessageL1
|
|
|
|
L2 *MessageL2 // protected by fileDesc.once
|
|
|
|
}
|
|
|
|
MessageL1 struct {
|
2019-11-07 15:30:44 -08:00
|
|
|
Enums Enums
|
|
|
|
Messages Messages
|
|
|
|
Extensions Extensions
|
|
|
|
IsMapEntry bool // promoted from google.protobuf.MessageOptions
|
|
|
|
IsMessageSet bool // promoted from google.protobuf.MessageOptions
|
2024-01-16 10:33:13 +01:00
|
|
|
|
|
|
|
EditionFeatures EditionFeatures
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
MessageL2 struct {
|
2022-05-24 05:12:23 +09:00
|
|
|
Options func() protoreflect.ProtoMessage
|
2019-06-06 13:01:53 -07:00
|
|
|
Fields Fields
|
|
|
|
Oneofs Oneofs
|
|
|
|
ReservedNames Names
|
|
|
|
ReservedRanges FieldRanges
|
|
|
|
RequiredNumbers FieldNumbers // must be consistent with Fields.Cardinality
|
|
|
|
ExtensionRanges FieldRanges
|
2022-05-24 05:12:23 +09:00
|
|
|
ExtensionRangeOptions []func() protoreflect.ProtoMessage // must be same length as ExtensionRanges
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Field struct {
|
|
|
|
Base
|
|
|
|
L1 FieldL1
|
|
|
|
}
|
|
|
|
FieldL1 struct {
|
2022-05-24 05:12:23 +09:00
|
|
|
Options func() protoreflect.ProtoMessage
|
|
|
|
Number protoreflect.FieldNumber
|
|
|
|
Cardinality protoreflect.Cardinality // must be consistent with Message.RequiredNumbers
|
|
|
|
Kind protoreflect.Kind
|
2020-06-24 16:47:32 -07:00
|
|
|
StringName stringName
|
2020-04-28 14:44:38 -07:00
|
|
|
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
|
|
|
|
IsWeak bool // promoted from google.protobuf.FieldOptions
|
2024-07-05 12:26:57 +02:00
|
|
|
IsLazy bool // promoted from google.protobuf.FieldOptions
|
2020-04-28 14:44:38 -07:00
|
|
|
Default defaultValue
|
2022-05-24 05:12:23 +09:00
|
|
|
ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
|
|
|
|
Enum protoreflect.EnumDescriptor
|
|
|
|
Message protoreflect.MessageDescriptor
|
2023-12-04 15:57:11 +01:00
|
|
|
|
2024-01-16 10:33:13 +01:00
|
|
|
EditionFeatures EditionFeatures
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Oneof struct {
|
|
|
|
Base
|
|
|
|
L1 OneofL1
|
|
|
|
}
|
|
|
|
OneofL1 struct {
|
2022-05-24 05:12:23 +09:00
|
|
|
Options func() protoreflect.ProtoMessage
|
2019-06-06 13:01:53 -07:00
|
|
|
Fields OneofFields // must be consistent with Message.Fields.ContainingOneof
|
2024-01-16 10:33:13 +01:00
|
|
|
|
|
|
|
EditionFeatures EditionFeatures
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func (md *Message) Options() protoreflect.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := md.lazyInit().Options; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.Message
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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 {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := md.lazyInit().ExtensionRangeOptions[i]; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.ExtensionRange
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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) }
|
2019-06-06 13:01:53 -07:00
|
|
|
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 {
|
2019-11-07 15:30:44 -08:00
|
|
|
return md.L1.IsMessageSet
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func (fd *Field) Options() protoreflect.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := fd.L1.Options; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.Field
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
func (fd *Field) Number() protoreflect.FieldNumber { return fd.L1.Number }
|
|
|
|
func (fd *Field) Cardinality() protoreflect.Cardinality { return fd.L1.Cardinality }
|
2024-01-16 10:33:13 +01:00
|
|
|
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) }
|
2020-04-28 14:44:38 -07:00
|
|
|
func (fd *Field) HasPresence() bool {
|
2024-02-27 11:00:04 +01:00
|
|
|
if fd.L1.Cardinality == protoreflect.Repeated {
|
|
|
|
return false
|
2023-12-04 15:57:11 +01:00
|
|
|
}
|
2024-03-26 09:19:07 +01:00
|
|
|
return fd.IsExtension() || fd.L1.EditionFeatures.IsFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil
|
2020-04-28 14:44:38 -07:00
|
|
|
}
|
|
|
|
func (fd *Field) HasOptionalKeyword() bool {
|
2022-05-24 05:12:23 +09:00
|
|
|
return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional
|
2020-04-28 14:44:38 -07:00
|
|
|
}
|
2019-06-06 13:01:53 -07:00
|
|
|
func (fd *Field) IsPacked() bool {
|
2024-02-23 16:19:47 +01:00
|
|
|
if fd.L1.Cardinality != protoreflect.Repeated {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
switch fd.L1.Kind {
|
|
|
|
case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
|
|
|
|
return false
|
|
|
|
}
|
2024-03-18 15:58:47 +01:00
|
|
|
return fd.L1.EditionFeatures.IsPacked
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
func (fd *Field) IsExtension() bool { return false }
|
|
|
|
func (fd *Field) IsWeak() bool { return fd.L1.IsWeak }
|
2024-07-05 12:26:57 +02:00
|
|
|
func (fd *Field) IsLazy() bool { return fd.L1.IsLazy }
|
2022-05-24 05:12:23 +09:00
|
|
|
func (fd *Field) IsList() bool { return fd.Cardinality() == protoreflect.Repeated && !fd.IsMap() }
|
2019-06-06 13:01:53 -07:00
|
|
|
func (fd *Field) IsMap() bool { return fd.Message() != nil && fd.Message().IsMapEntry() }
|
2022-05-24 05:12:23 +09:00
|
|
|
func (fd *Field) MapKey() protoreflect.FieldDescriptor {
|
2019-06-06 13:01:53 -07:00
|
|
|
if !fd.IsMap() {
|
|
|
|
return nil
|
|
|
|
}
|
2020-06-19 13:17:06 -07:00
|
|
|
return fd.Message().Fields().ByNumber(genid.MapEntry_Key_field_number)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
func (fd *Field) MapValue() protoreflect.FieldDescriptor {
|
2019-06-06 13:01:53 -07:00
|
|
|
if !fd.IsMap() {
|
|
|
|
return nil
|
|
|
|
}
|
2020-06-19 13:17:06 -07:00
|
|
|
return fd.Message().Fields().ByNumber(genid.MapEntry_Value_field_number)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
func (fd *Field) Enum() protoreflect.EnumDescriptor {
|
2019-08-05 13:41:37 -07:00
|
|
|
return fd.L1.Enum
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
func (fd *Field) Message() protoreflect.MessageDescriptor {
|
2019-08-05 13:41:37 -07:00
|
|
|
if fd.L1.IsWeak {
|
|
|
|
if d, _ := protoregistry.GlobalFiles.FindDescriptorByName(fd.L1.Message.FullName()); d != nil {
|
2022-05-24 05:12:23 +09:00
|
|
|
return d.(protoreflect.MessageDescriptor)
|
2019-08-05 13:41:37 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return fd.L1.Message
|
|
|
|
}
|
2024-05-29 09:43:14 -04:00
|
|
|
func (fd *Field) IsMapEntry() bool {
|
|
|
|
parent, ok := fd.L0.Parent.(protoreflect.MessageDescriptor)
|
|
|
|
return ok && parent.IsMapEntry()
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
func (fd *Field) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) }
|
|
|
|
func (fd *Field) ProtoType(protoreflect.FieldDescriptor) {}
|
2019-06-06 13:01:53 -07:00
|
|
|
|
2019-07-13 00:44:41 -07:00
|
|
|
// 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 {
|
2024-03-18 15:58:47 +01:00
|
|
|
return fd.L1.EditionFeatures.IsUTF8Validated
|
2019-07-13 00:44:41 -07:00
|
|
|
}
|
|
|
|
|
2020-04-28 14:44:38 -07:00
|
|
|
func (od *Oneof) IsSynthetic() bool {
|
2022-05-24 05:12:23 +09:00
|
|
|
return od.L0.ParentFile.L1.Syntax == protoreflect.Proto3 && len(od.L1.Fields.List) == 1 && od.L1.Fields.List[0].HasOptionalKeyword()
|
2020-04-28 14:44:38 -07:00
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
func (od *Oneof) Options() protoreflect.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := od.L1.Options; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.Oneof
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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) {}
|
2019-06-06 13:01:53 -07:00
|
|
|
|
|
|
|
type (
|
|
|
|
Extension struct {
|
|
|
|
Base
|
|
|
|
L1 ExtensionL1
|
|
|
|
L2 *ExtensionL2 // protected by fileDesc.once
|
|
|
|
}
|
|
|
|
ExtensionL1 struct {
|
2024-02-21 16:09:10 +01:00
|
|
|
Number protoreflect.FieldNumber
|
|
|
|
Extendee protoreflect.MessageDescriptor
|
|
|
|
Cardinality protoreflect.Cardinality
|
|
|
|
Kind protoreflect.Kind
|
2024-07-05 12:26:57 +02:00
|
|
|
IsLazy bool
|
2024-02-21 16:09:10 +01:00
|
|
|
EditionFeatures EditionFeatures
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
ExtensionL2 struct {
|
2022-05-24 05:12:23 +09:00
|
|
|
Options func() protoreflect.ProtoMessage
|
2020-06-24 16:47:32 -07:00
|
|
|
StringName stringName
|
2020-04-28 14:44:38 -07:00
|
|
|
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
|
|
|
|
Default defaultValue
|
2022-05-24 05:12:23 +09:00
|
|
|
Enum protoreflect.EnumDescriptor
|
|
|
|
Message protoreflect.MessageDescriptor
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func (xd *Extension) Options() protoreflect.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := xd.lazyInit().Options; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.Field
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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 }
|
2020-04-28 14:44:38 -07:00
|
|
|
func (xd *Extension) HasOptionalKeyword() bool {
|
2022-05-24 05:12:23 +09:00
|
|
|
return (xd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && xd.L1.Cardinality == protoreflect.Optional) || xd.lazyInit().IsProto3Optional
|
|
|
|
}
|
2024-04-16 15:09:33 +02:00
|
|
|
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
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
func (xd *Extension) IsExtension() bool { return true }
|
|
|
|
func (xd *Extension) IsWeak() bool { return false }
|
2024-07-05 12:26:57 +02:00
|
|
|
func (xd *Extension) IsLazy() bool { return xd.L1.IsLazy }
|
2022-05-24 05:12:23 +09:00
|
|
|
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) {}
|
2019-06-06 13:01:53 -07:00
|
|
|
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 {
|
2022-05-24 05:12:23 +09:00
|
|
|
Options func() protoreflect.ProtoMessage
|
2019-06-06 13:01:53 -07:00
|
|
|
Methods Methods
|
|
|
|
}
|
|
|
|
|
|
|
|
Method struct {
|
|
|
|
Base
|
|
|
|
L1 MethodL1
|
|
|
|
}
|
|
|
|
MethodL1 struct {
|
2022-05-24 05:12:23 +09:00
|
|
|
Options func() protoreflect.ProtoMessage
|
|
|
|
Input protoreflect.MessageDescriptor
|
|
|
|
Output protoreflect.MessageDescriptor
|
2019-06-06 13:01:53 -07:00
|
|
|
IsStreamingClient bool
|
|
|
|
IsStreamingServer bool
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func (sd *Service) Options() protoreflect.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := sd.lazyInit().Options; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.Service
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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) {}
|
2019-06-06 13:01:53 -07:00
|
|
|
func (sd *Service) lazyInit() *ServiceL2 {
|
|
|
|
sd.L0.ParentFile.lazyInit() // implicitly initializes L2
|
|
|
|
return sd.L2
|
|
|
|
}
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func (md *Method) Options() protoreflect.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if f := md.L1.Options; f != nil {
|
|
|
|
return f()
|
|
|
|
}
|
|
|
|
return descopts.Method
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
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) {}
|
2019-06-06 13:01:53 -07:00
|
|
|
|
|
|
|
// Surrogate files are can be used to create standalone descriptors
|
|
|
|
// where the syntax is only information derived from the parent file.
|
|
|
|
var (
|
2024-04-02 14:02:41 -07:00
|
|
|
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{}}
|
2019-06-06 13:01:53 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
Base struct {
|
|
|
|
L0 BaseL0
|
|
|
|
}
|
|
|
|
BaseL0 struct {
|
2022-05-24 05:12:23 +09:00
|
|
|
FullName protoreflect.FullName // must be populated
|
|
|
|
ParentFile *File // must be populated
|
|
|
|
Parent protoreflect.Descriptor
|
2019-06-06 13:01:53 -07:00
|
|
|
Index int
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
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 {
|
2019-06-06 13:01:53 -07:00
|
|
|
if d.L0.ParentFile == SurrogateProto2 || d.L0.ParentFile == SurrogateProto3 {
|
|
|
|
return nil // surrogate files are not real parents
|
|
|
|
}
|
|
|
|
return d.L0.ParentFile
|
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
func (d *Base) Parent() protoreflect.Descriptor { return d.L0.Parent }
|
2019-06-06 13:01:53 -07:00
|
|
|
func (d *Base) Index() int { return d.L0.Index }
|
2022-05-24 05:12:23 +09:00
|
|
|
func (d *Base) Syntax() protoreflect.Syntax { return d.L0.ParentFile.Syntax() }
|
2019-06-06 13:01:53 -07:00
|
|
|
func (d *Base) IsPlaceholder() bool { return false }
|
|
|
|
func (d *Base) ProtoInternal(pragma.DoNotImplement) {}
|
|
|
|
|
2020-06-24 16:47:32 -07:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-04-02 12:59:48 -07:00
|
|
|
// 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()
|
|
|
|
}
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func (s *stringName) lazyInit(fd protoreflect.FieldDescriptor) *stringName {
|
2020-06-24 16:47:32 -07:00
|
|
|
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())
|
2024-04-02 12:59:48 -07:00
|
|
|
if isGroupLike(fd) {
|
2020-06-24 16:47:32 -07:00
|
|
|
s.nameText = string(fd.Message().Name())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return s
|
2020-01-03 15:53:47 -08:00
|
|
|
}
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
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 }
|
2019-06-06 13:01:53 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func DefaultValue(v protoreflect.Value, ev protoreflect.EnumValueDescriptor) defaultValue {
|
2019-06-06 13:01:53 -07:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func unmarshalDefault(b []byte, k protoreflect.Kind, pf *File, ed protoreflect.EnumDescriptor) defaultValue {
|
|
|
|
var evs protoreflect.EnumValueDescriptors
|
|
|
|
if k == protoreflect.EnumKind {
|
2019-06-06 13:01:53 -07:00
|
|
|
// 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.
|
2019-08-30 01:00:42 -07:00
|
|
|
if e, ok := ed.(*Enum); ok && e.L0.ParentFile == pf {
|
|
|
|
evs = &e.L2.Values
|
2019-06-06 13:01:53 -07:00
|
|
|
} else {
|
|
|
|
evs = ed.Values()
|
|
|
|
}
|
2019-08-30 01:00:42 -07:00
|
|
|
|
|
|
|
// 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.
|
2022-05-24 05:12:23 +09:00
|
|
|
if ed.IsPlaceholder() && protoreflect.Name(b).IsValid() {
|
|
|
|
v := protoreflect.ValueOfEnum(0)
|
|
|
|
ev := PlaceholderEnumValue(ed.FullName().Parent().Append(protoreflect.Name(b)))
|
2019-08-30 01:00:42 -07:00
|
|
|
return DefaultValue(v, ev)
|
|
|
|
}
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2022-05-24 05:12:23 +09:00
|
|
|
val protoreflect.Value
|
|
|
|
enum protoreflect.EnumValueDescriptor
|
2019-06-06 13:01:53 -07:00
|
|
|
bytes []byte
|
|
|
|
}
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
func (dv *defaultValue) get(fd protoreflect.FieldDescriptor) protoreflect.Value {
|
2019-06-06 13:01:53 -07:00
|
|
|
// Return the zero value as the default if unpopulated.
|
|
|
|
if !dv.has {
|
2022-05-24 05:12:23 +09:00
|
|
|
if fd.Cardinality() == protoreflect.Repeated {
|
|
|
|
return protoreflect.Value{}
|
2019-07-01 13:45:52 -07:00
|
|
|
}
|
2019-06-06 13:01:53 -07:00
|
|
|
switch fd.Kind() {
|
2022-05-24 05:12:23 +09:00
|
|
|
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:
|
2019-09-17 13:05:45 -07:00
|
|
|
if evs := fd.Enum().Values(); evs.Len() > 0 {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfEnum(evs.Get(0).Number())
|
2019-09-17 13:05:45 -07:00
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfEnum(0)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
2020-04-22 21:58:56 -07:00
|
|
|
panic(fmt.Sprintf("detected mutation on the default bytes for %v", fd.FullName()))
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
return dv.val
|
|
|
|
}
|