Merge pull request #5434 from TomSweeneyRedHat/dev/tsweeney/cve-1.29-2

[release-1.29] bump to v1.29.3, fix conformance, CVE-2024-1753, CVE-2024-24786
This commit is contained in:
openshift-merge-bot[bot] 2024-03-27 17:34:31 +00:00 committed by GitHub
commit 28a3bb1e57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
76 changed files with 4985 additions and 1396 deletions

View File

@ -2,6 +2,14 @@
# Changelog # Changelog
## v1.29.3 (2024-03-26)
[release-1.29] Bump google.golang.org/protobuf to v1.33.0
[release-1.29] conformance tests: don't break on trailing zeroes
[release-1.29] CVE-2024-1753 container escape fix
bump golang.org/x/crypto to v0.17.0
conformance test: ignore file type bits when comparing layers
## v1.29.2 (2023-10-31) ## v1.29.2 (2023-10-31)
Mask /sys/devices/virtual/powercap by default Mask /sys/devices/virtual/powercap by default

View File

@ -1,3 +1,10 @@
- Changelog for v1.29.3 (2024-03-26)
* [release-1.29] Bump google.golang.org/protobuf to v1.33.0
* [release-1.29] conformance tests: don't break on trailing zeroes
* [release-1.29] CVE-2024-1753 container escape fix
* bump golang.org/x/crypto to v0.17.0
* conformance test: ignore file type bits when comparing layers
- Changelog for v1.29.2 (2023-10-31) - Changelog for v1.29.2 (2023-10-31)
* Mask /sys/devices/virtual/powercap by default * Mask /sys/devices/virtual/powercap by default
* remove registry.centos.org * remove registry.centos.org

View File

@ -30,7 +30,7 @@ const (
Package = "buildah" Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec // Version for the Package. Bump version in contrib/rpm/buildah.spec
// too. // too.
Version = "1.29.2" Version = "1.29.3"
// DefaultRuntime if containers.conf fails. // DefaultRuntime if containers.conf fails.
DefaultRuntime = "runc" DefaultRuntime = "runc"

2
go.mod
View File

@ -131,7 +131,7 @@ require (
golang.org/x/tools v0.6.0 // indirect golang.org/x/tools v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect
google.golang.org/grpc v1.51.0 // indirect google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect

4
go.sum
View File

@ -1336,8 +1336,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVCwMc= gopkg.in/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVCwMc=

View File

@ -11,6 +11,7 @@ import (
"errors" "errors"
"github.com/containers/buildah/copier"
"github.com/containers/buildah/define" "github.com/containers/buildah/define"
"github.com/containers/buildah/internal" "github.com/containers/buildah/internal"
internalUtil "github.com/containers/buildah/internal/util" internalUtil "github.com/containers/buildah/internal/util"
@ -164,7 +165,11 @@ func GetBindMount(ctx *types.SystemContext, args []string, contextDir string, st
// buildkit parity: support absolute path for sources from current build context // buildkit parity: support absolute path for sources from current build context
if contextDir != "" { if contextDir != "" {
// path should be /contextDir/specified path // path should be /contextDir/specified path
newMount.Source = filepath.Join(contextDir, filepath.Clean(string(filepath.Separator)+newMount.Source)) evaluated, err := copier.Eval(contextDir, newMount.Source, copier.EvalOptions{})
if err != nil {
return newMount, "", err
}
newMount.Source = evaluated
} else { } else {
// looks like its coming from `build run --mount=type=bind` allow using absolute path // looks like its coming from `build run --mount=type=bind` allow using absolute path
// error out if no source is set // error out if no source is set

View File

@ -5925,3 +5925,26 @@ _EOF
expect_output --substring "w=x y=z I=J K=L" expect_output --substring "w=x y=z I=J K=L"
expect_output --substring "w=x y=z I=I K=K" expect_output --substring "w=x y=z I=I K=K"
} }
@test "build no write file on host - CVE-2024-1753" {
_prefetch alpine
cat > ${TEST_SCRATCH_DIR}/Containerfile << _EOF
FROM alpine as base
RUN ln -s / /rootdir
FROM alpine
RUN echo "With exploit show host root, not the container's root, and create /BIND_BREAKOUT in / on the host"
RUN --mount=type=bind,from=base,source=/rootdir,destination=/exploit,rw ls -l /exploit; touch /exploit/BIND_BREAKOUT; ls -l /exploit
_EOF
run_buildah build $WITH_POLICY_JSON ${TEST_SCRATCH_DIR}
expect_output --substring "/BIND_BREAKOUT"
run ls /BIND_BREAKOUT
rm -f /BIND_BREAKOUT
assert "$status" -eq 2 "exit code from ls"
expect_output --substring "No such file or directory"
}

View File

@ -32,6 +32,8 @@ import (
"github.com/containers/image/v5/transports" "github.com/containers/image/v5/transports"
"github.com/containers/image/v5/types" "github.com/containers/image/v5/types"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/containers/storage/pkg/ioutils"
"github.com/containers/storage/pkg/reexec" "github.com/containers/storage/pkg/reexec"
dockertypes "github.com/docker/docker/api/types" dockertypes "github.com/docker/docker/api/types"
dockerdockerclient "github.com/docker/docker/client" dockerdockerclient "github.com/docker/docker/client"
@ -883,11 +885,15 @@ func saveReport(ctx context.Context, t *testing.T, ref types.ImageReference, dir
// summarizeLayer reads a blob and returns a summary of the parts of its contents that we care about // summarizeLayer reads a blob and returns a summary of the parts of its contents that we care about
func summarizeLayer(t *testing.T, imageName string, blobInfo types.BlobInfo, reader io.Reader) (layer Layer) { func summarizeLayer(t *testing.T, imageName string, blobInfo types.BlobInfo, reader io.Reader) (layer Layer) {
compressedDigest := digest.Canonical.Digester() compressedDigest := digest.Canonical.Digester()
uncompressedBlob, _, err := compression.AutoDecompress(io.TeeReader(reader, compressedDigest.Hash())) counter := ioutils.NewWriteCounter(compressedDigest.Hash())
require.Nil(t, err, "error decompressing blob %+v for image %q", blobInfo, imageName) compressionAlgorithm, _, reader, err := compression.DetectCompressionFormat(reader)
require.NoErrorf(t, err, "error checking if blob %+v for image %q is compressed", blobInfo, imageName)
uncompressedBlob, wasCompressed, err := compression.AutoDecompress(io.TeeReader(reader, counter))
require.NoErrorf(t, err, "error decompressing blob %+v for image %q", blobInfo, imageName)
defer uncompressedBlob.Close() defer uncompressedBlob.Close()
uncompressedDigest := digest.Canonical.Digester() uncompressedDigest := digest.Canonical.Digester()
tr := tar.NewReader(io.TeeReader(uncompressedBlob, uncompressedDigest.Hash())) tarToRead := io.TeeReader(uncompressedBlob, uncompressedDigest.Hash())
tr := tar.NewReader(tarToRead)
hdr, err := tr.Next() hdr, err := tr.Next()
for err == nil { for err == nil {
header := fsHeaderForEntry(hdr) header := fsHeaderForEntry(hdr)
@ -902,8 +908,18 @@ func summarizeLayer(t *testing.T, imageName string, blobInfo types.BlobInfo, rea
hdr, err = tr.Next() hdr, err = tr.Next()
} }
require.Equal(t, io.EOF, err, "unexpected error reading layer contents %+v for image %q", blobInfo, imageName) require.Equal(t, io.EOF, err, "unexpected error reading layer contents %+v for image %q", blobInfo, imageName)
_, err = io.Copy(io.Discard, tarToRead)
require.NoError(t, err, "reading out any not-usually-present zero padding at the end")
layer.CompressedDigest = compressedDigest.Digest() layer.CompressedDigest = compressedDigest.Digest()
require.Equal(t, blobInfo.Digest, layer.CompressedDigest, "calculated digest of compressed blob didn't match expected digest") blobFormatDescription := "uncompressed"
if wasCompressed {
if compressionAlgorithm.Name() != "" {
blobFormatDescription = "compressed with " + compressionAlgorithm.Name()
} else {
blobFormatDescription = "compressed (?)"
}
}
require.Equalf(t, blobInfo.Digest, layer.CompressedDigest, "calculated digest of %s blob didn't match expected digest (expected length %d, actual length %d)", blobFormatDescription, blobInfo.Size, counter.Count)
layer.UncompressedDigest = uncompressedDigest.Digest() layer.UncompressedDigest = uncompressedDigest.Digest()
return layer return layer
} }

View File

@ -11,6 +11,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/encoding/json" "google.golang.org/protobuf/internal/encoding/json"
"google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/errors"
@ -23,7 +24,7 @@ import (
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
) )
// Unmarshal reads the given []byte into the given proto.Message. // Unmarshal reads the given []byte into the given [proto.Message].
// The provided message must be mutable (e.g., a non-nil pointer to a message). // The provided message must be mutable (e.g., a non-nil pointer to a message).
func Unmarshal(b []byte, m proto.Message) error { func Unmarshal(b []byte, m proto.Message) error {
return UnmarshalOptions{}.Unmarshal(b, m) return UnmarshalOptions{}.Unmarshal(b, m)
@ -37,7 +38,7 @@ type UnmarshalOptions struct {
// required fields will not return an error. // required fields will not return an error.
AllowPartial bool AllowPartial bool
// If DiscardUnknown is set, unknown fields are ignored. // If DiscardUnknown is set, unknown fields and enum name values are ignored.
DiscardUnknown bool DiscardUnknown bool
// Resolver is used for looking up types when unmarshaling // Resolver is used for looking up types when unmarshaling
@ -47,9 +48,13 @@ type UnmarshalOptions struct {
protoregistry.MessageTypeResolver protoregistry.MessageTypeResolver
protoregistry.ExtensionTypeResolver protoregistry.ExtensionTypeResolver
} }
// RecursionLimit limits how deeply messages may be nested.
// If zero, a default limit is applied.
RecursionLimit int
} }
// Unmarshal reads the given []byte and populates the given proto.Message // Unmarshal reads the given []byte and populates the given [proto.Message]
// using options in the UnmarshalOptions object. // using options in the UnmarshalOptions object.
// It will clear the message first before setting the fields. // It will clear the message first before setting the fields.
// If it returns an error, the given message may be partially set. // If it returns an error, the given message may be partially set.
@ -67,6 +72,9 @@ func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error {
if o.Resolver == nil { if o.Resolver == nil {
o.Resolver = protoregistry.GlobalTypes o.Resolver = protoregistry.GlobalTypes
} }
if o.RecursionLimit == 0 {
o.RecursionLimit = protowire.DefaultRecursionLimit
}
dec := decoder{json.NewDecoder(b), o} dec := decoder{json.NewDecoder(b), o}
if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil { if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil {
@ -114,6 +122,10 @@ func (d decoder) syntaxError(pos int, f string, x ...interface{}) error {
// unmarshalMessage unmarshals a message into the given protoreflect.Message. // unmarshalMessage unmarshals a message into the given protoreflect.Message.
func (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) error { func (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) error {
d.opts.RecursionLimit--
if d.opts.RecursionLimit < 0 {
return errors.New("exceeded max recursion depth")
}
if unmarshal := wellKnownTypeUnmarshaler(m.Descriptor().FullName()); unmarshal != nil { if unmarshal := wellKnownTypeUnmarshaler(m.Descriptor().FullName()); unmarshal != nil {
return unmarshal(d, m) return unmarshal(d, m)
} }
@ -266,7 +278,9 @@ func (d decoder) unmarshalSingular(m protoreflect.Message, fd protoreflect.Field
if err != nil { if err != nil {
return err return err
} }
m.Set(fd, val) if val.IsValid() {
m.Set(fd, val)
}
return nil return nil
} }
@ -329,7 +343,7 @@ func (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.
} }
case protoreflect.EnumKind: case protoreflect.EnumKind:
if v, ok := unmarshalEnum(tok, fd); ok { if v, ok := unmarshalEnum(tok, fd, d.opts.DiscardUnknown); ok {
return v, nil return v, nil
} }
@ -474,7 +488,7 @@ func unmarshalBytes(tok json.Token) (protoreflect.Value, bool) {
return protoreflect.ValueOfBytes(b), true return protoreflect.ValueOfBytes(b), true
} }
func unmarshalEnum(tok json.Token, fd protoreflect.FieldDescriptor) (protoreflect.Value, bool) { func unmarshalEnum(tok json.Token, fd protoreflect.FieldDescriptor, discardUnknown bool) (protoreflect.Value, bool) {
switch tok.Kind() { switch tok.Kind() {
case json.String: case json.String:
// Lookup EnumNumber based on name. // Lookup EnumNumber based on name.
@ -482,6 +496,9 @@ func unmarshalEnum(tok json.Token, fd protoreflect.FieldDescriptor) (protoreflec
if enumVal := fd.Enum().Values().ByName(protoreflect.Name(s)); enumVal != nil { if enumVal := fd.Enum().Values().ByName(protoreflect.Name(s)); enumVal != nil {
return protoreflect.ValueOfEnum(enumVal.Number()), true return protoreflect.ValueOfEnum(enumVal.Number()), true
} }
if discardUnknown {
return protoreflect.Value{}, true
}
case json.Number: case json.Number:
if n, ok := tok.Int(32); ok { if n, ok := tok.Int(32); ok {
@ -542,7 +559,9 @@ func (d decoder) unmarshalList(list protoreflect.List, fd protoreflect.FieldDesc
if err != nil { if err != nil {
return err return err
} }
list.Append(val) if val.IsValid() {
list.Append(val)
}
} }
} }
@ -609,8 +628,9 @@ Loop:
if err != nil { if err != nil {
return err return err
} }
if pval.IsValid() {
mmap.Set(pkey, pval) mmap.Set(pkey, pval)
}
} }
return nil return nil

View File

@ -4,8 +4,8 @@
// Package protojson marshals and unmarshals protocol buffer messages as JSON // Package protojson marshals and unmarshals protocol buffer messages as JSON
// format. It follows the guide at // format. It follows the guide at
// https://developers.google.com/protocol-buffers/docs/proto3#json. // https://protobuf.dev/programming-guides/proto3#json.
// //
// This package produces a different output than the standard "encoding/json" // This package produces a different output than the standard [encoding/json]
// package, which does not operate correctly on protocol buffer messages. // package, which does not operate correctly on protocol buffer messages.
package protojson package protojson

View File

@ -31,7 +31,7 @@ func Format(m proto.Message) string {
return MarshalOptions{Multiline: true}.Format(m) return MarshalOptions{Multiline: true}.Format(m)
} }
// Marshal writes the given proto.Message in JSON format using default options. // Marshal writes the given [proto.Message] in JSON format using default options.
// Do not depend on the output being stable. It may change over time across // Do not depend on the output being stable. It may change over time across
// different versions of the program. // different versions of the program.
func Marshal(m proto.Message) ([]byte, error) { func Marshal(m proto.Message) ([]byte, error) {
@ -81,6 +81,25 @@ type MarshalOptions struct {
// ╚═══════╧════════════════════════════╝ // ╚═══════╧════════════════════════════╝
EmitUnpopulated bool EmitUnpopulated bool
// EmitDefaultValues specifies whether to emit default-valued primitive fields,
// empty lists, and empty maps. The fields affected are as follows:
// ╔═══════╤════════════════════════════════════════╗
// ║ JSON │ Protobuf field ║
// ╠═══════╪════════════════════════════════════════╣
// ║ false │ non-optional scalar boolean fields ║
// ║ 0 │ non-optional scalar numeric fields ║
// ║ "" │ non-optional scalar string/byte fields ║
// ║ [] │ empty repeated fields ║
// ║ {} │ empty map fields ║
// ╚═══════╧════════════════════════════════════════╝
//
// Behaves similarly to EmitUnpopulated, but does not emit "null"-value fields,
// i.e. presence-sensing fields that are omitted will remain omitted to preserve
// presence-sensing.
// EmitUnpopulated takes precedence over EmitDefaultValues since the former generates
// a strict superset of the latter.
EmitDefaultValues bool
// Resolver is used for looking up types when expanding google.protobuf.Any // Resolver is used for looking up types when expanding google.protobuf.Any
// messages. If nil, this defaults to using protoregistry.GlobalTypes. // messages. If nil, this defaults to using protoregistry.GlobalTypes.
Resolver interface { Resolver interface {
@ -102,17 +121,23 @@ func (o MarshalOptions) Format(m proto.Message) string {
return string(b) return string(b)
} }
// Marshal marshals the given proto.Message in the JSON format using options in // Marshal marshals the given [proto.Message] in the JSON format using options in
// MarshalOptions. Do not depend on the output being stable. It may change over // MarshalOptions. Do not depend on the output being stable. It may change over
// time across different versions of the program. // time across different versions of the program.
func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
return o.marshal(m) return o.marshal(nil, m)
}
// MarshalAppend appends the JSON format encoding of m to b,
// returning the result.
func (o MarshalOptions) MarshalAppend(b []byte, m proto.Message) ([]byte, error) {
return o.marshal(b, m)
} }
// marshal is a centralized function that all marshal operations go through. // marshal is a centralized function that all marshal operations go through.
// For profiling purposes, avoid changing the name of this function or // For profiling purposes, avoid changing the name of this function or
// introducing other code paths for marshal that do not go through this. // introducing other code paths for marshal that do not go through this.
func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) { func (o MarshalOptions) marshal(b []byte, m proto.Message) ([]byte, error) {
if o.Multiline && o.Indent == "" { if o.Multiline && o.Indent == "" {
o.Indent = defaultIndent o.Indent = defaultIndent
} }
@ -120,7 +145,7 @@ func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) {
o.Resolver = protoregistry.GlobalTypes o.Resolver = protoregistry.GlobalTypes
} }
internalEnc, err := json.NewEncoder(o.Indent) internalEnc, err := json.NewEncoder(b, o.Indent)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -128,7 +153,7 @@ func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) {
// Treat nil message interface as an empty message, // Treat nil message interface as an empty message,
// in which case the output in an empty JSON object. // in which case the output in an empty JSON object.
if m == nil { if m == nil {
return []byte("{}"), nil return append(b, '{', '}'), nil
} }
enc := encoder{internalEnc, o} enc := encoder{internalEnc, o}
@ -172,7 +197,11 @@ func (m typeURLFieldRanger) Range(f func(protoreflect.FieldDescriptor, protorefl
// unpopulatedFieldRanger wraps a protoreflect.Message and modifies its Range // unpopulatedFieldRanger wraps a protoreflect.Message and modifies its Range
// method to additionally iterate over unpopulated fields. // method to additionally iterate over unpopulated fields.
type unpopulatedFieldRanger struct{ protoreflect.Message } type unpopulatedFieldRanger struct {
protoreflect.Message
skipNull bool
}
func (m unpopulatedFieldRanger) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { func (m unpopulatedFieldRanger) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
fds := m.Descriptor().Fields() fds := m.Descriptor().Fields()
@ -186,6 +215,9 @@ func (m unpopulatedFieldRanger) Range(f func(protoreflect.FieldDescriptor, proto
isProto2Scalar := fd.Syntax() == protoreflect.Proto2 && fd.Default().IsValid() isProto2Scalar := fd.Syntax() == protoreflect.Proto2 && fd.Default().IsValid()
isSingularMessage := fd.Cardinality() != protoreflect.Repeated && fd.Message() != nil isSingularMessage := fd.Cardinality() != protoreflect.Repeated && fd.Message() != nil
if isProto2Scalar || isSingularMessage { if isProto2Scalar || isSingularMessage {
if m.skipNull {
continue
}
v = protoreflect.Value{} // use invalid value to emit null v = protoreflect.Value{} // use invalid value to emit null
} }
if !f(fd, v) { if !f(fd, v) {
@ -211,8 +243,11 @@ func (e encoder) marshalMessage(m protoreflect.Message, typeURL string) error {
defer e.EndObject() defer e.EndObject()
var fields order.FieldRanger = m var fields order.FieldRanger = m
if e.opts.EmitUnpopulated { switch {
fields = unpopulatedFieldRanger{m} case e.opts.EmitUnpopulated:
fields = unpopulatedFieldRanger{Message: m, skipNull: false}
case e.opts.EmitDefaultValues:
fields = unpopulatedFieldRanger{Message: m, skipNull: true}
} }
if typeURL != "" { if typeURL != "" {
fields = typeURLFieldRanger{fields, typeURL} fields = typeURLFieldRanger{fields, typeURL}

View File

@ -176,7 +176,7 @@ func (d decoder) unmarshalAny(m protoreflect.Message) error {
// Use another decoder to parse the unread bytes for @type field. This // Use another decoder to parse the unread bytes for @type field. This
// avoids advancing a read from current decoder because the current JSON // avoids advancing a read from current decoder because the current JSON
// object may contain the fields of the embedded type. // object may contain the fields of the embedded type.
dec := decoder{d.Clone(), UnmarshalOptions{}} dec := decoder{d.Clone(), UnmarshalOptions{RecursionLimit: d.opts.RecursionLimit}}
tok, err := findTypeURL(dec) tok, err := findTypeURL(dec)
switch err { switch err {
case errEmptyObject: case errEmptyObject:
@ -308,48 +308,29 @@ Loop:
// array) in order to advance the read to the next JSON value. It relies on // array) in order to advance the read to the next JSON value. It relies on
// the decoder returning an error if the types are not in valid sequence. // the decoder returning an error if the types are not in valid sequence.
func (d decoder) skipJSONValue() error { func (d decoder) skipJSONValue() error {
tok, err := d.Read() var open int
if err != nil { for {
return err tok, err := d.Read()
} if err != nil {
// Only need to continue reading for objects and arrays. return err
switch tok.Kind() {
case json.ObjectOpen:
for {
tok, err := d.Read()
if err != nil {
return err
}
switch tok.Kind() {
case json.ObjectClose:
return nil
case json.Name:
// Skip object field value.
if err := d.skipJSONValue(); err != nil {
return err
}
}
} }
switch tok.Kind() {
case json.ArrayOpen: case json.ObjectClose, json.ArrayClose:
for { open--
tok, err := d.Peek() case json.ObjectOpen, json.ArrayOpen:
if err != nil { open++
return err if open > d.opts.RecursionLimit {
} return errors.New("exceeded max recursion depth")
switch tok.Kind() {
case json.ArrayClose:
d.Read()
return nil
default:
// Skip array item.
if err := d.skipJSONValue(); err != nil {
return err
}
} }
case json.EOF:
// This can only happen if there's a bug in Decoder.Read.
// Avoid an infinite loop if this does happen.
return errors.New("unexpected EOF")
}
if open == 0 {
return nil
} }
} }
return nil
} }
// unmarshalAnyValue unmarshals the given custom-type message from the JSON // unmarshalAnyValue unmarshals the given custom-type message from the JSON
@ -814,16 +795,22 @@ func (d decoder) unmarshalTimestamp(m protoreflect.Message) error {
return d.unexpectedTokenError(tok) return d.unexpectedTokenError(tok)
} }
t, err := time.Parse(time.RFC3339Nano, tok.ParsedString()) s := tok.ParsedString()
t, err := time.Parse(time.RFC3339Nano, s)
if err != nil { if err != nil {
return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString()) return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString())
} }
// Validate seconds. No need to validate nanos because time.Parse would have // Validate seconds.
// covered that already.
secs := t.Unix() secs := t.Unix()
if secs < minTimestampSeconds || secs > maxTimestampSeconds { if secs < minTimestampSeconds || secs > maxTimestampSeconds {
return d.newError(tok.Pos(), "%v value out of range: %v", genid.Timestamp_message_fullname, tok.RawString()) return d.newError(tok.Pos(), "%v value out of range: %v", genid.Timestamp_message_fullname, tok.RawString())
} }
// Validate subseconds.
i := strings.LastIndexByte(s, '.') // start of subsecond field
j := strings.LastIndexAny(s, "Z-+") // start of timezone field
if i >= 0 && j >= i && j-i > len(".999999999") {
return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString())
}
fds := m.Descriptor().Fields() fds := m.Descriptor().Fields()
fdSeconds := fds.ByNumber(genid.Timestamp_Seconds_field_number) fdSeconds := fds.ByNumber(genid.Timestamp_Seconds_field_number)

View File

@ -21,7 +21,7 @@ import (
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
) )
// Unmarshal reads the given []byte into the given proto.Message. // Unmarshal reads the given []byte into the given [proto.Message].
// The provided message must be mutable (e.g., a non-nil pointer to a message). // The provided message must be mutable (e.g., a non-nil pointer to a message).
func Unmarshal(b []byte, m proto.Message) error { func Unmarshal(b []byte, m proto.Message) error {
return UnmarshalOptions{}.Unmarshal(b, m) return UnmarshalOptions{}.Unmarshal(b, m)
@ -51,7 +51,7 @@ type UnmarshalOptions struct {
} }
} }
// Unmarshal reads the given []byte and populates the given proto.Message // Unmarshal reads the given []byte and populates the given [proto.Message]
// using options in the UnmarshalOptions object. // using options in the UnmarshalOptions object.
// The provided message must be mutable (e.g., a non-nil pointer to a message). // The provided message must be mutable (e.g., a non-nil pointer to a message).
func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error { func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
@ -739,7 +739,9 @@ func (d decoder) skipValue() error {
case text.ListClose: case text.ListClose:
return nil return nil
case text.MessageOpen: case text.MessageOpen:
return d.skipMessageValue() if err := d.skipMessageValue(); err != nil {
return err
}
default: default:
// Skip items. This will not validate whether skipped values are // Skip items. This will not validate whether skipped values are
// of the same type or not, same behavior as C++ // of the same type or not, same behavior as C++

View File

@ -33,7 +33,7 @@ func Format(m proto.Message) string {
return MarshalOptions{Multiline: true}.Format(m) return MarshalOptions{Multiline: true}.Format(m)
} }
// Marshal writes the given proto.Message in textproto format using default // Marshal writes the given [proto.Message] in textproto format using default
// options. Do not depend on the output being stable. It may change over time // options. Do not depend on the output being stable. It may change over time
// across different versions of the program. // across different versions of the program.
func Marshal(m proto.Message) ([]byte, error) { func Marshal(m proto.Message) ([]byte, error) {
@ -97,17 +97,23 @@ func (o MarshalOptions) Format(m proto.Message) string {
return string(b) return string(b)
} }
// Marshal writes the given proto.Message in textproto format using options in // Marshal writes the given [proto.Message] in textproto format using options in
// MarshalOptions object. Do not depend on the output being stable. It may // MarshalOptions object. Do not depend on the output being stable. It may
// change over time across different versions of the program. // change over time across different versions of the program.
func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
return o.marshal(m) return o.marshal(nil, m)
}
// MarshalAppend appends the textproto format encoding of m to b,
// returning the result.
func (o MarshalOptions) MarshalAppend(b []byte, m proto.Message) ([]byte, error) {
return o.marshal(b, m)
} }
// marshal is a centralized function that all marshal operations go through. // marshal is a centralized function that all marshal operations go through.
// For profiling purposes, avoid changing the name of this function or // For profiling purposes, avoid changing the name of this function or
// introducing other code paths for marshal that do not go through this. // introducing other code paths for marshal that do not go through this.
func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) { func (o MarshalOptions) marshal(b []byte, m proto.Message) ([]byte, error) {
var delims = [2]byte{'{', '}'} var delims = [2]byte{'{', '}'}
if o.Multiline && o.Indent == "" { if o.Multiline && o.Indent == "" {
@ -117,7 +123,7 @@ func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) {
o.Resolver = protoregistry.GlobalTypes o.Resolver = protoregistry.GlobalTypes
} }
internalEnc, err := text.NewEncoder(o.Indent, delims, o.EmitASCII) internalEnc, err := text.NewEncoder(b, o.Indent, delims, o.EmitASCII)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -125,7 +131,7 @@ func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) {
// Treat nil message interface as an empty message, // Treat nil message interface as an empty message,
// in which case there is nothing to output. // in which case there is nothing to output.
if m == nil { if m == nil {
return []byte{}, nil return b, nil
} }
enc := encoder{internalEnc, o} enc := encoder{internalEnc, o}

View File

@ -3,10 +3,10 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package protowire parses and formats the raw wire encoding. // Package protowire parses and formats the raw wire encoding.
// See https://developers.google.com/protocol-buffers/docs/encoding. // See https://protobuf.dev/programming-guides/encoding.
// //
// For marshaling and unmarshaling entire protobuf messages, // For marshaling and unmarshaling entire protobuf messages,
// use the "google.golang.org/protobuf/proto" package instead. // use the [google.golang.org/protobuf/proto] package instead.
package protowire package protowire
import ( import (
@ -29,12 +29,8 @@ const (
) )
// IsValid reports whether the field number is semantically valid. // IsValid reports whether the field number is semantically valid.
//
// Note that while numbers within the reserved range are semantically invalid,
// they are syntactically valid in the wire format.
// Implementations may treat records with reserved field numbers as unknown.
func (n Number) IsValid() bool { func (n Number) IsValid() bool {
return MinValidNumber <= n && n < FirstReservedNumber || LastReservedNumber < n && n <= MaxValidNumber return MinValidNumber <= n && n <= MaxValidNumber
} }
// Type represents the wire type. // Type represents the wire type.
@ -91,7 +87,7 @@ func ParseError(n int) error {
// ConsumeField parses an entire field record (both tag and value) and returns // ConsumeField parses an entire field record (both tag and value) and returns
// the field number, the wire type, and the total length. // the field number, the wire type, and the total length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
// //
// The total length includes the tag header and the end group marker (if the // The total length includes the tag header and the end group marker (if the
// field is a group). // field is a group).
@ -108,8 +104,8 @@ func ConsumeField(b []byte) (Number, Type, int) {
} }
// ConsumeFieldValue parses a field value and returns its length. // ConsumeFieldValue parses a field value and returns its length.
// This assumes that the field Number and wire Type have already been parsed. // This assumes that the field [Number] and wire [Type] have already been parsed.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
// //
// When parsing a group, the length includes the end group marker and // When parsing a group, the length includes the end group marker and
// the end group is verified to match the starting field number. // the end group is verified to match the starting field number.
@ -168,7 +164,7 @@ func AppendTag(b []byte, num Number, typ Type) []byte {
} }
// ConsumeTag parses b as a varint-encoded tag, reporting its length. // ConsumeTag parses b as a varint-encoded tag, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeTag(b []byte) (Number, Type, int) { func ConsumeTag(b []byte) (Number, Type, int) {
v, n := ConsumeVarint(b) v, n := ConsumeVarint(b)
if n < 0 { if n < 0 {
@ -267,7 +263,7 @@ func AppendVarint(b []byte, v uint64) []byte {
} }
// ConsumeVarint parses b as a varint-encoded uint64, reporting its length. // ConsumeVarint parses b as a varint-encoded uint64, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeVarint(b []byte) (v uint64, n int) { func ConsumeVarint(b []byte) (v uint64, n int) {
var y uint64 var y uint64
if len(b) <= 0 { if len(b) <= 0 {
@ -388,7 +384,7 @@ func AppendFixed32(b []byte, v uint32) []byte {
} }
// ConsumeFixed32 parses b as a little-endian uint32, reporting its length. // ConsumeFixed32 parses b as a little-endian uint32, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeFixed32(b []byte) (v uint32, n int) { func ConsumeFixed32(b []byte) (v uint32, n int) {
if len(b) < 4 { if len(b) < 4 {
return 0, errCodeTruncated return 0, errCodeTruncated
@ -416,7 +412,7 @@ func AppendFixed64(b []byte, v uint64) []byte {
} }
// ConsumeFixed64 parses b as a little-endian uint64, reporting its length. // ConsumeFixed64 parses b as a little-endian uint64, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeFixed64(b []byte) (v uint64, n int) { func ConsumeFixed64(b []byte) (v uint64, n int) {
if len(b) < 8 { if len(b) < 8 {
return 0, errCodeTruncated return 0, errCodeTruncated
@ -436,7 +432,7 @@ func AppendBytes(b []byte, v []byte) []byte {
} }
// ConsumeBytes parses b as a length-prefixed bytes value, reporting its length. // ConsumeBytes parses b as a length-prefixed bytes value, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeBytes(b []byte) (v []byte, n int) { func ConsumeBytes(b []byte) (v []byte, n int) {
m, n := ConsumeVarint(b) m, n := ConsumeVarint(b)
if n < 0 { if n < 0 {
@ -460,7 +456,7 @@ func AppendString(b []byte, v string) []byte {
} }
// ConsumeString parses b as a length-prefixed bytes value, reporting its length. // ConsumeString parses b as a length-prefixed bytes value, reporting its length.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeString(b []byte) (v string, n int) { func ConsumeString(b []byte) (v string, n int) {
bb, n := ConsumeBytes(b) bb, n := ConsumeBytes(b)
return string(bb), n return string(bb), n
@ -475,7 +471,7 @@ func AppendGroup(b []byte, num Number, v []byte) []byte {
// ConsumeGroup parses b as a group value until the trailing end group marker, // ConsumeGroup parses b as a group value until the trailing end group marker,
// and verifies that the end marker matches the provided num. The value v // and verifies that the end marker matches the provided num. The value v
// does not contain the end marker, while the length does contain the end marker. // does not contain the end marker, while the length does contain the end marker.
// This returns a negative length upon an error (see ParseError). // This returns a negative length upon an error (see [ParseError]).
func ConsumeGroup(num Number, b []byte) (v []byte, n int) { func ConsumeGroup(num Number, b []byte) (v []byte, n int) {
n = ConsumeFieldValue(num, StartGroupType, b) n = ConsumeFieldValue(num, StartGroupType, b)
if n < 0 { if n < 0 {
@ -499,8 +495,8 @@ func SizeGroup(num Number, n int) int {
return n + SizeTag(num) return n + SizeTag(num)
} }
// DecodeTag decodes the field Number and wire Type from its unified form. // DecodeTag decodes the field [Number] and wire [Type] from its unified form.
// The Number is -1 if the decoded field number overflows int32. // The [Number] is -1 if the decoded field number overflows int32.
// Other than overflow, this does not check for field number validity. // Other than overflow, this does not check for field number validity.
func DecodeTag(x uint64) (Number, Type) { func DecodeTag(x uint64) (Number, Type) {
// NOTE: MessageSet allows for larger field numbers than normal. // NOTE: MessageSet allows for larger field numbers than normal.
@ -510,7 +506,7 @@ func DecodeTag(x uint64) (Number, Type) {
return Number(x >> 3), Type(x & 7) return Number(x >> 3), Type(x & 7)
} }
// EncodeTag encodes the field Number and wire Type into its unified form. // EncodeTag encodes the field [Number] and wire [Type] into its unified form.
func EncodeTag(num Number, typ Type) uint64 { func EncodeTag(num Number, typ Type) uint64 {
return uint64(num)<<3 | uint64(typ&7) return uint64(num)<<3 | uint64(typ&7)
} }

View File

@ -83,7 +83,13 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
case protoreflect.FileImports: case protoreflect.FileImports:
for i := 0; i < vs.Len(); i++ { for i := 0; i < vs.Len(); i++ {
var rs records var rs records
rs.Append(reflect.ValueOf(vs.Get(i)), "Path", "Package", "IsPublic", "IsWeak") rv := reflect.ValueOf(vs.Get(i))
rs.Append(rv, []methodAndName{
{rv.MethodByName("Path"), "Path"},
{rv.MethodByName("Package"), "Package"},
{rv.MethodByName("IsPublic"), "IsPublic"},
{rv.MethodByName("IsWeak"), "IsWeak"},
}...)
ss = append(ss, "{"+rs.Join()+"}") ss = append(ss, "{"+rs.Join()+"}")
} }
return start + joinStrings(ss, allowMulti) + end return start + joinStrings(ss, allowMulti) + end
@ -92,34 +98,26 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
for i := 0; i < vs.Len(); i++ { for i := 0; i < vs.Len(); i++ {
m := reflect.ValueOf(vs).MethodByName("Get") m := reflect.ValueOf(vs).MethodByName("Get")
v := m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface() v := m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface()
ss = append(ss, formatDescOpt(v.(protoreflect.Descriptor), false, allowMulti && !isEnumValue)) ss = append(ss, formatDescOpt(v.(protoreflect.Descriptor), false, allowMulti && !isEnumValue, nil))
} }
return start + joinStrings(ss, allowMulti && isEnumValue) + end return start + joinStrings(ss, allowMulti && isEnumValue) + end
} }
} }
// descriptorAccessors is a list of accessors to print for each descriptor. type methodAndName struct {
// method reflect.Value
// Do not print all accessors since some contain redundant information, name string
// while others are pointers that we do not want to follow since the descriptor
// is actually a cyclic graph.
//
// Using a list allows us to print the accessors in a sensible order.
var descriptorAccessors = map[reflect.Type][]string{
reflect.TypeOf((*protoreflect.FileDescriptor)(nil)).Elem(): {"Path", "Package", "Imports", "Messages", "Enums", "Extensions", "Services"},
reflect.TypeOf((*protoreflect.MessageDescriptor)(nil)).Elem(): {"IsMapEntry", "Fields", "Oneofs", "ReservedNames", "ReservedRanges", "RequiredNumbers", "ExtensionRanges", "Messages", "Enums", "Extensions"},
reflect.TypeOf((*protoreflect.FieldDescriptor)(nil)).Elem(): {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "HasPresence", "IsExtension", "IsPacked", "IsWeak", "IsList", "IsMap", "MapKey", "MapValue", "HasDefault", "Default", "ContainingOneof", "ContainingMessage", "Message", "Enum"},
reflect.TypeOf((*protoreflect.OneofDescriptor)(nil)).Elem(): {"Fields"}, // not directly used; must keep in sync with formatDescOpt
reflect.TypeOf((*protoreflect.EnumDescriptor)(nil)).Elem(): {"Values", "ReservedNames", "ReservedRanges"},
reflect.TypeOf((*protoreflect.EnumValueDescriptor)(nil)).Elem(): {"Number"},
reflect.TypeOf((*protoreflect.ServiceDescriptor)(nil)).Elem(): {"Methods"},
reflect.TypeOf((*protoreflect.MethodDescriptor)(nil)).Elem(): {"Input", "Output", "IsStreamingClient", "IsStreamingServer"},
} }
func FormatDesc(s fmt.State, r rune, t protoreflect.Descriptor) { func FormatDesc(s fmt.State, r rune, t protoreflect.Descriptor) {
io.WriteString(s, formatDescOpt(t, true, r == 'v' && (s.Flag('+') || s.Flag('#')))) io.WriteString(s, formatDescOpt(t, true, r == 'v' && (s.Flag('+') || s.Flag('#')), nil))
} }
func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
func InternalFormatDescOptForTesting(t protoreflect.Descriptor, isRoot, allowMulti bool, record func(string)) string {
return formatDescOpt(t, isRoot, allowMulti, record)
}
func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool, record func(string)) string {
rv := reflect.ValueOf(t) rv := reflect.ValueOf(t)
rt := rv.MethodByName("ProtoType").Type().In(0) rt := rv.MethodByName("ProtoType").Type().In(0)
@ -129,26 +127,60 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
} }
_, isFile := t.(protoreflect.FileDescriptor) _, isFile := t.(protoreflect.FileDescriptor)
rs := records{allowMulti: allowMulti} rs := records{
allowMulti: allowMulti,
record: record,
}
if t.IsPlaceholder() { if t.IsPlaceholder() {
if isFile { if isFile {
rs.Append(rv, "Path", "Package", "IsPlaceholder") rs.Append(rv, []methodAndName{
{rv.MethodByName("Path"), "Path"},
{rv.MethodByName("Package"), "Package"},
{rv.MethodByName("IsPlaceholder"), "IsPlaceholder"},
}...)
} else { } else {
rs.Append(rv, "FullName", "IsPlaceholder") rs.Append(rv, []methodAndName{
{rv.MethodByName("FullName"), "FullName"},
{rv.MethodByName("IsPlaceholder"), "IsPlaceholder"},
}...)
} }
} else { } else {
switch { switch {
case isFile: case isFile:
rs.Append(rv, "Syntax") rs.Append(rv, methodAndName{rv.MethodByName("Syntax"), "Syntax"})
case isRoot: case isRoot:
rs.Append(rv, "Syntax", "FullName") rs.Append(rv, []methodAndName{
{rv.MethodByName("Syntax"), "Syntax"},
{rv.MethodByName("FullName"), "FullName"},
}...)
default: default:
rs.Append(rv, "Name") rs.Append(rv, methodAndName{rv.MethodByName("Name"), "Name"})
} }
switch t := t.(type) { switch t := t.(type) {
case protoreflect.FieldDescriptor: case protoreflect.FieldDescriptor:
for _, s := range descriptorAccessors[rt] { accessors := []methodAndName{
switch s { {rv.MethodByName("Number"), "Number"},
{rv.MethodByName("Cardinality"), "Cardinality"},
{rv.MethodByName("Kind"), "Kind"},
{rv.MethodByName("HasJSONName"), "HasJSONName"},
{rv.MethodByName("JSONName"), "JSONName"},
{rv.MethodByName("HasPresence"), "HasPresence"},
{rv.MethodByName("IsExtension"), "IsExtension"},
{rv.MethodByName("IsPacked"), "IsPacked"},
{rv.MethodByName("IsWeak"), "IsWeak"},
{rv.MethodByName("IsList"), "IsList"},
{rv.MethodByName("IsMap"), "IsMap"},
{rv.MethodByName("MapKey"), "MapKey"},
{rv.MethodByName("MapValue"), "MapValue"},
{rv.MethodByName("HasDefault"), "HasDefault"},
{rv.MethodByName("Default"), "Default"},
{rv.MethodByName("ContainingOneof"), "ContainingOneof"},
{rv.MethodByName("ContainingMessage"), "ContainingMessage"},
{rv.MethodByName("Message"), "Message"},
{rv.MethodByName("Enum"), "Enum"},
}
for _, s := range accessors {
switch s.name {
case "MapKey": case "MapKey":
if k := t.MapKey(); k != nil { if k := t.MapKey(); k != nil {
rs.recs = append(rs.recs, [2]string{"MapKey", k.Kind().String()}) rs.recs = append(rs.recs, [2]string{"MapKey", k.Kind().String()})
@ -157,20 +189,20 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
if v := t.MapValue(); v != nil { if v := t.MapValue(); v != nil {
switch v.Kind() { switch v.Kind() {
case protoreflect.EnumKind: case protoreflect.EnumKind:
rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Enum().FullName())}) rs.AppendRecs("MapValue", [2]string{"MapValue", string(v.Enum().FullName())})
case protoreflect.MessageKind, protoreflect.GroupKind: case protoreflect.MessageKind, protoreflect.GroupKind:
rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Message().FullName())}) rs.AppendRecs("MapValue", [2]string{"MapValue", string(v.Message().FullName())})
default: default:
rs.recs = append(rs.recs, [2]string{"MapValue", v.Kind().String()}) rs.AppendRecs("MapValue", [2]string{"MapValue", v.Kind().String()})
} }
} }
case "ContainingOneof": case "ContainingOneof":
if od := t.ContainingOneof(); od != nil { if od := t.ContainingOneof(); od != nil {
rs.recs = append(rs.recs, [2]string{"Oneof", string(od.Name())}) rs.AppendRecs("ContainingOneof", [2]string{"Oneof", string(od.Name())})
} }
case "ContainingMessage": case "ContainingMessage":
if t.IsExtension() { if t.IsExtension() {
rs.recs = append(rs.recs, [2]string{"Extendee", string(t.ContainingMessage().FullName())}) rs.AppendRecs("ContainingMessage", [2]string{"Extendee", string(t.ContainingMessage().FullName())})
} }
case "Message": case "Message":
if !t.IsMap() { if !t.IsMap() {
@ -187,13 +219,61 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
ss = append(ss, string(fs.Get(i).Name())) ss = append(ss, string(fs.Get(i).Name()))
} }
if len(ss) > 0 { if len(ss) > 0 {
rs.recs = append(rs.recs, [2]string{"Fields", "[" + joinStrings(ss, false) + "]"}) rs.AppendRecs("Fields", [2]string{"Fields", "[" + joinStrings(ss, false) + "]"})
} }
default:
rs.Append(rv, descriptorAccessors[rt]...) case protoreflect.FileDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Path"), "Path"},
{rv.MethodByName("Package"), "Package"},
{rv.MethodByName("Imports"), "Imports"},
{rv.MethodByName("Messages"), "Messages"},
{rv.MethodByName("Enums"), "Enums"},
{rv.MethodByName("Extensions"), "Extensions"},
{rv.MethodByName("Services"), "Services"},
}...)
case protoreflect.MessageDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("IsMapEntry"), "IsMapEntry"},
{rv.MethodByName("Fields"), "Fields"},
{rv.MethodByName("Oneofs"), "Oneofs"},
{rv.MethodByName("ReservedNames"), "ReservedNames"},
{rv.MethodByName("ReservedRanges"), "ReservedRanges"},
{rv.MethodByName("RequiredNumbers"), "RequiredNumbers"},
{rv.MethodByName("ExtensionRanges"), "ExtensionRanges"},
{rv.MethodByName("Messages"), "Messages"},
{rv.MethodByName("Enums"), "Enums"},
{rv.MethodByName("Extensions"), "Extensions"},
}...)
case protoreflect.EnumDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Values"), "Values"},
{rv.MethodByName("ReservedNames"), "ReservedNames"},
{rv.MethodByName("ReservedRanges"), "ReservedRanges"},
}...)
case protoreflect.EnumValueDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Number"), "Number"},
}...)
case protoreflect.ServiceDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Methods"), "Methods"},
}...)
case protoreflect.MethodDescriptor:
rs.Append(rv, []methodAndName{
{rv.MethodByName("Input"), "Input"},
{rv.MethodByName("Output"), "Output"},
{rv.MethodByName("IsStreamingClient"), "IsStreamingClient"},
{rv.MethodByName("IsStreamingServer"), "IsStreamingServer"},
}...)
} }
if rv.MethodByName("GoType").IsValid() { if m := rv.MethodByName("GoType"); m.IsValid() {
rs.Append(rv, "GoType") rs.Append(rv, methodAndName{m, "GoType"})
} }
} }
return start + rs.Join() + end return start + rs.Join() + end
@ -202,19 +282,34 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
type records struct { type records struct {
recs [][2]string recs [][2]string
allowMulti bool allowMulti bool
// record is a function that will be called for every Append() or
// AppendRecs() call, to be used for testing with the
// InternalFormatDescOptForTesting function.
record func(string)
} }
func (rs *records) Append(v reflect.Value, accessors ...string) { func (rs *records) AppendRecs(fieldName string, newRecs [2]string) {
if rs.record != nil {
rs.record(fieldName)
}
rs.recs = append(rs.recs, newRecs)
}
func (rs *records) Append(v reflect.Value, accessors ...methodAndName) {
for _, a := range accessors { for _, a := range accessors {
if rs.record != nil {
rs.record(a.name)
}
var rv reflect.Value var rv reflect.Value
if m := v.MethodByName(a); m.IsValid() { if a.method.IsValid() {
rv = m.Call(nil)[0] rv = a.method.Call(nil)[0]
} }
if v.Kind() == reflect.Struct && !rv.IsValid() { if v.Kind() == reflect.Struct && !rv.IsValid() {
rv = v.FieldByName(a) rv = v.FieldByName(a.name)
} }
if !rv.IsValid() { if !rv.IsValid() {
panic(fmt.Sprintf("unknown accessor: %v.%s", v.Type(), a)) panic(fmt.Sprintf("unknown accessor: %v.%s", v.Type(), a.name))
} }
if _, ok := rv.Interface().(protoreflect.Value); ok { if _, ok := rv.Interface().(protoreflect.Value); ok {
rv = rv.MethodByName("Interface").Call(nil)[0] rv = rv.MethodByName("Interface").Call(nil)[0]
@ -261,7 +356,7 @@ func (rs *records) Append(v reflect.Value, accessors ...string) {
default: default:
s = fmt.Sprint(v) s = fmt.Sprint(v)
} }
rs.recs = append(rs.recs, [2]string{a, s}) rs.recs = append(rs.recs, [2]string{a.name, s})
} }
} }

View File

@ -0,0 +1,12 @@
// Copyright 2024 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 editiondefaults contains the binary representation of the editions
// defaults.
package editiondefaults
import _ "embed"
//go:embed editions_defaults.binpb
var Defaults []byte

View File

@ -0,0 +1,4 @@
  (0ж
  (0з
  (0и ж

View File

@ -121,7 +121,7 @@ func (d *Decoder) Read() (Token, error) {
case ObjectClose: case ObjectClose:
if len(d.openStack) == 0 || if len(d.openStack) == 0 ||
d.lastToken.kind == comma || d.lastToken.kind&(Name|comma) != 0 ||
d.openStack[len(d.openStack)-1] != ObjectOpen { d.openStack[len(d.openStack)-1] != ObjectOpen {
return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString()) return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString())
} }
@ -294,7 +294,7 @@ func (d *Decoder) isValueNext() bool {
} }
// consumeToken constructs a Token for given Kind with raw value derived from // consumeToken constructs a Token for given Kind with raw value derived from
// current d.in and given size, and consumes the given size-lenght of it. // current d.in and given size, and consumes the given size-length of it.
func (d *Decoder) consumeToken(kind Kind, size int) Token { func (d *Decoder) consumeToken(kind Kind, size int) Token {
tok := Token{ tok := Token{
kind: kind, kind: kind,

View File

@ -41,8 +41,10 @@ type Encoder struct {
// //
// If indent is a non-empty string, it causes every entry for an Array or Object // If indent is a non-empty string, it causes every entry for an Array or Object
// to be preceded by the indent and trailed by a newline. // to be preceded by the indent and trailed by a newline.
func NewEncoder(indent string) (*Encoder, error) { func NewEncoder(buf []byte, indent string) (*Encoder, error) {
e := &Encoder{} e := &Encoder{
out: buf,
}
if len(indent) > 0 { if len(indent) > 0 {
if strings.Trim(indent, " \t") != "" { if strings.Trim(indent, " \t") != "" {
return nil, errors.New("indent may only be composed of space or tab characters") return nil, errors.New("indent may only be composed of space or tab characters")
@ -176,13 +178,13 @@ func appendFloat(out []byte, n float64, bitSize int) []byte {
// WriteInt writes out the given signed integer in JSON number value. // WriteInt writes out the given signed integer in JSON number value.
func (e *Encoder) WriteInt(n int64) { func (e *Encoder) WriteInt(n int64) {
e.prepareNext(scalar) e.prepareNext(scalar)
e.out = append(e.out, strconv.FormatInt(n, 10)...) e.out = strconv.AppendInt(e.out, n, 10)
} }
// WriteUint writes out the given unsigned integer in JSON number value. // WriteUint writes out the given unsigned integer in JSON number value.
func (e *Encoder) WriteUint(n uint64) { func (e *Encoder) WriteUint(n uint64) {
e.prepareNext(scalar) e.prepareNext(scalar)
e.out = append(e.out, strconv.FormatUint(n, 10)...) e.out = strconv.AppendUint(e.out, n, 10)
} }
// StartObject writes out the '{' symbol. // StartObject writes out the '{' symbol.

View File

@ -412,12 +412,13 @@ func (d *Decoder) parseFieldName() (tok Token, err error) {
// Field number. Identify if input is a valid number that is not negative // Field number. Identify if input is a valid number that is not negative
// and is decimal integer within 32-bit range. // and is decimal integer within 32-bit range.
if num := parseNumber(d.in); num.size > 0 { if num := parseNumber(d.in); num.size > 0 {
str := num.string(d.in)
if !num.neg && num.kind == numDec { if !num.neg && num.kind == numDec {
if _, err := strconv.ParseInt(string(d.in[:num.size]), 10, 32); err == nil { if _, err := strconv.ParseInt(str, 10, 32); err == nil {
return d.consumeToken(Name, num.size, uint8(FieldNumber)), nil return d.consumeToken(Name, num.size, uint8(FieldNumber)), nil
} }
} }
return Token{}, d.newSyntaxError("invalid field number: %s", d.in[:num.size]) return Token{}, d.newSyntaxError("invalid field number: %s", str)
} }
return Token{}, d.newSyntaxError("invalid field name: %s", errId(d.in)) return Token{}, d.newSyntaxError("invalid field name: %s", errId(d.in))

View File

@ -15,17 +15,12 @@ func (d *Decoder) parseNumberValue() (Token, bool) {
if num.neg { if num.neg {
numAttrs |= isNegative numAttrs |= isNegative
} }
strSize := num.size
last := num.size - 1
if num.kind == numFloat && (d.in[last] == 'f' || d.in[last] == 'F') {
strSize = last
}
tok := Token{ tok := Token{
kind: Scalar, kind: Scalar,
attrs: numberValue, attrs: numberValue,
pos: len(d.orig) - len(d.in), pos: len(d.orig) - len(d.in),
raw: d.in[:num.size], raw: d.in[:num.size],
str: string(d.in[:strSize]), str: num.string(d.in),
numAttrs: numAttrs, numAttrs: numAttrs,
} }
d.consume(num.size) d.consume(num.size)
@ -46,6 +41,27 @@ type number struct {
kind uint8 kind uint8
neg bool neg bool
size int size int
// if neg, this is the length of whitespace and comments between
// the minus sign and the rest fo the number literal
sep int
}
func (num number) string(data []byte) string {
strSize := num.size
last := num.size - 1
if num.kind == numFloat && (data[last] == 'f' || data[last] == 'F') {
strSize = last
}
if num.neg && num.sep > 0 {
// strip whitespace/comments between negative sign and the rest
strLen := strSize - num.sep
str := make([]byte, strLen)
str[0] = data[0]
copy(str[1:], data[num.sep+1:strSize])
return string(str)
}
return string(data[:strSize])
} }
// parseNumber constructs a number object from given input. It allows for the // parseNumber constructs a number object from given input. It allows for the
@ -67,19 +83,22 @@ func parseNumber(input []byte) number {
} }
// Optional - // Optional -
var sep int
if s[0] == '-' { if s[0] == '-' {
neg = true neg = true
s = s[1:] s = s[1:]
size++ size++
// Consume any whitespace or comments between the
// negative sign and the rest of the number
lenBefore := len(s)
s = consume(s, 0)
sep = lenBefore - len(s)
size += sep
if len(s) == 0 { if len(s) == 0 {
return number{} return number{}
} }
} }
// C++ allows for whitespace and comments in between the negative sign and
// the rest of the number. This logic currently does not but is consistent
// with v1.
switch { switch {
case s[0] == '0': case s[0] == '0':
if len(s) > 1 { if len(s) > 1 {
@ -116,7 +135,7 @@ func parseNumber(input []byte) number {
if len(s) > 0 && !isDelim(s[0]) { if len(s) > 0 && !isDelim(s[0]) {
return number{} return number{}
} }
return number{kind: kind, neg: neg, size: size} return number{kind: kind, neg: neg, size: size, sep: sep}
} }
} }
s = s[1:] s = s[1:]
@ -188,5 +207,5 @@ func parseNumber(input []byte) number {
return number{} return number{}
} }
return number{kind: kind, neg: neg, size: size} return number{kind: kind, neg: neg, size: size, sep: sep}
} }

View File

@ -53,8 +53,10 @@ type encoderState struct {
// If outputASCII is true, strings will be serialized in such a way that // If outputASCII is true, strings will be serialized in such a way that
// multi-byte UTF-8 sequences are escaped. This property ensures that the // multi-byte UTF-8 sequences are escaped. This property ensures that the
// overall output is ASCII (as opposed to UTF-8). // overall output is ASCII (as opposed to UTF-8).
func NewEncoder(indent string, delims [2]byte, outputASCII bool) (*Encoder, error) { func NewEncoder(buf []byte, indent string, delims [2]byte, outputASCII bool) (*Encoder, error) {
e := &Encoder{} e := &Encoder{
encoderState: encoderState{out: buf},
}
if len(indent) > 0 { if len(indent) > 0 {
if strings.Trim(indent, " \t") != "" { if strings.Trim(indent, " \t") != "" {
return nil, errors.New("indent may only be composed of space and tab characters") return nil, errors.New("indent may only be composed of space and tab characters")
@ -195,13 +197,13 @@ func appendFloat(out []byte, n float64, bitSize int) []byte {
// WriteInt writes out the given signed integer value. // WriteInt writes out the given signed integer value.
func (e *Encoder) WriteInt(n int64) { func (e *Encoder) WriteInt(n int64) {
e.prepareNext(scalar) e.prepareNext(scalar)
e.out = append(e.out, strconv.FormatInt(n, 10)...) e.out = strconv.AppendInt(e.out, n, 10)
} }
// WriteUint writes out the given unsigned integer value. // WriteUint writes out the given unsigned integer value.
func (e *Encoder) WriteUint(n uint64) { func (e *Encoder) WriteUint(n uint64) {
e.prepareNext(scalar) e.prepareNext(scalar)
e.out = append(e.out, strconv.FormatUint(n, 10)...) e.out = strconv.AppendUint(e.out, n, 10)
} }
// WriteLiteral writes out the given string as a literal value without quotes. // WriteLiteral writes out the given string as a literal value without quotes.

View File

@ -21,11 +21,26 @@ import (
"google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/reflect/protoregistry"
) )
// 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
)
// The types in this file may have a suffix: // The types in this file may have a suffix:
// • L0: Contains fields common to all descriptors (except File) and // • L0: Contains fields common to all descriptors (except File) and
// must be initialized up front. // must be initialized up front.
// • L1: Contains fields specific to a descriptor and // • L1: Contains fields specific to a descriptor and
// must be initialized up front. // 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 // • L2: Contains fields that are lazily initialized when constructing
// from the raw file descriptor. When constructing as a literal, the L2 // from the raw file descriptor. When constructing as a literal, the L2
// fields must be initialized up front. // fields must be initialized up front.
@ -44,6 +59,7 @@ type (
} }
FileL1 struct { FileL1 struct {
Syntax protoreflect.Syntax Syntax protoreflect.Syntax
Edition Edition // Only used if Syntax == Editions
Path string Path string
Package protoreflect.FullName Package protoreflect.FullName
@ -51,12 +67,41 @@ type (
Messages Messages Messages Messages
Extensions Extensions Extensions Extensions
Services Services Services Services
EditionFeatures EditionFeatures
} }
FileL2 struct { FileL2 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage
Imports FileImports Imports FileImports
Locations SourceLocations Locations SourceLocations
} }
EditionFeatures struct {
// 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
}
) )
func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd } func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
@ -117,6 +162,8 @@ type (
} }
EnumL1 struct { EnumL1 struct {
eagerValues bool // controls whether EnumL2.Values is already populated eagerValues bool // controls whether EnumL2.Values is already populated
EditionFeatures EditionFeatures
} }
EnumL2 struct { EnumL2 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage
@ -178,6 +225,8 @@ type (
Extensions Extensions Extensions Extensions
IsMapEntry bool // promoted from google.protobuf.MessageOptions IsMapEntry bool // promoted from google.protobuf.MessageOptions
IsMessageSet bool // promoted from google.protobuf.MessageOptions IsMessageSet bool // promoted from google.protobuf.MessageOptions
EditionFeatures EditionFeatures
} }
MessageL2 struct { MessageL2 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage
@ -210,6 +259,8 @@ type (
ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
Enum protoreflect.EnumDescriptor Enum protoreflect.EnumDescriptor
Message protoreflect.MessageDescriptor Message protoreflect.MessageDescriptor
EditionFeatures EditionFeatures
} }
Oneof struct { Oneof struct {
@ -219,6 +270,8 @@ type (
OneofL1 struct { OneofL1 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage
Fields OneofFields // must be consistent with Message.Fields.ContainingOneof Fields OneofFields // must be consistent with Message.Fields.ContainingOneof
EditionFeatures EditionFeatures
} }
) )
@ -268,23 +321,36 @@ func (fd *Field) Options() protoreflect.ProtoMessage {
} }
func (fd *Field) Number() protoreflect.FieldNumber { return fd.L1.Number } func (fd *Field) Number() protoreflect.FieldNumber { return fd.L1.Number }
func (fd *Field) Cardinality() protoreflect.Cardinality { return fd.L1.Cardinality } func (fd *Field) Cardinality() protoreflect.Cardinality { return fd.L1.Cardinality }
func (fd *Field) Kind() protoreflect.Kind { return fd.L1.Kind } func (fd *Field) Kind() protoreflect.Kind {
func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON } return fd.L1.Kind
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) 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 { func (fd *Field) HasPresence() bool {
return fd.L1.Cardinality != protoreflect.Repeated && (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil) if fd.L1.Cardinality == protoreflect.Repeated {
return false
}
explicitFieldPresence := fd.Syntax() == protoreflect.Editions && fd.L1.EditionFeatures.IsFieldPresence
return fd.Syntax() == protoreflect.Proto2 || explicitFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil
} }
func (fd *Field) HasOptionalKeyword() bool { 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 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 { func (fd *Field) IsPacked() bool {
if !fd.L1.HasPacked && fd.L0.ParentFile.L1.Syntax != protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Repeated { if fd.L1.Cardinality != protoreflect.Repeated {
switch fd.L1.Kind { return false
case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind: }
default: switch fd.L1.Kind {
return true case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
} return false
}
if fd.L0.ParentFile.L1.Syntax == protoreflect.Editions {
return fd.L1.EditionFeatures.IsPacked
}
if fd.L0.ParentFile.L1.Syntax == protoreflect.Proto3 {
// proto3 repeated fields are packed by default.
return !fd.L1.HasPacked || fd.L1.IsPacked
} }
return fd.L1.IsPacked return fd.L1.IsPacked
} }
@ -333,6 +399,9 @@ func (fd *Field) ProtoType(protoreflect.FieldDescriptor) {}
// WARNING: This method is exempt from the compatibility promise and may be // WARNING: This method is exempt from the compatibility promise and may be
// removed in the future without warning. // removed in the future without warning.
func (fd *Field) EnforceUTF8() bool { func (fd *Field) EnforceUTF8() bool {
if fd.L0.ParentFile.L1.Syntax == protoreflect.Editions {
return fd.L1.EditionFeatures.IsUTF8Validated
}
if fd.L1.HasEnforceUTF8 { if fd.L1.HasEnforceUTF8 {
return fd.L1.EnforceUTF8 return fd.L1.EnforceUTF8
} }
@ -359,10 +428,11 @@ type (
L2 *ExtensionL2 // protected by fileDesc.once L2 *ExtensionL2 // protected by fileDesc.once
} }
ExtensionL1 struct { ExtensionL1 struct {
Number protoreflect.FieldNumber Number protoreflect.FieldNumber
Extendee protoreflect.MessageDescriptor Extendee protoreflect.MessageDescriptor
Cardinality protoreflect.Cardinality Cardinality protoreflect.Cardinality
Kind protoreflect.Kind Kind protoreflect.Kind
EditionFeatures EditionFeatures
} }
ExtensionL2 struct { ExtensionL2 struct {
Options func() protoreflect.ProtoMessage Options func() protoreflect.ProtoMessage

View File

@ -5,6 +5,7 @@
package filedesc package filedesc
import ( import (
"fmt"
"sync" "sync"
"google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/encoding/protowire"
@ -98,6 +99,7 @@ func (fd *File) unmarshalSeed(b []byte) {
var prevField protoreflect.FieldNumber var prevField protoreflect.FieldNumber
var numEnums, numMessages, numExtensions, numServices int var numEnums, numMessages, numExtensions, numServices int
var posEnums, posMessages, posExtensions, posServices int var posEnums, posMessages, posExtensions, posServices int
var options []byte
b0 := b b0 := b
for len(b) > 0 { for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b) num, typ, n := protowire.ConsumeTag(b)
@ -113,6 +115,8 @@ func (fd *File) unmarshalSeed(b []byte) {
fd.L1.Syntax = protoreflect.Proto2 fd.L1.Syntax = protoreflect.Proto2
case "proto3": case "proto3":
fd.L1.Syntax = protoreflect.Proto3 fd.L1.Syntax = protoreflect.Proto3
case "editions":
fd.L1.Syntax = protoreflect.Editions
default: default:
panic("invalid syntax") panic("invalid syntax")
} }
@ -120,6 +124,8 @@ func (fd *File) unmarshalSeed(b []byte) {
fd.L1.Path = sb.MakeString(v) fd.L1.Path = sb.MakeString(v)
case genid.FileDescriptorProto_Package_field_number: case genid.FileDescriptorProto_Package_field_number:
fd.L1.Package = protoreflect.FullName(sb.MakeString(v)) fd.L1.Package = protoreflect.FullName(sb.MakeString(v))
case genid.FileDescriptorProto_Options_field_number:
options = v
case genid.FileDescriptorProto_EnumType_field_number: case genid.FileDescriptorProto_EnumType_field_number:
if prevField != genid.FileDescriptorProto_EnumType_field_number { if prevField != genid.FileDescriptorProto_EnumType_field_number {
if numEnums > 0 { if numEnums > 0 {
@ -154,6 +160,13 @@ func (fd *File) unmarshalSeed(b []byte) {
numServices++ numServices++
} }
prevField = num prevField = num
case protowire.VarintType:
v, m := protowire.ConsumeVarint(b)
b = b[m:]
switch num {
case genid.FileDescriptorProto_Edition_field_number:
fd.L1.Edition = Edition(v)
}
default: default:
m := protowire.ConsumeFieldValue(num, typ, b) m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:] b = b[m:]
@ -166,6 +179,15 @@ func (fd *File) unmarshalSeed(b []byte) {
fd.L1.Syntax = protoreflect.Proto2 fd.L1.Syntax = protoreflect.Proto2
} }
if fd.L1.Syntax == protoreflect.Editions {
fd.L1.EditionFeatures = getFeaturesFor(fd.L1.Edition)
}
// Parse editions features from options if any
if options != nil {
fd.unmarshalSeedOptions(options)
}
// Must allocate all declarations before parsing each descriptor type // Must allocate all declarations before parsing each descriptor type
// to ensure we handled all descriptors in "flattened ordering". // to ensure we handled all descriptors in "flattened ordering".
if numEnums > 0 { if numEnums > 0 {
@ -219,6 +241,28 @@ func (fd *File) unmarshalSeed(b []byte) {
} }
} }
func (fd *File) unmarshalSeedOptions(b []byte) {
for b := b; len(b) > 0; {
num, typ, n := protowire.ConsumeTag(b)
b = b[n:]
switch typ {
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.FileOptions_Features_field_number:
if fd.Syntax() != protoreflect.Editions {
panic(fmt.Sprintf("invalid descriptor: using edition features in a proto with syntax %s", fd.Syntax()))
}
fd.L1.EditionFeatures = unmarshalFeatureSet(v, fd.L1.EditionFeatures)
}
default:
m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:]
}
}
}
func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) { func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
ed.L0.ParentFile = pf ed.L0.ParentFile = pf
ed.L0.Parent = pd ed.L0.Parent = pd
@ -275,6 +319,7 @@ func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protor
md.L0.ParentFile = pf md.L0.ParentFile = pf
md.L0.Parent = pd md.L0.Parent = pd
md.L0.Index = i md.L0.Index = i
md.L1.EditionFeatures = featuresFromParentDesc(md.Parent())
var prevField protoreflect.FieldNumber var prevField protoreflect.FieldNumber
var numEnums, numMessages, numExtensions int var numEnums, numMessages, numExtensions int
@ -380,6 +425,13 @@ func (md *Message) unmarshalSeedOptions(b []byte) {
case genid.MessageOptions_MessageSetWireFormat_field_number: case genid.MessageOptions_MessageSetWireFormat_field_number:
md.L1.IsMessageSet = protowire.DecodeBool(v) md.L1.IsMessageSet = protowire.DecodeBool(v)
} }
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.MessageOptions_Features_field_number:
md.L1.EditionFeatures = unmarshalFeatureSet(v, md.L1.EditionFeatures)
}
default: default:
m := protowire.ConsumeFieldValue(num, typ, b) m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:] b = b[m:]

View File

@ -414,6 +414,7 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref
fd.L0.ParentFile = pf fd.L0.ParentFile = pf
fd.L0.Parent = pd fd.L0.Parent = pd
fd.L0.Index = i fd.L0.Index = i
fd.L1.EditionFeatures = featuresFromParentDesc(fd.Parent())
var rawTypeName []byte var rawTypeName []byte
var rawOptions []byte var rawOptions []byte
@ -465,6 +466,12 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref
b = b[m:] b = b[m:]
} }
} }
if fd.Syntax() == protoreflect.Editions && fd.L1.Kind == protoreflect.MessageKind && fd.L1.EditionFeatures.IsDelimitedEncoded {
fd.L1.Kind = protoreflect.GroupKind
}
if fd.Syntax() == protoreflect.Editions && fd.L1.EditionFeatures.IsLegacyRequired {
fd.L1.Cardinality = protoreflect.Required
}
if rawTypeName != nil { if rawTypeName != nil {
name := makeFullName(sb, rawTypeName) name := makeFullName(sb, rawTypeName)
switch fd.L1.Kind { switch fd.L1.Kind {
@ -497,6 +504,13 @@ func (fd *Field) unmarshalOptions(b []byte) {
fd.L1.HasEnforceUTF8 = true fd.L1.HasEnforceUTF8 = true
fd.L1.EnforceUTF8 = protowire.DecodeBool(v) fd.L1.EnforceUTF8 = protowire.DecodeBool(v)
} }
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.FieldOptions_Features_field_number:
fd.L1.EditionFeatures = unmarshalFeatureSet(v, fd.L1.EditionFeatures)
}
default: default:
m := protowire.ConsumeFieldValue(num, typ, b) m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:] b = b[m:]
@ -534,6 +548,7 @@ func (od *Oneof) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref
func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) { func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
var rawTypeName []byte var rawTypeName []byte
var rawOptions []byte var rawOptions []byte
xd.L1.EditionFeatures = featuresFromParentDesc(xd.L1.Extendee)
xd.L2 = new(ExtensionL2) xd.L2 = new(ExtensionL2)
for len(b) > 0 { for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b) num, typ, n := protowire.ConsumeTag(b)
@ -565,6 +580,12 @@ func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
b = b[m:] b = b[m:]
} }
} }
if xd.Syntax() == protoreflect.Editions && xd.L1.Kind == protoreflect.MessageKind && xd.L1.EditionFeatures.IsDelimitedEncoded {
xd.L1.Kind = protoreflect.GroupKind
}
if xd.Syntax() == protoreflect.Editions && xd.L1.EditionFeatures.IsLegacyRequired {
xd.L1.Cardinality = protoreflect.Required
}
if rawTypeName != nil { if rawTypeName != nil {
name := makeFullName(sb, rawTypeName) name := makeFullName(sb, rawTypeName)
switch xd.L1.Kind { switch xd.L1.Kind {
@ -589,6 +610,13 @@ func (xd *Extension) unmarshalOptions(b []byte) {
case genid.FieldOptions_Packed_field_number: case genid.FieldOptions_Packed_field_number:
xd.L2.IsPacked = protowire.DecodeBool(v) xd.L2.IsPacked = protowire.DecodeBool(v)
} }
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.FieldOptions_Features_field_number:
xd.L1.EditionFeatures = unmarshalFeatureSet(v, xd.L1.EditionFeatures)
}
default: default:
m := protowire.ConsumeFieldValue(num, typ, b) m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:] b = b[m:]

View File

@ -0,0 +1,142 @@
// Copyright 2024 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 (
"fmt"
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/editiondefaults"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/reflect/protoreflect"
)
var defaultsCache = make(map[Edition]EditionFeatures)
func init() {
unmarshalEditionDefaults(editiondefaults.Defaults)
}
func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
for len(b) > 0 {
num, _, n := protowire.ConsumeTag(b)
b = b[n:]
switch num {
case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
v, m := protowire.ConsumeVarint(b)
b = b[m:]
parent.GenerateLegacyUnmarshalJSON = protowire.DecodeBool(v)
default:
panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
}
}
return parent
}
func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b)
b = b[n:]
switch typ {
case protowire.VarintType:
v, m := protowire.ConsumeVarint(b)
b = b[m:]
switch num {
case genid.FeatureSet_FieldPresence_field_number:
parent.IsFieldPresence = v == genid.FeatureSet_EXPLICIT_enum_value || v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
parent.IsLegacyRequired = v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
case genid.FeatureSet_EnumType_field_number:
parent.IsOpenEnum = v == genid.FeatureSet_OPEN_enum_value
case genid.FeatureSet_RepeatedFieldEncoding_field_number:
parent.IsPacked = v == genid.FeatureSet_PACKED_enum_value
case genid.FeatureSet_Utf8Validation_field_number:
parent.IsUTF8Validated = v == genid.FeatureSet_VERIFY_enum_value
case genid.FeatureSet_MessageEncoding_field_number:
parent.IsDelimitedEncoded = v == genid.FeatureSet_DELIMITED_enum_value
case genid.FeatureSet_JsonFormat_field_number:
parent.IsJSONCompliant = v == genid.FeatureSet_ALLOW_enum_value
default:
panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
}
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
parent = unmarshalGoFeature(v, parent)
}
}
}
return parent
}
func featuresFromParentDesc(parentDesc protoreflect.Descriptor) EditionFeatures {
var parentFS EditionFeatures
switch p := parentDesc.(type) {
case *File:
parentFS = p.L1.EditionFeatures
case *Message:
parentFS = p.L1.EditionFeatures
default:
panic(fmt.Sprintf("unknown parent type %T", parentDesc))
}
return parentFS
}
func unmarshalEditionDefault(b []byte) {
var ed Edition
var fs EditionFeatures
for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b)
b = b[n:]
switch typ {
case protowire.VarintType:
v, m := protowire.ConsumeVarint(b)
b = b[m:]
switch num {
case genid.FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number:
ed = Edition(v)
}
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]
switch num {
case genid.FeatureSetDefaults_FeatureSetEditionDefault_Features_field_number:
fs = unmarshalFeatureSet(v, fs)
}
}
}
defaultsCache[ed] = fs
}
func unmarshalEditionDefaults(b []byte) {
for len(b) > 0 {
num, _, n := protowire.ConsumeTag(b)
b = b[n:]
switch num {
case genid.FeatureSetDefaults_Defaults_field_number:
def, m := protowire.ConsumeBytes(b)
b = b[m:]
unmarshalEditionDefault(def)
case genid.FeatureSetDefaults_MinimumEdition_field_number,
genid.FeatureSetDefaults_MaximumEdition_field_number:
// We don't care about the minimum and maximum editions. If the
// edition we are looking for later on is not in the cache we know
// it is outside of the range between minimum and maximum edition.
_, m := protowire.ConsumeVarint(b)
b = b[m:]
default:
panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
}
}
}
func getFeaturesFor(ed Edition) EditionFeatures {
if def, ok := defaultsCache[ed]; ok {
return def
}
panic(fmt.Sprintf("unsupported edition: %v", ed))
}

View File

@ -12,6 +12,27 @@ import (
const File_google_protobuf_descriptor_proto = "google/protobuf/descriptor.proto" const File_google_protobuf_descriptor_proto = "google/protobuf/descriptor.proto"
// Full and short names for google.protobuf.Edition.
const (
Edition_enum_fullname = "google.protobuf.Edition"
Edition_enum_name = "Edition"
)
// Enum values for google.protobuf.Edition.
const (
Edition_EDITION_UNKNOWN_enum_value = 0
Edition_EDITION_PROTO2_enum_value = 998
Edition_EDITION_PROTO3_enum_value = 999
Edition_EDITION_2023_enum_value = 1000
Edition_EDITION_2024_enum_value = 1001
Edition_EDITION_1_TEST_ONLY_enum_value = 1
Edition_EDITION_2_TEST_ONLY_enum_value = 2
Edition_EDITION_99997_TEST_ONLY_enum_value = 99997
Edition_EDITION_99998_TEST_ONLY_enum_value = 99998
Edition_EDITION_99999_TEST_ONLY_enum_value = 99999
Edition_EDITION_MAX_enum_value = 2147483647
)
// Names for google.protobuf.FileDescriptorSet. // Names for google.protobuf.FileDescriptorSet.
const ( const (
FileDescriptorSet_message_name protoreflect.Name = "FileDescriptorSet" FileDescriptorSet_message_name protoreflect.Name = "FileDescriptorSet"
@ -50,6 +71,7 @@ const (
FileDescriptorProto_Options_field_name protoreflect.Name = "options" FileDescriptorProto_Options_field_name protoreflect.Name = "options"
FileDescriptorProto_SourceCodeInfo_field_name protoreflect.Name = "source_code_info" FileDescriptorProto_SourceCodeInfo_field_name protoreflect.Name = "source_code_info"
FileDescriptorProto_Syntax_field_name protoreflect.Name = "syntax" FileDescriptorProto_Syntax_field_name protoreflect.Name = "syntax"
FileDescriptorProto_Edition_field_name protoreflect.Name = "edition"
FileDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.name" FileDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.name"
FileDescriptorProto_Package_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.package" FileDescriptorProto_Package_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.package"
@ -63,6 +85,7 @@ const (
FileDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.options" FileDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.options"
FileDescriptorProto_SourceCodeInfo_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.source_code_info" FileDescriptorProto_SourceCodeInfo_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.source_code_info"
FileDescriptorProto_Syntax_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.syntax" FileDescriptorProto_Syntax_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.syntax"
FileDescriptorProto_Edition_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.edition"
) )
// Field numbers for google.protobuf.FileDescriptorProto. // Field numbers for google.protobuf.FileDescriptorProto.
@ -79,6 +102,7 @@ const (
FileDescriptorProto_Options_field_number protoreflect.FieldNumber = 8 FileDescriptorProto_Options_field_number protoreflect.FieldNumber = 8
FileDescriptorProto_SourceCodeInfo_field_number protoreflect.FieldNumber = 9 FileDescriptorProto_SourceCodeInfo_field_number protoreflect.FieldNumber = 9
FileDescriptorProto_Syntax_field_number protoreflect.FieldNumber = 12 FileDescriptorProto_Syntax_field_number protoreflect.FieldNumber = 12
FileDescriptorProto_Edition_field_number protoreflect.FieldNumber = 14
) )
// Names for google.protobuf.DescriptorProto. // Names for google.protobuf.DescriptorProto.
@ -180,13 +204,64 @@ const (
// Field names for google.protobuf.ExtensionRangeOptions. // Field names for google.protobuf.ExtensionRangeOptions.
const ( const (
ExtensionRangeOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ExtensionRangeOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
ExtensionRangeOptions_Declaration_field_name protoreflect.Name = "declaration"
ExtensionRangeOptions_Features_field_name protoreflect.Name = "features"
ExtensionRangeOptions_Verification_field_name protoreflect.Name = "verification"
ExtensionRangeOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.uninterpreted_option" ExtensionRangeOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.uninterpreted_option"
ExtensionRangeOptions_Declaration_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.declaration"
ExtensionRangeOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.features"
ExtensionRangeOptions_Verification_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.verification"
) )
// Field numbers for google.protobuf.ExtensionRangeOptions. // Field numbers for google.protobuf.ExtensionRangeOptions.
const ( const (
ExtensionRangeOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ExtensionRangeOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
ExtensionRangeOptions_Declaration_field_number protoreflect.FieldNumber = 2
ExtensionRangeOptions_Features_field_number protoreflect.FieldNumber = 50
ExtensionRangeOptions_Verification_field_number protoreflect.FieldNumber = 3
)
// Full and short names for google.protobuf.ExtensionRangeOptions.VerificationState.
const (
ExtensionRangeOptions_VerificationState_enum_fullname = "google.protobuf.ExtensionRangeOptions.VerificationState"
ExtensionRangeOptions_VerificationState_enum_name = "VerificationState"
)
// Enum values for google.protobuf.ExtensionRangeOptions.VerificationState.
const (
ExtensionRangeOptions_DECLARATION_enum_value = 0
ExtensionRangeOptions_UNVERIFIED_enum_value = 1
)
// Names for google.protobuf.ExtensionRangeOptions.Declaration.
const (
ExtensionRangeOptions_Declaration_message_name protoreflect.Name = "Declaration"
ExtensionRangeOptions_Declaration_message_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration"
)
// Field names for google.protobuf.ExtensionRangeOptions.Declaration.
const (
ExtensionRangeOptions_Declaration_Number_field_name protoreflect.Name = "number"
ExtensionRangeOptions_Declaration_FullName_field_name protoreflect.Name = "full_name"
ExtensionRangeOptions_Declaration_Type_field_name protoreflect.Name = "type"
ExtensionRangeOptions_Declaration_Reserved_field_name protoreflect.Name = "reserved"
ExtensionRangeOptions_Declaration_Repeated_field_name protoreflect.Name = "repeated"
ExtensionRangeOptions_Declaration_Number_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.number"
ExtensionRangeOptions_Declaration_FullName_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.full_name"
ExtensionRangeOptions_Declaration_Type_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.type"
ExtensionRangeOptions_Declaration_Reserved_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.reserved"
ExtensionRangeOptions_Declaration_Repeated_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.repeated"
)
// Field numbers for google.protobuf.ExtensionRangeOptions.Declaration.
const (
ExtensionRangeOptions_Declaration_Number_field_number protoreflect.FieldNumber = 1
ExtensionRangeOptions_Declaration_FullName_field_number protoreflect.FieldNumber = 2
ExtensionRangeOptions_Declaration_Type_field_number protoreflect.FieldNumber = 3
ExtensionRangeOptions_Declaration_Reserved_field_number protoreflect.FieldNumber = 5
ExtensionRangeOptions_Declaration_Repeated_field_number protoreflect.FieldNumber = 6
) )
// Names for google.protobuf.FieldDescriptorProto. // Names for google.protobuf.FieldDescriptorProto.
@ -243,12 +318,41 @@ const (
FieldDescriptorProto_Type_enum_name = "Type" FieldDescriptorProto_Type_enum_name = "Type"
) )
// Enum values for google.protobuf.FieldDescriptorProto.Type.
const (
FieldDescriptorProto_TYPE_DOUBLE_enum_value = 1
FieldDescriptorProto_TYPE_FLOAT_enum_value = 2
FieldDescriptorProto_TYPE_INT64_enum_value = 3
FieldDescriptorProto_TYPE_UINT64_enum_value = 4
FieldDescriptorProto_TYPE_INT32_enum_value = 5
FieldDescriptorProto_TYPE_FIXED64_enum_value = 6
FieldDescriptorProto_TYPE_FIXED32_enum_value = 7
FieldDescriptorProto_TYPE_BOOL_enum_value = 8
FieldDescriptorProto_TYPE_STRING_enum_value = 9
FieldDescriptorProto_TYPE_GROUP_enum_value = 10
FieldDescriptorProto_TYPE_MESSAGE_enum_value = 11
FieldDescriptorProto_TYPE_BYTES_enum_value = 12
FieldDescriptorProto_TYPE_UINT32_enum_value = 13
FieldDescriptorProto_TYPE_ENUM_enum_value = 14
FieldDescriptorProto_TYPE_SFIXED32_enum_value = 15
FieldDescriptorProto_TYPE_SFIXED64_enum_value = 16
FieldDescriptorProto_TYPE_SINT32_enum_value = 17
FieldDescriptorProto_TYPE_SINT64_enum_value = 18
)
// Full and short names for google.protobuf.FieldDescriptorProto.Label. // Full and short names for google.protobuf.FieldDescriptorProto.Label.
const ( const (
FieldDescriptorProto_Label_enum_fullname = "google.protobuf.FieldDescriptorProto.Label" FieldDescriptorProto_Label_enum_fullname = "google.protobuf.FieldDescriptorProto.Label"
FieldDescriptorProto_Label_enum_name = "Label" FieldDescriptorProto_Label_enum_name = "Label"
) )
// Enum values for google.protobuf.FieldDescriptorProto.Label.
const (
FieldDescriptorProto_LABEL_OPTIONAL_enum_value = 1
FieldDescriptorProto_LABEL_REPEATED_enum_value = 3
FieldDescriptorProto_LABEL_REQUIRED_enum_value = 2
)
// Names for google.protobuf.OneofDescriptorProto. // Names for google.protobuf.OneofDescriptorProto.
const ( const (
OneofDescriptorProto_message_name protoreflect.Name = "OneofDescriptorProto" OneofDescriptorProto_message_name protoreflect.Name = "OneofDescriptorProto"
@ -420,7 +524,6 @@ const (
FileOptions_CcGenericServices_field_name protoreflect.Name = "cc_generic_services" FileOptions_CcGenericServices_field_name protoreflect.Name = "cc_generic_services"
FileOptions_JavaGenericServices_field_name protoreflect.Name = "java_generic_services" FileOptions_JavaGenericServices_field_name protoreflect.Name = "java_generic_services"
FileOptions_PyGenericServices_field_name protoreflect.Name = "py_generic_services" FileOptions_PyGenericServices_field_name protoreflect.Name = "py_generic_services"
FileOptions_PhpGenericServices_field_name protoreflect.Name = "php_generic_services"
FileOptions_Deprecated_field_name protoreflect.Name = "deprecated" FileOptions_Deprecated_field_name protoreflect.Name = "deprecated"
FileOptions_CcEnableArenas_field_name protoreflect.Name = "cc_enable_arenas" FileOptions_CcEnableArenas_field_name protoreflect.Name = "cc_enable_arenas"
FileOptions_ObjcClassPrefix_field_name protoreflect.Name = "objc_class_prefix" FileOptions_ObjcClassPrefix_field_name protoreflect.Name = "objc_class_prefix"
@ -430,6 +533,7 @@ const (
FileOptions_PhpNamespace_field_name protoreflect.Name = "php_namespace" FileOptions_PhpNamespace_field_name protoreflect.Name = "php_namespace"
FileOptions_PhpMetadataNamespace_field_name protoreflect.Name = "php_metadata_namespace" FileOptions_PhpMetadataNamespace_field_name protoreflect.Name = "php_metadata_namespace"
FileOptions_RubyPackage_field_name protoreflect.Name = "ruby_package" FileOptions_RubyPackage_field_name protoreflect.Name = "ruby_package"
FileOptions_Features_field_name protoreflect.Name = "features"
FileOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" FileOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
FileOptions_JavaPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_package" FileOptions_JavaPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_package"
@ -442,7 +546,6 @@ const (
FileOptions_CcGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_generic_services" FileOptions_CcGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_generic_services"
FileOptions_JavaGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generic_services" FileOptions_JavaGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generic_services"
FileOptions_PyGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.py_generic_services" FileOptions_PyGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.py_generic_services"
FileOptions_PhpGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_generic_services"
FileOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.deprecated" FileOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.deprecated"
FileOptions_CcEnableArenas_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_enable_arenas" FileOptions_CcEnableArenas_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_enable_arenas"
FileOptions_ObjcClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.objc_class_prefix" FileOptions_ObjcClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.objc_class_prefix"
@ -452,6 +555,7 @@ const (
FileOptions_PhpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_namespace" FileOptions_PhpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_namespace"
FileOptions_PhpMetadataNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_metadata_namespace" FileOptions_PhpMetadataNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_metadata_namespace"
FileOptions_RubyPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.ruby_package" FileOptions_RubyPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.ruby_package"
FileOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.features"
FileOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.uninterpreted_option" FileOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.uninterpreted_option"
) )
@ -467,7 +571,6 @@ const (
FileOptions_CcGenericServices_field_number protoreflect.FieldNumber = 16 FileOptions_CcGenericServices_field_number protoreflect.FieldNumber = 16
FileOptions_JavaGenericServices_field_number protoreflect.FieldNumber = 17 FileOptions_JavaGenericServices_field_number protoreflect.FieldNumber = 17
FileOptions_PyGenericServices_field_number protoreflect.FieldNumber = 18 FileOptions_PyGenericServices_field_number protoreflect.FieldNumber = 18
FileOptions_PhpGenericServices_field_number protoreflect.FieldNumber = 42
FileOptions_Deprecated_field_number protoreflect.FieldNumber = 23 FileOptions_Deprecated_field_number protoreflect.FieldNumber = 23
FileOptions_CcEnableArenas_field_number protoreflect.FieldNumber = 31 FileOptions_CcEnableArenas_field_number protoreflect.FieldNumber = 31
FileOptions_ObjcClassPrefix_field_number protoreflect.FieldNumber = 36 FileOptions_ObjcClassPrefix_field_number protoreflect.FieldNumber = 36
@ -477,6 +580,7 @@ const (
FileOptions_PhpNamespace_field_number protoreflect.FieldNumber = 41 FileOptions_PhpNamespace_field_number protoreflect.FieldNumber = 41
FileOptions_PhpMetadataNamespace_field_number protoreflect.FieldNumber = 44 FileOptions_PhpMetadataNamespace_field_number protoreflect.FieldNumber = 44
FileOptions_RubyPackage_field_number protoreflect.FieldNumber = 45 FileOptions_RubyPackage_field_number protoreflect.FieldNumber = 45
FileOptions_Features_field_number protoreflect.FieldNumber = 50
FileOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 FileOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -486,6 +590,13 @@ const (
FileOptions_OptimizeMode_enum_name = "OptimizeMode" FileOptions_OptimizeMode_enum_name = "OptimizeMode"
) )
// Enum values for google.protobuf.FileOptions.OptimizeMode.
const (
FileOptions_SPEED_enum_value = 1
FileOptions_CODE_SIZE_enum_value = 2
FileOptions_LITE_RUNTIME_enum_value = 3
)
// Names for google.protobuf.MessageOptions. // Names for google.protobuf.MessageOptions.
const ( const (
MessageOptions_message_name protoreflect.Name = "MessageOptions" MessageOptions_message_name protoreflect.Name = "MessageOptions"
@ -494,26 +605,32 @@ const (
// Field names for google.protobuf.MessageOptions. // Field names for google.protobuf.MessageOptions.
const ( const (
MessageOptions_MessageSetWireFormat_field_name protoreflect.Name = "message_set_wire_format" MessageOptions_MessageSetWireFormat_field_name protoreflect.Name = "message_set_wire_format"
MessageOptions_NoStandardDescriptorAccessor_field_name protoreflect.Name = "no_standard_descriptor_accessor" MessageOptions_NoStandardDescriptorAccessor_field_name protoreflect.Name = "no_standard_descriptor_accessor"
MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated" MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated"
MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry" MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry"
MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts"
MessageOptions_Features_field_name protoreflect.Name = "features"
MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format" MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format"
MessageOptions_NoStandardDescriptorAccessor_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.no_standard_descriptor_accessor" MessageOptions_NoStandardDescriptorAccessor_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.no_standard_descriptor_accessor"
MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated" MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated"
MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry" MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry"
MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option" MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated_legacy_json_field_conflicts"
MessageOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.features"
MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option"
) )
// Field numbers for google.protobuf.MessageOptions. // Field numbers for google.protobuf.MessageOptions.
const ( const (
MessageOptions_MessageSetWireFormat_field_number protoreflect.FieldNumber = 1 MessageOptions_MessageSetWireFormat_field_number protoreflect.FieldNumber = 1
MessageOptions_NoStandardDescriptorAccessor_field_number protoreflect.FieldNumber = 2 MessageOptions_NoStandardDescriptorAccessor_field_number protoreflect.FieldNumber = 2
MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3 MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3
MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7 MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7
MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 11
MessageOptions_Features_field_number protoreflect.FieldNumber = 12
MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
// Names for google.protobuf.FieldOptions. // Names for google.protobuf.FieldOptions.
@ -528,16 +645,28 @@ const (
FieldOptions_Packed_field_name protoreflect.Name = "packed" FieldOptions_Packed_field_name protoreflect.Name = "packed"
FieldOptions_Jstype_field_name protoreflect.Name = "jstype" FieldOptions_Jstype_field_name protoreflect.Name = "jstype"
FieldOptions_Lazy_field_name protoreflect.Name = "lazy" FieldOptions_Lazy_field_name protoreflect.Name = "lazy"
FieldOptions_UnverifiedLazy_field_name protoreflect.Name = "unverified_lazy"
FieldOptions_Deprecated_field_name protoreflect.Name = "deprecated" FieldOptions_Deprecated_field_name protoreflect.Name = "deprecated"
FieldOptions_Weak_field_name protoreflect.Name = "weak" FieldOptions_Weak_field_name protoreflect.Name = "weak"
FieldOptions_DebugRedact_field_name protoreflect.Name = "debug_redact"
FieldOptions_Retention_field_name protoreflect.Name = "retention"
FieldOptions_Targets_field_name protoreflect.Name = "targets"
FieldOptions_EditionDefaults_field_name protoreflect.Name = "edition_defaults"
FieldOptions_Features_field_name protoreflect.Name = "features"
FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype" FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype"
FieldOptions_Packed_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.packed" FieldOptions_Packed_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.packed"
FieldOptions_Jstype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.jstype" FieldOptions_Jstype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.jstype"
FieldOptions_Lazy_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.lazy" FieldOptions_Lazy_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.lazy"
FieldOptions_UnverifiedLazy_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.unverified_lazy"
FieldOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.deprecated" FieldOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.deprecated"
FieldOptions_Weak_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.weak" FieldOptions_Weak_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.weak"
FieldOptions_DebugRedact_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.debug_redact"
FieldOptions_Retention_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.retention"
FieldOptions_Targets_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.targets"
FieldOptions_EditionDefaults_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.edition_defaults"
FieldOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.features"
FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option" FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option"
) )
@ -547,8 +676,14 @@ const (
FieldOptions_Packed_field_number protoreflect.FieldNumber = 2 FieldOptions_Packed_field_number protoreflect.FieldNumber = 2
FieldOptions_Jstype_field_number protoreflect.FieldNumber = 6 FieldOptions_Jstype_field_number protoreflect.FieldNumber = 6
FieldOptions_Lazy_field_number protoreflect.FieldNumber = 5 FieldOptions_Lazy_field_number protoreflect.FieldNumber = 5
FieldOptions_UnverifiedLazy_field_number protoreflect.FieldNumber = 15
FieldOptions_Deprecated_field_number protoreflect.FieldNumber = 3 FieldOptions_Deprecated_field_number protoreflect.FieldNumber = 3
FieldOptions_Weak_field_number protoreflect.FieldNumber = 10 FieldOptions_Weak_field_number protoreflect.FieldNumber = 10
FieldOptions_DebugRedact_field_number protoreflect.FieldNumber = 16
FieldOptions_Retention_field_number protoreflect.FieldNumber = 17
FieldOptions_Targets_field_number protoreflect.FieldNumber = 19
FieldOptions_EditionDefaults_field_number protoreflect.FieldNumber = 20
FieldOptions_Features_field_number protoreflect.FieldNumber = 21
FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -558,12 +693,80 @@ const (
FieldOptions_CType_enum_name = "CType" FieldOptions_CType_enum_name = "CType"
) )
// Enum values for google.protobuf.FieldOptions.CType.
const (
FieldOptions_STRING_enum_value = 0
FieldOptions_CORD_enum_value = 1
FieldOptions_STRING_PIECE_enum_value = 2
)
// Full and short names for google.protobuf.FieldOptions.JSType. // Full and short names for google.protobuf.FieldOptions.JSType.
const ( const (
FieldOptions_JSType_enum_fullname = "google.protobuf.FieldOptions.JSType" FieldOptions_JSType_enum_fullname = "google.protobuf.FieldOptions.JSType"
FieldOptions_JSType_enum_name = "JSType" FieldOptions_JSType_enum_name = "JSType"
) )
// Enum values for google.protobuf.FieldOptions.JSType.
const (
FieldOptions_JS_NORMAL_enum_value = 0
FieldOptions_JS_STRING_enum_value = 1
FieldOptions_JS_NUMBER_enum_value = 2
)
// Full and short names for google.protobuf.FieldOptions.OptionRetention.
const (
FieldOptions_OptionRetention_enum_fullname = "google.protobuf.FieldOptions.OptionRetention"
FieldOptions_OptionRetention_enum_name = "OptionRetention"
)
// Enum values for google.protobuf.FieldOptions.OptionRetention.
const (
FieldOptions_RETENTION_UNKNOWN_enum_value = 0
FieldOptions_RETENTION_RUNTIME_enum_value = 1
FieldOptions_RETENTION_SOURCE_enum_value = 2
)
// Full and short names for google.protobuf.FieldOptions.OptionTargetType.
const (
FieldOptions_OptionTargetType_enum_fullname = "google.protobuf.FieldOptions.OptionTargetType"
FieldOptions_OptionTargetType_enum_name = "OptionTargetType"
)
// Enum values for google.protobuf.FieldOptions.OptionTargetType.
const (
FieldOptions_TARGET_TYPE_UNKNOWN_enum_value = 0
FieldOptions_TARGET_TYPE_FILE_enum_value = 1
FieldOptions_TARGET_TYPE_EXTENSION_RANGE_enum_value = 2
FieldOptions_TARGET_TYPE_MESSAGE_enum_value = 3
FieldOptions_TARGET_TYPE_FIELD_enum_value = 4
FieldOptions_TARGET_TYPE_ONEOF_enum_value = 5
FieldOptions_TARGET_TYPE_ENUM_enum_value = 6
FieldOptions_TARGET_TYPE_ENUM_ENTRY_enum_value = 7
FieldOptions_TARGET_TYPE_SERVICE_enum_value = 8
FieldOptions_TARGET_TYPE_METHOD_enum_value = 9
)
// Names for google.protobuf.FieldOptions.EditionDefault.
const (
FieldOptions_EditionDefault_message_name protoreflect.Name = "EditionDefault"
FieldOptions_EditionDefault_message_fullname protoreflect.FullName = "google.protobuf.FieldOptions.EditionDefault"
)
// Field names for google.protobuf.FieldOptions.EditionDefault.
const (
FieldOptions_EditionDefault_Edition_field_name protoreflect.Name = "edition"
FieldOptions_EditionDefault_Value_field_name protoreflect.Name = "value"
FieldOptions_EditionDefault_Edition_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.EditionDefault.edition"
FieldOptions_EditionDefault_Value_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.EditionDefault.value"
)
// Field numbers for google.protobuf.FieldOptions.EditionDefault.
const (
FieldOptions_EditionDefault_Edition_field_number protoreflect.FieldNumber = 3
FieldOptions_EditionDefault_Value_field_number protoreflect.FieldNumber = 2
)
// Names for google.protobuf.OneofOptions. // Names for google.protobuf.OneofOptions.
const ( const (
OneofOptions_message_name protoreflect.Name = "OneofOptions" OneofOptions_message_name protoreflect.Name = "OneofOptions"
@ -572,13 +775,16 @@ const (
// Field names for google.protobuf.OneofOptions. // Field names for google.protobuf.OneofOptions.
const ( const (
OneofOptions_Features_field_name protoreflect.Name = "features"
OneofOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" OneofOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
OneofOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.features"
OneofOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.uninterpreted_option" OneofOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.uninterpreted_option"
) )
// Field numbers for google.protobuf.OneofOptions. // Field numbers for google.protobuf.OneofOptions.
const ( const (
OneofOptions_Features_field_number protoreflect.FieldNumber = 1
OneofOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 OneofOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -590,20 +796,26 @@ const (
// Field names for google.protobuf.EnumOptions. // Field names for google.protobuf.EnumOptions.
const ( const (
EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias" EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias"
EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated" EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated"
EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts"
EnumOptions_Features_field_name protoreflect.Name = "features"
EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias" EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias"
EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated" EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated"
EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option" EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated_legacy_json_field_conflicts"
EnumOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.features"
EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option"
) )
// Field numbers for google.protobuf.EnumOptions. // Field numbers for google.protobuf.EnumOptions.
const ( const (
EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2 EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2
EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3 EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3
EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 6
EnumOptions_Features_field_number protoreflect.FieldNumber = 7
EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
// Names for google.protobuf.EnumValueOptions. // Names for google.protobuf.EnumValueOptions.
@ -615,15 +827,21 @@ const (
// Field names for google.protobuf.EnumValueOptions. // Field names for google.protobuf.EnumValueOptions.
const ( const (
EnumValueOptions_Deprecated_field_name protoreflect.Name = "deprecated" EnumValueOptions_Deprecated_field_name protoreflect.Name = "deprecated"
EnumValueOptions_Features_field_name protoreflect.Name = "features"
EnumValueOptions_DebugRedact_field_name protoreflect.Name = "debug_redact"
EnumValueOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" EnumValueOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
EnumValueOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.deprecated" EnumValueOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.deprecated"
EnumValueOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.features"
EnumValueOptions_DebugRedact_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.debug_redact"
EnumValueOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.uninterpreted_option" EnumValueOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.uninterpreted_option"
) )
// Field numbers for google.protobuf.EnumValueOptions. // Field numbers for google.protobuf.EnumValueOptions.
const ( const (
EnumValueOptions_Deprecated_field_number protoreflect.FieldNumber = 1 EnumValueOptions_Deprecated_field_number protoreflect.FieldNumber = 1
EnumValueOptions_Features_field_number protoreflect.FieldNumber = 2
EnumValueOptions_DebugRedact_field_number protoreflect.FieldNumber = 3
EnumValueOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 EnumValueOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -635,15 +853,18 @@ const (
// Field names for google.protobuf.ServiceOptions. // Field names for google.protobuf.ServiceOptions.
const ( const (
ServiceOptions_Features_field_name protoreflect.Name = "features"
ServiceOptions_Deprecated_field_name protoreflect.Name = "deprecated" ServiceOptions_Deprecated_field_name protoreflect.Name = "deprecated"
ServiceOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ServiceOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
ServiceOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.features"
ServiceOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.deprecated" ServiceOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.deprecated"
ServiceOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.uninterpreted_option" ServiceOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.uninterpreted_option"
) )
// Field numbers for google.protobuf.ServiceOptions. // Field numbers for google.protobuf.ServiceOptions.
const ( const (
ServiceOptions_Features_field_number protoreflect.FieldNumber = 34
ServiceOptions_Deprecated_field_number protoreflect.FieldNumber = 33 ServiceOptions_Deprecated_field_number protoreflect.FieldNumber = 33
ServiceOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ServiceOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -658,10 +879,12 @@ const (
const ( const (
MethodOptions_Deprecated_field_name protoreflect.Name = "deprecated" MethodOptions_Deprecated_field_name protoreflect.Name = "deprecated"
MethodOptions_IdempotencyLevel_field_name protoreflect.Name = "idempotency_level" MethodOptions_IdempotencyLevel_field_name protoreflect.Name = "idempotency_level"
MethodOptions_Features_field_name protoreflect.Name = "features"
MethodOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" MethodOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
MethodOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.deprecated" MethodOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.deprecated"
MethodOptions_IdempotencyLevel_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.idempotency_level" MethodOptions_IdempotencyLevel_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.idempotency_level"
MethodOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.features"
MethodOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.uninterpreted_option" MethodOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.uninterpreted_option"
) )
@ -669,6 +892,7 @@ const (
const ( const (
MethodOptions_Deprecated_field_number protoreflect.FieldNumber = 33 MethodOptions_Deprecated_field_number protoreflect.FieldNumber = 33
MethodOptions_IdempotencyLevel_field_number protoreflect.FieldNumber = 34 MethodOptions_IdempotencyLevel_field_number protoreflect.FieldNumber = 34
MethodOptions_Features_field_number protoreflect.FieldNumber = 35
MethodOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 MethodOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
) )
@ -678,6 +902,13 @@ const (
MethodOptions_IdempotencyLevel_enum_name = "IdempotencyLevel" MethodOptions_IdempotencyLevel_enum_name = "IdempotencyLevel"
) )
// Enum values for google.protobuf.MethodOptions.IdempotencyLevel.
const (
MethodOptions_IDEMPOTENCY_UNKNOWN_enum_value = 0
MethodOptions_NO_SIDE_EFFECTS_enum_value = 1
MethodOptions_IDEMPOTENT_enum_value = 2
)
// Names for google.protobuf.UninterpretedOption. // Names for google.protobuf.UninterpretedOption.
const ( const (
UninterpretedOption_message_name protoreflect.Name = "UninterpretedOption" UninterpretedOption_message_name protoreflect.Name = "UninterpretedOption"
@ -735,6 +966,163 @@ const (
UninterpretedOption_NamePart_IsExtension_field_number protoreflect.FieldNumber = 2 UninterpretedOption_NamePart_IsExtension_field_number protoreflect.FieldNumber = 2
) )
// Names for google.protobuf.FeatureSet.
const (
FeatureSet_message_name protoreflect.Name = "FeatureSet"
FeatureSet_message_fullname protoreflect.FullName = "google.protobuf.FeatureSet"
)
// Field names for google.protobuf.FeatureSet.
const (
FeatureSet_FieldPresence_field_name protoreflect.Name = "field_presence"
FeatureSet_EnumType_field_name protoreflect.Name = "enum_type"
FeatureSet_RepeatedFieldEncoding_field_name protoreflect.Name = "repeated_field_encoding"
FeatureSet_Utf8Validation_field_name protoreflect.Name = "utf8_validation"
FeatureSet_MessageEncoding_field_name protoreflect.Name = "message_encoding"
FeatureSet_JsonFormat_field_name protoreflect.Name = "json_format"
FeatureSet_FieldPresence_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
FeatureSet_EnumType_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
FeatureSet_RepeatedFieldEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
FeatureSet_Utf8Validation_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
FeatureSet_MessageEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
FeatureSet_JsonFormat_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
)
// Field numbers for google.protobuf.FeatureSet.
const (
FeatureSet_FieldPresence_field_number protoreflect.FieldNumber = 1
FeatureSet_EnumType_field_number protoreflect.FieldNumber = 2
FeatureSet_RepeatedFieldEncoding_field_number protoreflect.FieldNumber = 3
FeatureSet_Utf8Validation_field_number protoreflect.FieldNumber = 4
FeatureSet_MessageEncoding_field_number protoreflect.FieldNumber = 5
FeatureSet_JsonFormat_field_number protoreflect.FieldNumber = 6
)
// Full and short names for google.protobuf.FeatureSet.FieldPresence.
const (
FeatureSet_FieldPresence_enum_fullname = "google.protobuf.FeatureSet.FieldPresence"
FeatureSet_FieldPresence_enum_name = "FieldPresence"
)
// Enum values for google.protobuf.FeatureSet.FieldPresence.
const (
FeatureSet_FIELD_PRESENCE_UNKNOWN_enum_value = 0
FeatureSet_EXPLICIT_enum_value = 1
FeatureSet_IMPLICIT_enum_value = 2
FeatureSet_LEGACY_REQUIRED_enum_value = 3
)
// Full and short names for google.protobuf.FeatureSet.EnumType.
const (
FeatureSet_EnumType_enum_fullname = "google.protobuf.FeatureSet.EnumType"
FeatureSet_EnumType_enum_name = "EnumType"
)
// Enum values for google.protobuf.FeatureSet.EnumType.
const (
FeatureSet_ENUM_TYPE_UNKNOWN_enum_value = 0
FeatureSet_OPEN_enum_value = 1
FeatureSet_CLOSED_enum_value = 2
)
// Full and short names for google.protobuf.FeatureSet.RepeatedFieldEncoding.
const (
FeatureSet_RepeatedFieldEncoding_enum_fullname = "google.protobuf.FeatureSet.RepeatedFieldEncoding"
FeatureSet_RepeatedFieldEncoding_enum_name = "RepeatedFieldEncoding"
)
// Enum values for google.protobuf.FeatureSet.RepeatedFieldEncoding.
const (
FeatureSet_REPEATED_FIELD_ENCODING_UNKNOWN_enum_value = 0
FeatureSet_PACKED_enum_value = 1
FeatureSet_EXPANDED_enum_value = 2
)
// Full and short names for google.protobuf.FeatureSet.Utf8Validation.
const (
FeatureSet_Utf8Validation_enum_fullname = "google.protobuf.FeatureSet.Utf8Validation"
FeatureSet_Utf8Validation_enum_name = "Utf8Validation"
)
// Enum values for google.protobuf.FeatureSet.Utf8Validation.
const (
FeatureSet_UTF8_VALIDATION_UNKNOWN_enum_value = 0
FeatureSet_VERIFY_enum_value = 2
FeatureSet_NONE_enum_value = 3
)
// Full and short names for google.protobuf.FeatureSet.MessageEncoding.
const (
FeatureSet_MessageEncoding_enum_fullname = "google.protobuf.FeatureSet.MessageEncoding"
FeatureSet_MessageEncoding_enum_name = "MessageEncoding"
)
// Enum values for google.protobuf.FeatureSet.MessageEncoding.
const (
FeatureSet_MESSAGE_ENCODING_UNKNOWN_enum_value = 0
FeatureSet_LENGTH_PREFIXED_enum_value = 1
FeatureSet_DELIMITED_enum_value = 2
)
// Full and short names for google.protobuf.FeatureSet.JsonFormat.
const (
FeatureSet_JsonFormat_enum_fullname = "google.protobuf.FeatureSet.JsonFormat"
FeatureSet_JsonFormat_enum_name = "JsonFormat"
)
// Enum values for google.protobuf.FeatureSet.JsonFormat.
const (
FeatureSet_JSON_FORMAT_UNKNOWN_enum_value = 0
FeatureSet_ALLOW_enum_value = 1
FeatureSet_LEGACY_BEST_EFFORT_enum_value = 2
)
// Names for google.protobuf.FeatureSetDefaults.
const (
FeatureSetDefaults_message_name protoreflect.Name = "FeatureSetDefaults"
FeatureSetDefaults_message_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults"
)
// Field names for google.protobuf.FeatureSetDefaults.
const (
FeatureSetDefaults_Defaults_field_name protoreflect.Name = "defaults"
FeatureSetDefaults_MinimumEdition_field_name protoreflect.Name = "minimum_edition"
FeatureSetDefaults_MaximumEdition_field_name protoreflect.Name = "maximum_edition"
FeatureSetDefaults_Defaults_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.defaults"
FeatureSetDefaults_MinimumEdition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.minimum_edition"
FeatureSetDefaults_MaximumEdition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.maximum_edition"
)
// Field numbers for google.protobuf.FeatureSetDefaults.
const (
FeatureSetDefaults_Defaults_field_number protoreflect.FieldNumber = 1
FeatureSetDefaults_MinimumEdition_field_number protoreflect.FieldNumber = 4
FeatureSetDefaults_MaximumEdition_field_number protoreflect.FieldNumber = 5
)
// Names for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.
const (
FeatureSetDefaults_FeatureSetEditionDefault_message_name protoreflect.Name = "FeatureSetEditionDefault"
FeatureSetDefaults_FeatureSetEditionDefault_message_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault"
)
// Field names for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.
const (
FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_name protoreflect.Name = "edition"
FeatureSetDefaults_FeatureSetEditionDefault_Features_field_name protoreflect.Name = "features"
FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition"
FeatureSetDefaults_FeatureSetEditionDefault_Features_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.features"
)
// Field numbers for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.
const (
FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number protoreflect.FieldNumber = 3
FeatureSetDefaults_FeatureSetEditionDefault_Features_field_number protoreflect.FieldNumber = 2
)
// Names for google.protobuf.SourceCodeInfo. // Names for google.protobuf.SourceCodeInfo.
const ( const (
SourceCodeInfo_message_name protoreflect.Name = "SourceCodeInfo" SourceCodeInfo_message_name protoreflect.Name = "SourceCodeInfo"
@ -813,11 +1201,13 @@ const (
GeneratedCodeInfo_Annotation_SourceFile_field_name protoreflect.Name = "source_file" GeneratedCodeInfo_Annotation_SourceFile_field_name protoreflect.Name = "source_file"
GeneratedCodeInfo_Annotation_Begin_field_name protoreflect.Name = "begin" GeneratedCodeInfo_Annotation_Begin_field_name protoreflect.Name = "begin"
GeneratedCodeInfo_Annotation_End_field_name protoreflect.Name = "end" GeneratedCodeInfo_Annotation_End_field_name protoreflect.Name = "end"
GeneratedCodeInfo_Annotation_Semantic_field_name protoreflect.Name = "semantic"
GeneratedCodeInfo_Annotation_Path_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.path" GeneratedCodeInfo_Annotation_Path_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.path"
GeneratedCodeInfo_Annotation_SourceFile_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.source_file" GeneratedCodeInfo_Annotation_SourceFile_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.source_file"
GeneratedCodeInfo_Annotation_Begin_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.begin" GeneratedCodeInfo_Annotation_Begin_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.begin"
GeneratedCodeInfo_Annotation_End_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.end" GeneratedCodeInfo_Annotation_End_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.end"
GeneratedCodeInfo_Annotation_Semantic_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.semantic"
) )
// Field numbers for google.protobuf.GeneratedCodeInfo.Annotation. // Field numbers for google.protobuf.GeneratedCodeInfo.Annotation.
@ -826,4 +1216,18 @@ const (
GeneratedCodeInfo_Annotation_SourceFile_field_number protoreflect.FieldNumber = 2 GeneratedCodeInfo_Annotation_SourceFile_field_number protoreflect.FieldNumber = 2
GeneratedCodeInfo_Annotation_Begin_field_number protoreflect.FieldNumber = 3 GeneratedCodeInfo_Annotation_Begin_field_number protoreflect.FieldNumber = 3
GeneratedCodeInfo_Annotation_End_field_number protoreflect.FieldNumber = 4 GeneratedCodeInfo_Annotation_End_field_number protoreflect.FieldNumber = 4
GeneratedCodeInfo_Annotation_Semantic_field_number protoreflect.FieldNumber = 5
)
// Full and short names for google.protobuf.GeneratedCodeInfo.Annotation.Semantic.
const (
GeneratedCodeInfo_Annotation_Semantic_enum_fullname = "google.protobuf.GeneratedCodeInfo.Annotation.Semantic"
GeneratedCodeInfo_Annotation_Semantic_enum_name = "Semantic"
)
// Enum values for google.protobuf.GeneratedCodeInfo.Annotation.Semantic.
const (
GeneratedCodeInfo_Annotation_NONE_enum_value = 0
GeneratedCodeInfo_Annotation_SET_enum_value = 1
GeneratedCodeInfo_Annotation_ALIAS_enum_value = 2
) )

View File

@ -0,0 +1,31 @@
// 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.
// Code generated by generate-protos. DO NOT EDIT.
package genid
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
)
const File_reflect_protodesc_proto_go_features_proto = "reflect/protodesc/proto/go_features.proto"
// Names for google.protobuf.GoFeatures.
const (
GoFeatures_message_name protoreflect.Name = "GoFeatures"
GoFeatures_message_fullname protoreflect.FullName = "google.protobuf.GoFeatures"
)
// Field names for google.protobuf.GoFeatures.
const (
GoFeatures_LegacyUnmarshalJsonEnum_field_name protoreflect.Name = "legacy_unmarshal_json_enum"
GoFeatures_LegacyUnmarshalJsonEnum_field_fullname protoreflect.FullName = "google.protobuf.GoFeatures.legacy_unmarshal_json_enum"
)
// Field numbers for google.protobuf.GoFeatures.
const (
GoFeatures_LegacyUnmarshalJsonEnum_field_number protoreflect.FieldNumber = 1
)

View File

@ -18,6 +18,11 @@ const (
NullValue_enum_name = "NullValue" NullValue_enum_name = "NullValue"
) )
// Enum values for google.protobuf.NullValue.
const (
NullValue_NULL_VALUE_enum_value = 0
)
// Names for google.protobuf.Struct. // Names for google.protobuf.Struct.
const ( const (
Struct_message_name protoreflect.Name = "Struct" Struct_message_name protoreflect.Name = "Struct"

View File

@ -18,6 +18,13 @@ const (
Syntax_enum_name = "Syntax" Syntax_enum_name = "Syntax"
) )
// Enum values for google.protobuf.Syntax.
const (
Syntax_SYNTAX_PROTO2_enum_value = 0
Syntax_SYNTAX_PROTO3_enum_value = 1
Syntax_SYNTAX_EDITIONS_enum_value = 2
)
// Names for google.protobuf.Type. // Names for google.protobuf.Type.
const ( const (
Type_message_name protoreflect.Name = "Type" Type_message_name protoreflect.Name = "Type"
@ -32,6 +39,7 @@ const (
Type_Options_field_name protoreflect.Name = "options" Type_Options_field_name protoreflect.Name = "options"
Type_SourceContext_field_name protoreflect.Name = "source_context" Type_SourceContext_field_name protoreflect.Name = "source_context"
Type_Syntax_field_name protoreflect.Name = "syntax" Type_Syntax_field_name protoreflect.Name = "syntax"
Type_Edition_field_name protoreflect.Name = "edition"
Type_Name_field_fullname protoreflect.FullName = "google.protobuf.Type.name" Type_Name_field_fullname protoreflect.FullName = "google.protobuf.Type.name"
Type_Fields_field_fullname protoreflect.FullName = "google.protobuf.Type.fields" Type_Fields_field_fullname protoreflect.FullName = "google.protobuf.Type.fields"
@ -39,6 +47,7 @@ const (
Type_Options_field_fullname protoreflect.FullName = "google.protobuf.Type.options" Type_Options_field_fullname protoreflect.FullName = "google.protobuf.Type.options"
Type_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Type.source_context" Type_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Type.source_context"
Type_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Type.syntax" Type_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Type.syntax"
Type_Edition_field_fullname protoreflect.FullName = "google.protobuf.Type.edition"
) )
// Field numbers for google.protobuf.Type. // Field numbers for google.protobuf.Type.
@ -49,6 +58,7 @@ const (
Type_Options_field_number protoreflect.FieldNumber = 4 Type_Options_field_number protoreflect.FieldNumber = 4
Type_SourceContext_field_number protoreflect.FieldNumber = 5 Type_SourceContext_field_number protoreflect.FieldNumber = 5
Type_Syntax_field_number protoreflect.FieldNumber = 6 Type_Syntax_field_number protoreflect.FieldNumber = 6
Type_Edition_field_number protoreflect.FieldNumber = 7
) )
// Names for google.protobuf.Field. // Names for google.protobuf.Field.
@ -102,12 +112,43 @@ const (
Field_Kind_enum_name = "Kind" Field_Kind_enum_name = "Kind"
) )
// Enum values for google.protobuf.Field.Kind.
const (
Field_TYPE_UNKNOWN_enum_value = 0
Field_TYPE_DOUBLE_enum_value = 1
Field_TYPE_FLOAT_enum_value = 2
Field_TYPE_INT64_enum_value = 3
Field_TYPE_UINT64_enum_value = 4
Field_TYPE_INT32_enum_value = 5
Field_TYPE_FIXED64_enum_value = 6
Field_TYPE_FIXED32_enum_value = 7
Field_TYPE_BOOL_enum_value = 8
Field_TYPE_STRING_enum_value = 9
Field_TYPE_GROUP_enum_value = 10
Field_TYPE_MESSAGE_enum_value = 11
Field_TYPE_BYTES_enum_value = 12
Field_TYPE_UINT32_enum_value = 13
Field_TYPE_ENUM_enum_value = 14
Field_TYPE_SFIXED32_enum_value = 15
Field_TYPE_SFIXED64_enum_value = 16
Field_TYPE_SINT32_enum_value = 17
Field_TYPE_SINT64_enum_value = 18
)
// Full and short names for google.protobuf.Field.Cardinality. // Full and short names for google.protobuf.Field.Cardinality.
const ( const (
Field_Cardinality_enum_fullname = "google.protobuf.Field.Cardinality" Field_Cardinality_enum_fullname = "google.protobuf.Field.Cardinality"
Field_Cardinality_enum_name = "Cardinality" Field_Cardinality_enum_name = "Cardinality"
) )
// Enum values for google.protobuf.Field.Cardinality.
const (
Field_CARDINALITY_UNKNOWN_enum_value = 0
Field_CARDINALITY_OPTIONAL_enum_value = 1
Field_CARDINALITY_REQUIRED_enum_value = 2
Field_CARDINALITY_REPEATED_enum_value = 3
)
// Names for google.protobuf.Enum. // Names for google.protobuf.Enum.
const ( const (
Enum_message_name protoreflect.Name = "Enum" Enum_message_name protoreflect.Name = "Enum"
@ -121,12 +162,14 @@ const (
Enum_Options_field_name protoreflect.Name = "options" Enum_Options_field_name protoreflect.Name = "options"
Enum_SourceContext_field_name protoreflect.Name = "source_context" Enum_SourceContext_field_name protoreflect.Name = "source_context"
Enum_Syntax_field_name protoreflect.Name = "syntax" Enum_Syntax_field_name protoreflect.Name = "syntax"
Enum_Edition_field_name protoreflect.Name = "edition"
Enum_Name_field_fullname protoreflect.FullName = "google.protobuf.Enum.name" Enum_Name_field_fullname protoreflect.FullName = "google.protobuf.Enum.name"
Enum_Enumvalue_field_fullname protoreflect.FullName = "google.protobuf.Enum.enumvalue" Enum_Enumvalue_field_fullname protoreflect.FullName = "google.protobuf.Enum.enumvalue"
Enum_Options_field_fullname protoreflect.FullName = "google.protobuf.Enum.options" Enum_Options_field_fullname protoreflect.FullName = "google.protobuf.Enum.options"
Enum_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Enum.source_context" Enum_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Enum.source_context"
Enum_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Enum.syntax" Enum_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Enum.syntax"
Enum_Edition_field_fullname protoreflect.FullName = "google.protobuf.Enum.edition"
) )
// Field numbers for google.protobuf.Enum. // Field numbers for google.protobuf.Enum.
@ -136,6 +179,7 @@ const (
Enum_Options_field_number protoreflect.FieldNumber = 3 Enum_Options_field_number protoreflect.FieldNumber = 3
Enum_SourceContext_field_number protoreflect.FieldNumber = 4 Enum_SourceContext_field_number protoreflect.FieldNumber = 4
Enum_Syntax_field_number protoreflect.FieldNumber = 5 Enum_Syntax_field_number protoreflect.FieldNumber = 5
Enum_Edition_field_number protoreflect.FieldNumber = 6
) )
// Names for google.protobuf.EnumValue. // Names for google.protobuf.EnumValue.

View File

@ -21,26 +21,18 @@ type extensionFieldInfo struct {
validation validationInfo validation validationInfo
} }
var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo
func getExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo { func getExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo {
if xi, ok := xt.(*ExtensionInfo); ok { if xi, ok := xt.(*ExtensionInfo); ok {
xi.lazyInit() xi.lazyInit()
return xi.info return xi.info
} }
return legacyLoadExtensionFieldInfo(xt) // Ideally we'd cache the resulting *extensionFieldInfo so we don't have to
} // recompute this metadata repeatedly. But without support for something like
// weak references, such a cache would pin temporary values (like dynamic
// legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt. // extension types, constructed for the duration of a user request) to the
func legacyLoadExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo { // heap forever, causing memory usage of the cache to grow unbounded.
if xi, ok := legacyExtensionFieldInfoCache.Load(xt); ok { // See discussion in https://github.com/golang/protobuf/issues/1521.
return xi.(*extensionFieldInfo) return makeExtensionFieldInfo(xt.TypeDescriptor())
}
e := makeExtensionFieldInfo(xt.TypeDescriptor())
if e, ok := legacyMessageTypeCache.LoadOrStore(xt, e); ok {
return e.(*extensionFieldInfo)
}
return e
} }
func makeExtensionFieldInfo(xd protoreflect.ExtensionDescriptor) *extensionFieldInfo { func makeExtensionFieldInfo(xd protoreflect.ExtensionDescriptor) *extensionFieldInfo {

View File

@ -162,11 +162,20 @@ func appendBoolSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions
func consumeBoolSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeBoolSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.BoolSlice() sp := p.BoolSlice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growBoolSlice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -732,11 +741,20 @@ func appendInt32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOption
func consumeInt32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeInt32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int32Slice() sp := p.Int32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growInt32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -1138,11 +1156,20 @@ func appendSint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeSint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeSint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int32Slice() sp := p.Int32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growInt32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -1544,11 +1571,20 @@ func appendUint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeUint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeUint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint32Slice() sp := p.Uint32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growUint32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -1950,11 +1986,20 @@ func appendInt64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOption
func consumeInt64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeInt64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int64Slice() sp := p.Int64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growInt64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -2356,11 +2401,20 @@ func appendSint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeSint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeSint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int64Slice() sp := p.Int64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growInt64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -2762,11 +2816,20 @@ func appendUint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeUint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeUint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint64Slice() sp := p.Uint64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := 0
for _, v := range b {
if v < 0x80 {
count++
}
}
if count > 0 {
p.growUint64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
var v uint64 var v uint64
var n int var n int
@ -3145,11 +3208,15 @@ func appendSfixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpt
func consumeSfixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeSfixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int32Slice() sp := p.Int32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed32()
if count > 0 {
p.growInt32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
@ -3461,11 +3528,15 @@ func appendFixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpti
func consumeFixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeFixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint32Slice() sp := p.Uint32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed32()
if count > 0 {
p.growUint32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
@ -3777,11 +3848,15 @@ func appendFloatSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOption
func consumeFloatSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeFloatSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Float32Slice() sp := p.Float32Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed32()
if count > 0 {
p.growFloat32Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed32(b) v, n := protowire.ConsumeFixed32(b)
if n < 0 { if n < 0 {
@ -4093,11 +4168,15 @@ func appendSfixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpt
func consumeSfixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeSfixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int64Slice() sp := p.Int64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed64()
if count > 0 {
p.growInt64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
@ -4409,11 +4488,15 @@ func appendFixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpti
func consumeFixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeFixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint64Slice() sp := p.Uint64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed64()
if count > 0 {
p.growUint64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {
@ -4725,11 +4808,15 @@ func appendDoubleSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeDoubleSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { func consumeDoubleSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Float64Slice() sp := p.Float64Slice()
if wtyp == protowire.BytesType { if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b) b, n := protowire.ConsumeBytes(b)
if n < 0 { if n < 0 {
return out, errDecode return out, errDecode
} }
count := len(b) / protowire.SizeFixed64()
if count > 0 {
p.growFloat64Slice(count)
}
s := *sp
for len(b) > 0 { for len(b) > 0 {
v, n := protowire.ConsumeFixed64(b) v, n := protowire.ConsumeFixed64(b)
if n < 0 { if n < 0 {

View File

@ -197,7 +197,7 @@ func fieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) (*MessageInfo,
return getMessageInfo(ft), makeMessageFieldCoder(fd, ft) return getMessageInfo(ft), makeMessageFieldCoder(fd, ft)
case fd.Kind() == protoreflect.GroupKind: case fd.Kind() == protoreflect.GroupKind:
return getMessageInfo(ft), makeGroupFieldCoder(fd, ft) return getMessageInfo(ft), makeGroupFieldCoder(fd, ft)
case fd.Syntax() == protoreflect.Proto3 && fd.ContainingOneof() == nil: case !fd.HasPresence() && fd.ContainingOneof() == nil:
// Populated oneof fields always encode even if set to the zero value, // Populated oneof fields always encode even if set to the zero value,
// which normally are not encoded in proto3. // which normally are not encoded in proto3.
switch fd.Kind() { switch fd.Kind() {

View File

@ -59,7 +59,6 @@ func NewConverter(t reflect.Type, fd protoreflect.FieldDescriptor) Converter {
default: default:
return newSingularConverter(t, fd) return newSingularConverter(t, fd)
} }
panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName()))
} }
var ( var (

View File

@ -206,13 +206,18 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName
// Obtain a list of oneof wrapper types. // Obtain a list of oneof wrapper types.
var oneofWrappers []reflect.Type var oneofWrappers []reflect.Type
for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { methods := make([]reflect.Method, 0, 2)
if fn, ok := t.MethodByName(method); ok { if m, ok := t.MethodByName("XXX_OneofFuncs"); ok {
for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { methods = append(methods, m)
if vs, ok := v.Interface().([]interface{}); ok { }
for _, v := range vs { if m, ok := t.MethodByName("XXX_OneofWrappers"); ok {
oneofWrappers = append(oneofWrappers, reflect.TypeOf(v)) methods = append(methods, m)
} }
for _, fn := range methods {
for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
if vs, ok := v.Interface().([]interface{}); ok {
for _, v := range vs {
oneofWrappers = append(oneofWrappers, reflect.TypeOf(v))
} }
} }
} }

View File

@ -192,12 +192,17 @@ fieldLoop:
// Derive a mapping of oneof wrappers to fields. // Derive a mapping of oneof wrappers to fields.
oneofWrappers := mi.OneofWrappers oneofWrappers := mi.OneofWrappers
for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { methods := make([]reflect.Method, 0, 2)
if fn, ok := reflect.PtrTo(t).MethodByName(method); ok { if m, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { methods = append(methods, m)
if vs, ok := v.Interface().([]interface{}); ok { }
oneofWrappers = vs if m, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
} methods = append(methods, m)
}
for _, fn := range methods {
for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
if vs, ok := v.Interface().([]interface{}); ok {
oneofWrappers = vs
} }
} }
} }

View File

@ -538,6 +538,6 @@ func isZero(v reflect.Value) bool {
} }
return true return true
default: default:
panic(&reflect.ValueError{"reflect.Value.IsZero", v.Kind()}) panic(&reflect.ValueError{Method: "reflect.Value.IsZero", Kind: v.Kind()})
} }
} }

View File

@ -159,6 +159,42 @@ func (p pointer) SetPointer(v pointer) {
p.v.Elem().Set(v.v) p.v.Elem().Set(v.v)
} }
func growSlice(p pointer, addCap int) {
// TODO: Once we only support Go 1.20 and newer, use reflect.Grow.
in := p.v.Elem()
out := reflect.MakeSlice(in.Type(), in.Len(), in.Len()+addCap)
reflect.Copy(out, in)
p.v.Elem().Set(out)
}
func (p pointer) growBoolSlice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growInt32Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growUint32Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growInt64Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growUint64Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growFloat64Slice(addCap int) {
growSlice(p, addCap)
}
func (p pointer) growFloat32Slice(addCap int) {
growSlice(p, addCap)
}
func (Export) MessageStateOf(p Pointer) *messageState { panic("not supported") } func (Export) MessageStateOf(p Pointer) *messageState { panic("not supported") }
func (ms *messageState) pointer() pointer { panic("not supported") } func (ms *messageState) pointer() pointer { panic("not supported") }
func (ms *messageState) messageInfo() *MessageInfo { panic("not supported") } func (ms *messageState) messageInfo() *MessageInfo { panic("not supported") }

View File

@ -138,6 +138,46 @@ func (p pointer) SetPointer(v pointer) {
*(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p) *(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p)
} }
func (p pointer) growBoolSlice(addCap int) {
sp := p.BoolSlice()
s := make([]bool, 0, addCap+len(*sp))
s = s[:len(*sp)]
copy(s, *sp)
*sp = s
}
func (p pointer) growInt32Slice(addCap int) {
sp := p.Int32Slice()
s := make([]int32, 0, addCap+len(*sp))
s = s[:len(*sp)]
copy(s, *sp)
*sp = s
}
func (p pointer) growUint32Slice(addCap int) {
p.growInt32Slice(addCap)
}
func (p pointer) growFloat32Slice(addCap int) {
p.growInt32Slice(addCap)
}
func (p pointer) growInt64Slice(addCap int) {
sp := p.Int64Slice()
s := make([]int64, 0, addCap+len(*sp))
s = s[:len(*sp)]
copy(s, *sp)
*sp = s
}
func (p pointer) growUint64Slice(addCap int) {
p.growInt64Slice(addCap)
}
func (p pointer) growFloat64Slice(addCap int) {
p.growInt64Slice(addCap)
}
// Static check that MessageState does not exceed the size of a pointer. // Static check that MessageState does not exceed the size of a pointer.
const _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{})) const _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{}))

View File

@ -33,7 +33,7 @@ var (
return !inOneof(ox) && inOneof(oy) return !inOneof(ox) && inOneof(oy)
} }
// Fields in disjoint oneof sets are sorted by declaration index. // Fields in disjoint oneof sets are sorted by declaration index.
if ox != nil && oy != nil && ox != oy { if inOneof(ox) && inOneof(oy) && ox != oy {
return ox.Index() < oy.Index() return ox.Index() < oy.Index()
} }
// Fields sorted by field number. // Fields sorted by field number.

View File

@ -17,7 +17,7 @@ import (
// EnforceUTF8 reports whether to enforce strict UTF-8 validation. // EnforceUTF8 reports whether to enforce strict UTF-8 validation.
func EnforceUTF8(fd protoreflect.FieldDescriptor) bool { func EnforceUTF8(fd protoreflect.FieldDescriptor) bool {
if flags.ProtoLegacy { if flags.ProtoLegacy || fd.Syntax() == protoreflect.Editions {
if fd, ok := fd.(interface{ EnforceUTF8() bool }); ok { if fd, ok := fd.(interface{ EnforceUTF8() bool }); ok {
return fd.EnforceUTF8() return fd.EnforceUTF8()
} }

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !purego && !appengine //go:build !purego && !appengine && !go1.21
// +build !purego,!appengine // +build !purego,!appengine,!go1.21
package strs package strs
@ -87,7 +87,7 @@ func (sb *Builder) grow(n int) {
// Unlike strings.Builder, we do not need to copy over the contents // Unlike strings.Builder, we do not need to copy over the contents
// of the old buffer since our builder provides no API for // of the old buffer since our builder provides no API for
// retrieving previously created strings. // retrieving previously created strings.
sb.buf = make([]byte, 2*(cap(sb.buf)+n)) sb.buf = make([]byte, 0, 2*(cap(sb.buf)+n))
} }
func (sb *Builder) last(n int) string { func (sb *Builder) last(n int) string {

View File

@ -0,0 +1,74 @@
// Copyright 2018 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.
//go:build !purego && !appengine && go1.21
// +build !purego,!appengine,go1.21
package strs
import (
"unsafe"
"google.golang.org/protobuf/reflect/protoreflect"
)
// UnsafeString returns an unsafe string reference of b.
// The caller must treat the input slice as immutable.
//
// WARNING: Use carefully. The returned result must not leak to the end user
// unless the input slice is provably immutable.
func UnsafeString(b []byte) string {
return unsafe.String(unsafe.SliceData(b), len(b))
}
// UnsafeBytes returns an unsafe bytes slice reference of s.
// The caller must treat returned slice as immutable.
//
// WARNING: Use carefully. The returned result must not leak to the end user.
func UnsafeBytes(s string) []byte {
return unsafe.Slice(unsafe.StringData(s), len(s))
}
// Builder builds a set of strings with shared lifetime.
// This differs from strings.Builder, which is for building a single string.
type Builder struct {
buf []byte
}
// AppendFullName is equivalent to protoreflect.FullName.Append,
// but optimized for large batches where each name has a shared lifetime.
func (sb *Builder) AppendFullName(prefix protoreflect.FullName, name protoreflect.Name) protoreflect.FullName {
n := len(prefix) + len(".") + len(name)
if len(prefix) == 0 {
n -= len(".")
}
sb.grow(n)
sb.buf = append(sb.buf, prefix...)
sb.buf = append(sb.buf, '.')
sb.buf = append(sb.buf, name...)
return protoreflect.FullName(sb.last(n))
}
// MakeString is equivalent to string(b), but optimized for large batches
// with a shared lifetime.
func (sb *Builder) MakeString(b []byte) string {
sb.grow(len(b))
sb.buf = append(sb.buf, b...)
return sb.last(len(b))
}
func (sb *Builder) grow(n int) {
if cap(sb.buf)-len(sb.buf) >= n {
return
}
// Unlike strings.Builder, we do not need to copy over the contents
// of the old buffer since our builder provides no API for
// retrieving previously created strings.
sb.buf = make([]byte, 0, 2*(cap(sb.buf)+n))
}
func (sb *Builder) last(n int) string {
return UnsafeString(sb.buf[len(sb.buf)-n:])
}

View File

@ -51,8 +51,8 @@ import (
// 10. Send out the CL for review and submit it. // 10. Send out the CL for review and submit it.
const ( const (
Major = 1 Major = 1
Minor = 28 Minor = 33
Patch = 1 Patch = 0
PreRelease = "" PreRelease = ""
) )

View File

@ -69,7 +69,7 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
// UnmarshalState parses a wire-format message and places the result in m. // UnmarshalState parses a wire-format message and places the result in m.
// //
// This method permits fine-grained control over the unmarshaler. // This method permits fine-grained control over the unmarshaler.
// Most users should use Unmarshal instead. // Most users should use [Unmarshal] instead.
func (o UnmarshalOptions) UnmarshalState(in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { func (o UnmarshalOptions) UnmarshalState(in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) {
if o.RecursionLimit == 0 { if o.RecursionLimit == 0 {
o.RecursionLimit = protowire.DefaultRecursionLimit o.RecursionLimit = protowire.DefaultRecursionLimit

View File

@ -5,43 +5,40 @@
// Package proto provides functions operating on protocol buffer messages. // Package proto provides functions operating on protocol buffer messages.
// //
// For documentation on protocol buffers in general, see: // For documentation on protocol buffers in general, see:
// // https://protobuf.dev.
// https://developers.google.com/protocol-buffers
// //
// For a tutorial on using protocol buffers with Go, see: // For a tutorial on using protocol buffers with Go, see:
// // https://protobuf.dev/getting-started/gotutorial.
// https://developers.google.com/protocol-buffers/docs/gotutorial
// //
// For a guide to generated Go protocol buffer code, see: // For a guide to generated Go protocol buffer code, see:
// // https://protobuf.dev/reference/go/go-generated.
// https://developers.google.com/protocol-buffers/docs/reference/go-generated
// //
// # Binary serialization // # Binary serialization
// //
// This package contains functions to convert to and from the wire format, // This package contains functions to convert to and from the wire format,
// an efficient binary serialization of protocol buffers. // an efficient binary serialization of protocol buffers.
// //
// • Size reports the size of a message in the wire format. // - [Size] reports the size of a message in the wire format.
// //
// • Marshal converts a message to the wire format. // - [Marshal] converts a message to the wire format.
// The MarshalOptions type provides more control over wire marshaling. // The [MarshalOptions] type provides more control over wire marshaling.
// //
// • Unmarshal converts a message from the wire format. // - [Unmarshal] converts a message from the wire format.
// The UnmarshalOptions type provides more control over wire unmarshaling. // The [UnmarshalOptions] type provides more control over wire unmarshaling.
// //
// # Basic message operations // # Basic message operations
// //
// • Clone makes a deep copy of a message. // - [Clone] makes a deep copy of a message.
// //
// • Merge merges the content of a message into another. // - [Merge] merges the content of a message into another.
// //
// • Equal compares two messages. For more control over comparisons // - [Equal] compares two messages. For more control over comparisons
// and detailed reporting of differences, see package // and detailed reporting of differences, see package
// "google.golang.org/protobuf/testing/protocmp". // [google.golang.org/protobuf/testing/protocmp].
// //
// • Reset clears the content of a message. // - [Reset] clears the content of a message.
// //
// • CheckInitialized reports whether all required fields in a message are set. // - [CheckInitialized] reports whether all required fields in a message are set.
// //
// # Optional scalar constructors // # Optional scalar constructors
// //
@ -49,9 +46,9 @@
// as pointers to a value. For example, an optional string field has the // as pointers to a value. For example, an optional string field has the
// Go type *string. // Go type *string.
// //
// • Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, and String // - [Bool], [Int32], [Int64], [Uint32], [Uint64], [Float32], [Float64], and [String]
// take a value and return a pointer to a new instance of it, // take a value and return a pointer to a new instance of it,
// to simplify construction of optional field values. // to simplify construction of optional field values.
// //
// Generated enum types usually have an Enum method which performs the // Generated enum types usually have an Enum method which performs the
// same operation. // same operation.
@ -60,29 +57,29 @@
// //
// # Extension accessors // # Extension accessors
// //
// • HasExtension, GetExtension, SetExtension, and ClearExtension // - [HasExtension], [GetExtension], [SetExtension], and [ClearExtension]
// access extension field values in a protocol buffer message. // access extension field values in a protocol buffer message.
// //
// Extension fields are only supported in proto2. // Extension fields are only supported in proto2.
// //
// # Related packages // # Related packages
// //
// • Package "google.golang.org/protobuf/encoding/protojson" converts messages to // - Package [google.golang.org/protobuf/encoding/protojson] converts messages to
// and from JSON. // and from JSON.
// //
// • Package "google.golang.org/protobuf/encoding/prototext" converts messages to // - Package [google.golang.org/protobuf/encoding/prototext] converts messages to
// and from the text format. // and from the text format.
// //
// • Package "google.golang.org/protobuf/reflect/protoreflect" provides a // - Package [google.golang.org/protobuf/reflect/protoreflect] provides a
// reflection interface for protocol buffer data types. // reflection interface for protocol buffer data types.
// //
// • Package "google.golang.org/protobuf/testing/protocmp" provides features // - Package [google.golang.org/protobuf/testing/protocmp] provides features
// to compare protocol buffer messages with the "github.com/google/go-cmp/cmp" // to compare protocol buffer messages with the [github.com/google/go-cmp/cmp]
// package. // package.
// //
// • Package "google.golang.org/protobuf/types/dynamicpb" provides a dynamic // - Package [google.golang.org/protobuf/types/dynamicpb] provides a dynamic
// message type, suitable for working with messages where the protocol buffer // message type, suitable for working with messages where the protocol buffer
// type is only known at runtime. // type is only known at runtime.
// //
// This module contains additional packages for more specialized use cases. // This module contains additional packages for more specialized use cases.
// Consult the individual package documentation for details. // Consult the individual package documentation for details.

View File

@ -129,7 +129,7 @@ func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) {
// MarshalState returns the wire-format encoding of a message. // MarshalState returns the wire-format encoding of a message.
// //
// This method permits fine-grained control over the marshaler. // This method permits fine-grained control over the marshaler.
// Most users should use Marshal instead. // Most users should use [Marshal] instead.
func (o MarshalOptions) MarshalState(in protoiface.MarshalInput) (protoiface.MarshalOutput, error) { func (o MarshalOptions) MarshalState(in protoiface.MarshalInput) (protoiface.MarshalOutput, error) {
return o.marshal(in.Buf, in.Message) return o.marshal(in.Buf, in.Message)
} }

View File

@ -5,30 +5,39 @@
package proto package proto
import ( import (
"bytes"
"math"
"reflect" "reflect"
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoreflect"
) )
// Equal reports whether two messages are equal. // Equal reports whether two messages are equal,
// If two messages marshal to the same bytes under deterministic serialization, // by recursively comparing the fields of the message.
// then Equal is guaranteed to report true.
// //
// Two messages are equal if they belong to the same message descriptor, // - Bytes fields are equal if they contain identical bytes.
// have the same set of populated known and extension field values, // Empty bytes (regardless of nil-ness) are considered equal.
// and the same set of unknown fields values. If either of the top-level
// messages are invalid, then Equal reports true only if both are invalid.
// //
// Scalar values are compared with the equivalent of the == operator in Go, // - Floating-point fields are equal if they contain the same value.
// except bytes values which are compared using bytes.Equal and // Unlike the == operator, a NaN is equal to another NaN.
// floating point values which specially treat NaNs as equal. //
// Message values are compared by recursively calling Equal. // - Other scalar fields are equal if they contain the same value.
// Lists are equal if each element value is also equal. //
// Maps are equal if they have the same set of keys, where the pair of values // - Message fields are equal if they have
// for each key is also equal. // the same set of populated known and extension field values, and
// the same set of unknown fields values.
//
// - Lists are equal if they are the same length and
// each corresponding element is equal.
//
// - Maps are equal if they have the same set of keys and
// the corresponding value for each key is equal.
//
// An invalid message is not equal to a valid message.
// An invalid message is only equal to another invalid message of the
// same type. An invalid message often corresponds to a nil pointer
// of the concrete message type. For example, (*pb.M)(nil) is not equal
// to &pb.M{}.
// If two valid messages marshal to the same bytes under deterministic
// serialization, then Equal is guaranteed to report true.
func Equal(x, y Message) bool { func Equal(x, y Message) bool {
if x == nil || y == nil { if x == nil || y == nil {
return x == nil && y == nil return x == nil && y == nil
@ -42,130 +51,7 @@ func Equal(x, y Message) bool {
if mx.IsValid() != my.IsValid() { if mx.IsValid() != my.IsValid() {
return false return false
} }
return equalMessage(mx, my) vx := protoreflect.ValueOfMessage(mx)
} vy := protoreflect.ValueOfMessage(my)
return vx.Equal(vy)
// equalMessage compares two messages.
func equalMessage(mx, my protoreflect.Message) bool {
if mx.Descriptor() != my.Descriptor() {
return false
}
nx := 0
equal := true
mx.Range(func(fd protoreflect.FieldDescriptor, vx protoreflect.Value) bool {
nx++
vy := my.Get(fd)
equal = my.Has(fd) && equalField(fd, vx, vy)
return equal
})
if !equal {
return false
}
ny := 0
my.Range(func(fd protoreflect.FieldDescriptor, vx protoreflect.Value) bool {
ny++
return true
})
if nx != ny {
return false
}
return equalUnknown(mx.GetUnknown(), my.GetUnknown())
}
// equalField compares two fields.
func equalField(fd protoreflect.FieldDescriptor, x, y protoreflect.Value) bool {
switch {
case fd.IsList():
return equalList(fd, x.List(), y.List())
case fd.IsMap():
return equalMap(fd, x.Map(), y.Map())
default:
return equalValue(fd, x, y)
}
}
// equalMap compares two maps.
func equalMap(fd protoreflect.FieldDescriptor, x, y protoreflect.Map) bool {
if x.Len() != y.Len() {
return false
}
equal := true
x.Range(func(k protoreflect.MapKey, vx protoreflect.Value) bool {
vy := y.Get(k)
equal = y.Has(k) && equalValue(fd.MapValue(), vx, vy)
return equal
})
return equal
}
// equalList compares two lists.
func equalList(fd protoreflect.FieldDescriptor, x, y protoreflect.List) bool {
if x.Len() != y.Len() {
return false
}
for i := x.Len() - 1; i >= 0; i-- {
if !equalValue(fd, x.Get(i), y.Get(i)) {
return false
}
}
return true
}
// equalValue compares two singular values.
func equalValue(fd protoreflect.FieldDescriptor, x, y protoreflect.Value) bool {
switch fd.Kind() {
case protoreflect.BoolKind:
return x.Bool() == y.Bool()
case protoreflect.EnumKind:
return x.Enum() == y.Enum()
case protoreflect.Int32Kind, protoreflect.Sint32Kind,
protoreflect.Int64Kind, protoreflect.Sint64Kind,
protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind:
return x.Int() == y.Int()
case protoreflect.Uint32Kind, protoreflect.Uint64Kind,
protoreflect.Fixed32Kind, protoreflect.Fixed64Kind:
return x.Uint() == y.Uint()
case protoreflect.FloatKind, protoreflect.DoubleKind:
fx := x.Float()
fy := y.Float()
if math.IsNaN(fx) || math.IsNaN(fy) {
return math.IsNaN(fx) && math.IsNaN(fy)
}
return fx == fy
case protoreflect.StringKind:
return x.String() == y.String()
case protoreflect.BytesKind:
return bytes.Equal(x.Bytes(), y.Bytes())
case protoreflect.MessageKind, protoreflect.GroupKind:
return equalMessage(x.Message(), y.Message())
default:
return x.Interface() == y.Interface()
}
}
// equalUnknown compares unknown fields by direct comparison on the raw bytes
// of each individual field number.
func equalUnknown(x, y protoreflect.RawFields) bool {
if len(x) != len(y) {
return false
}
if bytes.Equal([]byte(x), []byte(y)) {
return true
}
mx := make(map[protoreflect.FieldNumber]protoreflect.RawFields)
my := make(map[protoreflect.FieldNumber]protoreflect.RawFields)
for len(x) > 0 {
fnum, _, n := protowire.ConsumeField(x)
mx[fnum] = append(mx[fnum], x[:n]...)
x = x[n:]
}
for len(y) > 0 {
fnum, _, n := protowire.ConsumeField(y)
my[fnum] = append(my[fnum], y[:n]...)
y = y[n:]
}
return reflect.DeepEqual(mx, my)
} }

View File

@ -26,7 +26,7 @@ func HasExtension(m Message, xt protoreflect.ExtensionType) bool {
} }
// ClearExtension clears an extension field such that subsequent // ClearExtension clears an extension field such that subsequent
// HasExtension calls return false. // [HasExtension] calls return false.
// It panics if m is invalid or if xt does not extend m. // It panics if m is invalid or if xt does not extend m.
func ClearExtension(m Message, xt protoreflect.ExtensionType) { func ClearExtension(m Message, xt protoreflect.ExtensionType) {
m.ProtoReflect().Clear(xt.TypeDescriptor()) m.ProtoReflect().Clear(xt.TypeDescriptor())

View File

@ -21,7 +21,7 @@ import (
// The unknown fields of src are appended to the unknown fields of dst. // The unknown fields of src are appended to the unknown fields of dst.
// //
// It is semantically equivalent to unmarshaling the encoded form of src // It is semantically equivalent to unmarshaling the encoded form of src
// into dst with the UnmarshalOptions.Merge option specified. // into dst with the [UnmarshalOptions.Merge] option specified.
func Merge(dst, src Message) { func Merge(dst, src Message) {
// TODO: Should nil src be treated as semantically equivalent to a // TODO: Should nil src be treated as semantically equivalent to a
// untyped, read-only, empty message? What about a nil dst? // untyped, read-only, empty message? What about a nil dst?

View File

@ -15,18 +15,20 @@ import (
// protobuf module that accept a Message, except where otherwise specified. // protobuf module that accept a Message, except where otherwise specified.
// //
// This is the v2 interface definition for protobuf messages. // This is the v2 interface definition for protobuf messages.
// The v1 interface definition is "github.com/golang/protobuf/proto".Message. // The v1 interface definition is [github.com/golang/protobuf/proto.Message].
// //
// To convert a v1 message to a v2 message, // - To convert a v1 message to a v2 message,
// use "github.com/golang/protobuf/proto".MessageV2. // use [google.golang.org/protobuf/protoadapt.MessageV2Of].
// To convert a v2 message to a v1 message, // - To convert a v2 message to a v1 message,
// use "github.com/golang/protobuf/proto".MessageV1. // use [google.golang.org/protobuf/protoadapt.MessageV1Of].
type Message = protoreflect.ProtoMessage type Message = protoreflect.ProtoMessage
// Error matches all errors produced by packages in the protobuf module. // Error matches all errors produced by packages in the protobuf module
// according to [errors.Is].
// //
// That is, errors.Is(err, Error) reports whether an error is produced // Example usage:
// by this module. //
// if errors.Is(err, proto.Error) { ... }
var Error error var Error error
func init() { func init() {

View File

@ -73,23 +73,27 @@ func (o MarshalOptions) sizeField(fd protoreflect.FieldDescriptor, value protore
} }
func (o MarshalOptions) sizeList(num protowire.Number, fd protoreflect.FieldDescriptor, list protoreflect.List) (size int) { func (o MarshalOptions) sizeList(num protowire.Number, fd protoreflect.FieldDescriptor, list protoreflect.List) (size int) {
sizeTag := protowire.SizeTag(num)
if fd.IsPacked() && list.Len() > 0 { if fd.IsPacked() && list.Len() > 0 {
content := 0 content := 0
for i, llen := 0, list.Len(); i < llen; i++ { for i, llen := 0, list.Len(); i < llen; i++ {
content += o.sizeSingular(num, fd.Kind(), list.Get(i)) content += o.sizeSingular(num, fd.Kind(), list.Get(i))
} }
return protowire.SizeTag(num) + protowire.SizeBytes(content) return sizeTag + protowire.SizeBytes(content)
} }
for i, llen := 0, list.Len(); i < llen; i++ { for i, llen := 0, list.Len(); i < llen; i++ {
size += protowire.SizeTag(num) + o.sizeSingular(num, fd.Kind(), list.Get(i)) size += sizeTag + o.sizeSingular(num, fd.Kind(), list.Get(i))
} }
return size return size
} }
func (o MarshalOptions) sizeMap(num protowire.Number, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) (size int) { func (o MarshalOptions) sizeMap(num protowire.Number, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) (size int) {
sizeTag := protowire.SizeTag(num)
mapv.Range(func(key protoreflect.MapKey, value protoreflect.Value) bool { mapv.Range(func(key protoreflect.MapKey, value protoreflect.Value) bool {
size += protowire.SizeTag(num) size += sizeTag
size += protowire.SizeBytes(o.sizeField(fd.MapKey(), key.Value()) + o.sizeField(fd.MapValue(), value)) size += protowire.SizeBytes(o.sizeField(fd.MapKey(), key.Value()) + o.sizeField(fd.MapValue(), value))
return true return true
}) })

View File

@ -3,11 +3,11 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package protodesc provides functionality for converting // Package protodesc provides functionality for converting
// FileDescriptorProto messages to/from protoreflect.FileDescriptor values. // FileDescriptorProto messages to/from [protoreflect.FileDescriptor] values.
// //
// The google.protobuf.FileDescriptorProto is a protobuf message that describes // The google.protobuf.FileDescriptorProto is a protobuf message that describes
// the type information for a .proto file in a form that is easily serializable. // the type information for a .proto file in a form that is easily serializable.
// The protoreflect.FileDescriptor is a more structured representation of // The [protoreflect.FileDescriptor] is a more structured representation of
// the FileDescriptorProto message where references and remote dependencies // the FileDescriptorProto message where references and remote dependencies
// can be directly followed. // can be directly followed.
package protodesc package protodesc
@ -24,11 +24,11 @@ import (
"google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/descriptorpb"
) )
// Resolver is the resolver used by NewFile to resolve dependencies. // Resolver is the resolver used by [NewFile] to resolve dependencies.
// The enums and messages provided must belong to some parent file, // The enums and messages provided must belong to some parent file,
// which is also registered. // which is also registered.
// //
// It is implemented by protoregistry.Files. // It is implemented by [protoregistry.Files].
type Resolver interface { type Resolver interface {
FindFileByPath(string) (protoreflect.FileDescriptor, error) FindFileByPath(string) (protoreflect.FileDescriptor, error)
FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error) FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error)
@ -61,19 +61,19 @@ type FileOptions struct {
AllowUnresolvable bool AllowUnresolvable bool
} }
// NewFile creates a new protoreflect.FileDescriptor from the provided // NewFile creates a new [protoreflect.FileDescriptor] from the provided
// file descriptor message. See FileOptions.New for more information. // file descriptor message. See [FileOptions.New] for more information.
func NewFile(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) { func NewFile(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) {
return FileOptions{}.New(fd, r) return FileOptions{}.New(fd, r)
} }
// NewFiles creates a new protoregistry.Files from the provided // NewFiles creates a new [protoregistry.Files] from the provided
// FileDescriptorSet message. See FileOptions.NewFiles for more information. // FileDescriptorSet message. See [FileOptions.NewFiles] for more information.
func NewFiles(fd *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) { func NewFiles(fd *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) {
return FileOptions{}.NewFiles(fd) return FileOptions{}.NewFiles(fd)
} }
// New creates a new protoreflect.FileDescriptor from the provided // New creates a new [protoreflect.FileDescriptor] from the provided
// file descriptor message. The file must represent a valid proto file according // file descriptor message. The file must represent a valid proto file according
// to protobuf semantics. The returned descriptor is a deep copy of the input. // to protobuf semantics. The returned descriptor is a deep copy of the input.
// //
@ -93,9 +93,15 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
f.L1.Syntax = protoreflect.Proto2 f.L1.Syntax = protoreflect.Proto2
case "proto3": case "proto3":
f.L1.Syntax = protoreflect.Proto3 f.L1.Syntax = protoreflect.Proto3
case "editions":
f.L1.Syntax = protoreflect.Editions
f.L1.Edition = fromEditionProto(fd.GetEdition())
default: default:
return nil, errors.New("invalid syntax: %q", fd.GetSyntax()) return nil, errors.New("invalid syntax: %q", fd.GetSyntax())
} }
if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < SupportedEditionsMinimum || fd.GetEdition() > SupportedEditionsMaximum) {
return nil, errors.New("use of edition %v not yet supported by the Go Protobuf runtime", fd.GetEdition())
}
f.L1.Path = fd.GetName() f.L1.Path = fd.GetName()
if f.L1.Path == "" { if f.L1.Path == "" {
return nil, errors.New("file path must be populated") return nil, errors.New("file path must be populated")
@ -108,6 +114,9 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
opts = proto.Clone(opts).(*descriptorpb.FileOptions) opts = proto.Clone(opts).(*descriptorpb.FileOptions)
f.L2.Options = func() protoreflect.ProtoMessage { return opts } f.L2.Options = func() protoreflect.ProtoMessage { return opts }
} }
if f.L1.Syntax == protoreflect.Editions {
initFileDescFromFeatureSet(f, fd.GetOptions().GetFeatures())
}
f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency())) f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency()))
for _, i := range fd.GetPublicDependency() { for _, i := range fd.GetPublicDependency() {
@ -231,7 +240,7 @@ func (is importSet) importPublic(imps protoreflect.FileImports) {
} }
} }
// NewFiles creates a new protoregistry.Files from the provided // NewFiles creates a new [protoregistry.Files] from the provided
// FileDescriptorSet message. The descriptor set must include only // FileDescriptorSet message. The descriptor set must include only
// valid files according to protobuf semantics. The returned descriptors // valid files according to protobuf semantics. The returned descriptors
// are a deep copy of the input. // are a deep copy of the input.

View File

@ -28,6 +28,7 @@ func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProt
opts = proto.Clone(opts).(*descriptorpb.EnumOptions) opts = proto.Clone(opts).(*descriptorpb.EnumOptions)
e.L2.Options = func() protoreflect.ProtoMessage { return opts } e.L2.Options = func() protoreflect.ProtoMessage { return opts }
} }
e.L1.EditionFeatures = mergeEditionFeatures(parent, ed.GetOptions().GetFeatures())
for _, s := range ed.GetReservedName() { for _, s := range ed.GetReservedName() {
e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s)) e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
} }
@ -68,6 +69,9 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt
if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil { if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
return nil, err return nil, err
} }
if m.Base.L0.ParentFile.Syntax() == protoreflect.Editions {
m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures())
}
if opts := md.GetOptions(); opts != nil { if opts := md.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.MessageOptions) opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
m.L2.Options = func() protoreflect.ProtoMessage { return opts } m.L2.Options = func() protoreflect.ProtoMessage { return opts }
@ -114,6 +118,27 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt
return ms, nil return ms, nil
} }
// canBePacked returns whether the field can use packed encoding:
// https://protobuf.dev/programming-guides/encoding/#packed
func canBePacked(fd *descriptorpb.FieldDescriptorProto) bool {
if fd.GetLabel() != descriptorpb.FieldDescriptorProto_LABEL_REPEATED {
return false // not a repeated field
}
switch protoreflect.Kind(fd.GetType()) {
case protoreflect.MessageKind, protoreflect.GroupKind:
return false // not a scalar type field
case protoreflect.StringKind, protoreflect.BytesKind:
// string and bytes can explicitly not be declared as packed,
// see https://protobuf.dev/programming-guides/encoding/#packed
return false
default:
return true
}
}
func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) { func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) {
fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers
for i, fd := range fds { for i, fd := range fds {
@ -137,6 +162,34 @@ func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDesc
if fd.JsonName != nil { if fd.JsonName != nil {
f.L1.StringName.InitJSON(fd.GetJsonName()) f.L1.StringName.InitJSON(fd.GetJsonName())
} }
if f.Base.L0.ParentFile.Syntax() == protoreflect.Editions {
f.L1.EditionFeatures = mergeEditionFeatures(parent, fd.GetOptions().GetFeatures())
if f.L1.EditionFeatures.IsLegacyRequired {
f.L1.Cardinality = protoreflect.Required
}
// We reuse the existing field because the old option `[packed =
// true]` is mutually exclusive with the editions feature.
if canBePacked(fd) {
f.L1.HasPacked = true
f.L1.IsPacked = f.L1.EditionFeatures.IsPacked
}
// We pretend this option is always explicitly set because the only
// use of HasEnforceUTF8 is to determine whether to use EnforceUTF8
// or to return the appropriate default.
// When using editions we either parse the option or resolve the
// appropriate default here (instead of later when this option is
// requested from the descriptor).
// In proto2/proto3 syntax HasEnforceUTF8 might be false.
f.L1.HasEnforceUTF8 = true
f.L1.EnforceUTF8 = f.L1.EditionFeatures.IsUTF8Validated
if f.L1.Kind == protoreflect.MessageKind && f.L1.EditionFeatures.IsDelimitedEncoded {
f.L1.Kind = protoreflect.GroupKind
}
}
} }
return fs, nil return fs, nil
} }
@ -151,6 +204,9 @@ func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDesc
if opts := od.GetOptions(); opts != nil { if opts := od.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.OneofOptions) opts = proto.Clone(opts).(*descriptorpb.OneofOptions)
o.L1.Options = func() protoreflect.ProtoMessage { return opts } o.L1.Options = func() protoreflect.ProtoMessage { return opts }
if parent.Syntax() == protoreflect.Editions {
o.L1.EditionFeatures = mergeEditionFeatures(parent, opts.GetFeatures())
}
} }
} }
return os, nil return os, nil

View File

@ -276,8 +276,8 @@ func unmarshalDefault(s string, fd protoreflect.FieldDescriptor, allowUnresolvab
} else if err != nil { } else if err != nil {
return v, ev, err return v, ev, err
} }
if fd.Syntax() == protoreflect.Proto3 { if !fd.HasPresence() {
return v, ev, errors.New("cannot be specified under proto3 semantics") return v, ev, errors.New("cannot be specified with implicit field presence")
} }
if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated { if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated {
return v, ev, errors.New("cannot be specified on composite types") return v, ev, errors.New("cannot be specified on composite types")

View File

@ -107,7 +107,7 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc
if isMessageSet && !flags.ProtoLegacy { if isMessageSet && !flags.ProtoLegacy {
return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName()) return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName())
} }
if isMessageSet && (m.Syntax() != protoreflect.Proto2 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) { if isMessageSet && (m.Syntax() == protoreflect.Proto3 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) {
return errors.New("message %q is an invalid proto1 MessageSet", m.FullName()) return errors.New("message %q is an invalid proto1 MessageSet", m.FullName())
} }
if m.Syntax() == protoreflect.Proto3 { if m.Syntax() == protoreflect.Proto3 {
@ -314,8 +314,8 @@ func checkValidGroup(fd protoreflect.FieldDescriptor) error {
switch { switch {
case fd.Kind() != protoreflect.GroupKind: case fd.Kind() != protoreflect.GroupKind:
return nil return nil
case fd.Syntax() != protoreflect.Proto2: case fd.Syntax() == protoreflect.Proto3:
return errors.New("invalid under proto2 semantics") return errors.New("invalid under proto3 semantics")
case md == nil || md.IsPlaceholder(): case md == nil || md.IsPlaceholder():
return errors.New("message must be resolvable") return errors.New("message must be resolvable")
case fd.FullName().Parent() != md.FullName().Parent(): case fd.FullName().Parent() != md.FullName().Parent():

View File

@ -0,0 +1,148 @@
// 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 protodesc
import (
"fmt"
"os"
"sync"
"google.golang.org/protobuf/internal/editiondefaults"
"google.golang.org/protobuf/internal/filedesc"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/descriptorpb"
gofeaturespb "google.golang.org/protobuf/types/gofeaturespb"
)
const (
SupportedEditionsMinimum = descriptorpb.Edition_EDITION_PROTO2
SupportedEditionsMaximum = descriptorpb.Edition_EDITION_2023
)
var defaults = &descriptorpb.FeatureSetDefaults{}
var defaultsCacheMu sync.Mutex
var defaultsCache = make(map[filedesc.Edition]*descriptorpb.FeatureSet)
func init() {
err := proto.Unmarshal(editiondefaults.Defaults, defaults)
if err != nil {
fmt.Fprintf(os.Stderr, "unmarshal editions defaults: %v\n", err)
os.Exit(1)
}
}
func fromEditionProto(epb descriptorpb.Edition) filedesc.Edition {
return filedesc.Edition(epb)
}
func toEditionProto(ed filedesc.Edition) descriptorpb.Edition {
switch ed {
case filedesc.EditionUnknown:
return descriptorpb.Edition_EDITION_UNKNOWN
case filedesc.EditionProto2:
return descriptorpb.Edition_EDITION_PROTO2
case filedesc.EditionProto3:
return descriptorpb.Edition_EDITION_PROTO3
case filedesc.Edition2023:
return descriptorpb.Edition_EDITION_2023
default:
panic(fmt.Sprintf("unknown value for edition: %v", ed))
}
}
func getFeatureSetFor(ed filedesc.Edition) *descriptorpb.FeatureSet {
defaultsCacheMu.Lock()
defer defaultsCacheMu.Unlock()
if def, ok := defaultsCache[ed]; ok {
return def
}
edpb := toEditionProto(ed)
if defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb {
// This should never happen protodesc.(FileOptions).New would fail when
// initializing the file descriptor.
// This most likely means the embedded defaults were not updated.
fmt.Fprintf(os.Stderr, "internal error: unsupported edition %v (did you forget to update the embedded defaults (i.e. the bootstrap descriptor proto)?)\n", edpb)
os.Exit(1)
}
fs := defaults.GetDefaults()[0].GetFeatures()
// Using a linear search for now.
// Editions are guaranteed to be sorted and thus we could use a binary search.
// Given that there are only a handful of editions (with one more per year)
// there is not much reason to use a binary search.
for _, def := range defaults.GetDefaults() {
if def.GetEdition() <= edpb {
fs = def.GetFeatures()
} else {
break
}
}
defaultsCache[ed] = fs
return fs
}
// mergeEditionFeatures merges the parent and child feature sets. This function
// should be used when initializing Go descriptors from descriptor protos which
// is why the parent is a filedesc.EditionsFeatures (Go representation) while
// the child is a descriptorproto.FeatureSet (protoc representation).
// Any feature set by the child overwrites what is set by the parent.
func mergeEditionFeatures(parentDesc protoreflect.Descriptor, child *descriptorpb.FeatureSet) filedesc.EditionFeatures {
var parentFS filedesc.EditionFeatures
switch p := parentDesc.(type) {
case *filedesc.File:
parentFS = p.L1.EditionFeatures
case *filedesc.Message:
parentFS = p.L1.EditionFeatures
default:
panic(fmt.Sprintf("unknown parent type %T", parentDesc))
}
if child == nil {
return parentFS
}
if fp := child.FieldPresence; fp != nil {
parentFS.IsFieldPresence = *fp == descriptorpb.FeatureSet_LEGACY_REQUIRED ||
*fp == descriptorpb.FeatureSet_EXPLICIT
parentFS.IsLegacyRequired = *fp == descriptorpb.FeatureSet_LEGACY_REQUIRED
}
if et := child.EnumType; et != nil {
parentFS.IsOpenEnum = *et == descriptorpb.FeatureSet_OPEN
}
if rfe := child.RepeatedFieldEncoding; rfe != nil {
parentFS.IsPacked = *rfe == descriptorpb.FeatureSet_PACKED
}
if utf8val := child.Utf8Validation; utf8val != nil {
parentFS.IsUTF8Validated = *utf8val == descriptorpb.FeatureSet_VERIFY
}
if me := child.MessageEncoding; me != nil {
parentFS.IsDelimitedEncoded = *me == descriptorpb.FeatureSet_DELIMITED
}
if jf := child.JsonFormat; jf != nil {
parentFS.IsJSONCompliant = *jf == descriptorpb.FeatureSet_ALLOW
}
if goFeatures, ok := proto.GetExtension(child, gofeaturespb.E_Go).(*gofeaturespb.GoFeatures); ok && goFeatures != nil {
if luje := goFeatures.LegacyUnmarshalJsonEnum; luje != nil {
parentFS.GenerateLegacyUnmarshalJSON = *luje
}
}
return parentFS
}
// initFileDescFromFeatureSet initializes editions related fields in fd based
// on fs. If fs is nil it is assumed to be an empty featureset and all fields
// will be initialized with the appropriate default. fd.L1.Edition must be set
// before calling this function.
func initFileDescFromFeatureSet(fd *filedesc.File, fs *descriptorpb.FeatureSet) {
dfs := getFeatureSetFor(fd.L1.Edition)
// initialize the featureset with the defaults
fd.L1.EditionFeatures = mergeEditionFeatures(fd, dfs)
// overwrite any options explicitly specified
fd.L1.EditionFeatures = mergeEditionFeatures(fd, fs)
}

View File

@ -16,7 +16,7 @@ import (
"google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/descriptorpb"
) )
// ToFileDescriptorProto copies a protoreflect.FileDescriptor into a // ToFileDescriptorProto copies a [protoreflect.FileDescriptor] into a
// google.protobuf.FileDescriptorProto message. // google.protobuf.FileDescriptorProto message.
func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileDescriptorProto { func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileDescriptorProto {
p := &descriptorpb.FileDescriptorProto{ p := &descriptorpb.FileDescriptorProto{
@ -70,13 +70,13 @@ func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileD
for i, exts := 0, file.Extensions(); i < exts.Len(); i++ { for i, exts := 0, file.Extensions(); i < exts.Len(); i++ {
p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i))) p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i)))
} }
if syntax := file.Syntax(); syntax != protoreflect.Proto2 { if syntax := file.Syntax(); syntax != protoreflect.Proto2 && syntax.IsValid() {
p.Syntax = proto.String(file.Syntax().String()) p.Syntax = proto.String(file.Syntax().String())
} }
return p return p
} }
// ToDescriptorProto copies a protoreflect.MessageDescriptor into a // ToDescriptorProto copies a [protoreflect.MessageDescriptor] into a
// google.protobuf.DescriptorProto message. // google.protobuf.DescriptorProto message.
func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.DescriptorProto { func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.DescriptorProto {
p := &descriptorpb.DescriptorProto{ p := &descriptorpb.DescriptorProto{
@ -119,7 +119,7 @@ func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.Des
return p return p
} }
// ToFieldDescriptorProto copies a protoreflect.FieldDescriptor into a // ToFieldDescriptorProto copies a [protoreflect.FieldDescriptor] into a
// google.protobuf.FieldDescriptorProto message. // google.protobuf.FieldDescriptorProto message.
func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.FieldDescriptorProto { func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.FieldDescriptorProto {
p := &descriptorpb.FieldDescriptorProto{ p := &descriptorpb.FieldDescriptorProto{
@ -168,7 +168,7 @@ func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.Fi
return p return p
} }
// ToOneofDescriptorProto copies a protoreflect.OneofDescriptor into a // ToOneofDescriptorProto copies a [protoreflect.OneofDescriptor] into a
// google.protobuf.OneofDescriptorProto message. // google.protobuf.OneofDescriptorProto message.
func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.OneofDescriptorProto { func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.OneofDescriptorProto {
return &descriptorpb.OneofDescriptorProto{ return &descriptorpb.OneofDescriptorProto{
@ -177,7 +177,7 @@ func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.On
} }
} }
// ToEnumDescriptorProto copies a protoreflect.EnumDescriptor into a // ToEnumDescriptorProto copies a [protoreflect.EnumDescriptor] into a
// google.protobuf.EnumDescriptorProto message. // google.protobuf.EnumDescriptorProto message.
func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumDescriptorProto { func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumDescriptorProto {
p := &descriptorpb.EnumDescriptorProto{ p := &descriptorpb.EnumDescriptorProto{
@ -200,7 +200,7 @@ func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumD
return p return p
} }
// ToEnumValueDescriptorProto copies a protoreflect.EnumValueDescriptor into a // ToEnumValueDescriptorProto copies a [protoreflect.EnumValueDescriptor] into a
// google.protobuf.EnumValueDescriptorProto message. // google.protobuf.EnumValueDescriptorProto message.
func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descriptorpb.EnumValueDescriptorProto { func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descriptorpb.EnumValueDescriptorProto {
return &descriptorpb.EnumValueDescriptorProto{ return &descriptorpb.EnumValueDescriptorProto{
@ -210,7 +210,7 @@ func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descrip
} }
} }
// ToServiceDescriptorProto copies a protoreflect.ServiceDescriptor into a // ToServiceDescriptorProto copies a [protoreflect.ServiceDescriptor] into a
// google.protobuf.ServiceDescriptorProto message. // google.protobuf.ServiceDescriptorProto message.
func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descriptorpb.ServiceDescriptorProto { func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descriptorpb.ServiceDescriptorProto {
p := &descriptorpb.ServiceDescriptorProto{ p := &descriptorpb.ServiceDescriptorProto{
@ -223,7 +223,7 @@ func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descripto
return p return p
} }
// ToMethodDescriptorProto copies a protoreflect.MethodDescriptor into a // ToMethodDescriptorProto copies a [protoreflect.MethodDescriptor] into a
// google.protobuf.MethodDescriptorProto message. // google.protobuf.MethodDescriptorProto message.
func ToMethodDescriptorProto(method protoreflect.MethodDescriptor) *descriptorpb.MethodDescriptorProto { func ToMethodDescriptorProto(method protoreflect.MethodDescriptor) *descriptorpb.MethodDescriptorProto {
p := &descriptorpb.MethodDescriptorProto{ p := &descriptorpb.MethodDescriptorProto{

View File

@ -10,46 +10,46 @@
// //
// # Protocol Buffer Descriptors // # Protocol Buffer Descriptors
// //
// Protobuf descriptors (e.g., EnumDescriptor or MessageDescriptor) // Protobuf descriptors (e.g., [EnumDescriptor] or [MessageDescriptor])
// are immutable objects that represent protobuf type information. // are immutable objects that represent protobuf type information.
// They are wrappers around the messages declared in descriptor.proto. // They are wrappers around the messages declared in descriptor.proto.
// Protobuf descriptors alone lack any information regarding Go types. // Protobuf descriptors alone lack any information regarding Go types.
// //
// Enums and messages generated by this module implement Enum and ProtoMessage, // Enums and messages generated by this module implement [Enum] and [ProtoMessage],
// where the Descriptor and ProtoReflect.Descriptor accessors respectively // where the Descriptor and ProtoReflect.Descriptor accessors respectively
// return the protobuf descriptor for the values. // return the protobuf descriptor for the values.
// //
// The protobuf descriptor interfaces are not meant to be implemented by // The protobuf descriptor interfaces are not meant to be implemented by
// user code since they might need to be extended in the future to support // user code since they might need to be extended in the future to support
// additions to the protobuf language. // additions to the protobuf language.
// The "google.golang.org/protobuf/reflect/protodesc" package converts between // The [google.golang.org/protobuf/reflect/protodesc] package converts between
// google.protobuf.DescriptorProto messages and protobuf descriptors. // google.protobuf.DescriptorProto messages and protobuf descriptors.
// //
// # Go Type Descriptors // # Go Type Descriptors
// //
// A type descriptor (e.g., EnumType or MessageType) is a constructor for // A type descriptor (e.g., [EnumType] or [MessageType]) is a constructor for
// a concrete Go type that represents the associated protobuf descriptor. // a concrete Go type that represents the associated protobuf descriptor.
// There is commonly a one-to-one relationship between protobuf descriptors and // There is commonly a one-to-one relationship between protobuf descriptors and
// Go type descriptors, but it can potentially be a one-to-many relationship. // Go type descriptors, but it can potentially be a one-to-many relationship.
// //
// Enums and messages generated by this module implement Enum and ProtoMessage, // Enums and messages generated by this module implement [Enum] and [ProtoMessage],
// where the Type and ProtoReflect.Type accessors respectively // where the Type and ProtoReflect.Type accessors respectively
// return the protobuf descriptor for the values. // return the protobuf descriptor for the values.
// //
// The "google.golang.org/protobuf/types/dynamicpb" package can be used to // The [google.golang.org/protobuf/types/dynamicpb] package can be used to
// create Go type descriptors from protobuf descriptors. // create Go type descriptors from protobuf descriptors.
// //
// # Value Interfaces // # Value Interfaces
// //
// The Enum and Message interfaces provide a reflective view over an // The [Enum] and [Message] interfaces provide a reflective view over an
// enum or message instance. For enums, it provides the ability to retrieve // enum or message instance. For enums, it provides the ability to retrieve
// the enum value number for any concrete enum type. For messages, it provides // the enum value number for any concrete enum type. For messages, it provides
// the ability to access or manipulate fields of the message. // the ability to access or manipulate fields of the message.
// //
// To convert a proto.Message to a protoreflect.Message, use the // To convert a [google.golang.org/protobuf/proto.Message] to a [protoreflect.Message], use the
// former's ProtoReflect method. Since the ProtoReflect method is new to the // former's ProtoReflect method. Since the ProtoReflect method is new to the
// v2 message interface, it may not be present on older message implementations. // v2 message interface, it may not be present on older message implementations.
// The "github.com/golang/protobuf/proto".MessageReflect function can be used // The [github.com/golang/protobuf/proto.MessageReflect] function can be used
// to obtain a reflective view on older messages. // to obtain a reflective view on older messages.
// //
// # Relationships // # Relationships
@ -71,12 +71,12 @@
// │ │ // │ │
// └────────────────── Type() ───────┘ // └────────────────── Type() ───────┘
// //
// • An EnumType describes a concrete Go enum type. // • An [EnumType] describes a concrete Go enum type.
// It has an EnumDescriptor and can construct an Enum instance. // It has an EnumDescriptor and can construct an Enum instance.
// //
// • An EnumDescriptor describes an abstract protobuf enum type. // • An [EnumDescriptor] describes an abstract protobuf enum type.
// //
// • An Enum is a concrete enum instance. Generated enums implement Enum. // • An [Enum] is a concrete enum instance. Generated enums implement Enum.
// //
// ┌──────────────── New() ─────────────────┐ // ┌──────────────── New() ─────────────────┐
// │ │ // │ │
@ -90,24 +90,26 @@
// │ │ // │ │
// └─────────────────── Type() ─────────┘ // └─────────────────── Type() ─────────┘
// //
// • A MessageType describes a concrete Go message type. // • A [MessageType] describes a concrete Go message type.
// It has a MessageDescriptor and can construct a Message instance. // It has a [MessageDescriptor] and can construct a [Message] instance.
// Just as how Go's reflect.Type is a reflective description of a Go type, // Just as how Go's [reflect.Type] is a reflective description of a Go type,
// a MessageType is a reflective description of a Go type for a protobuf message. // a [MessageType] is a reflective description of a Go type for a protobuf message.
// //
// • A MessageDescriptor describes an abstract protobuf message type. // • A [MessageDescriptor] describes an abstract protobuf message type.
// It has no understanding of Go types. In order to construct a MessageType // It has no understanding of Go types. In order to construct a [MessageType]
// from just a MessageDescriptor, you can consider looking up the message type // from just a [MessageDescriptor], you can consider looking up the message type
// in the global registry using protoregistry.GlobalTypes.FindMessageByName // in the global registry using the FindMessageByName method on
// or constructing a dynamic MessageType using dynamicpb.NewMessageType. // [google.golang.org/protobuf/reflect/protoregistry.GlobalTypes]
// or constructing a dynamic [MessageType] using
// [google.golang.org/protobuf/types/dynamicpb.NewMessageType].
// //
// • A Message is a reflective view over a concrete message instance. // • A [Message] is a reflective view over a concrete message instance.
// Generated messages implement ProtoMessage, which can convert to a Message. // Generated messages implement [ProtoMessage], which can convert to a [Message].
// Just as how Go's reflect.Value is a reflective view over a Go value, // Just as how Go's [reflect.Value] is a reflective view over a Go value,
// a Message is a reflective view over a concrete protobuf message instance. // a [Message] is a reflective view over a concrete protobuf message instance.
// Using Go reflection as an analogy, the ProtoReflect method is similar to // Using Go reflection as an analogy, the [ProtoMessage.ProtoReflect] method is similar to
// calling reflect.ValueOf, and the Message.Interface method is similar to // calling [reflect.ValueOf], and the [Message.Interface] method is similar to
// calling reflect.Value.Interface. // calling [reflect.Value.Interface].
// //
// ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐ // ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐
// │ V │ V // │ V │ V
@ -119,15 +121,15 @@
// │ │ // │ │
// └────── implements ────────┘ // └────── implements ────────┘
// //
// • An ExtensionType describes a concrete Go implementation of an extension. // • An [ExtensionType] describes a concrete Go implementation of an extension.
// It has an ExtensionTypeDescriptor and can convert to/from // It has an [ExtensionTypeDescriptor] and can convert to/from
// abstract Values and Go values. // an abstract [Value] and a Go value.
// //
// • An ExtensionTypeDescriptor is an ExtensionDescriptor // • An [ExtensionTypeDescriptor] is an [ExtensionDescriptor]
// which also has an ExtensionType. // which also has an [ExtensionType].
// //
// • An ExtensionDescriptor describes an abstract protobuf extension field and // • An [ExtensionDescriptor] describes an abstract protobuf extension field and
// may not always be an ExtensionTypeDescriptor. // may not always be an [ExtensionTypeDescriptor].
package protoreflect package protoreflect
import ( import (
@ -142,7 +144,7 @@ type doNotImplement pragma.DoNotImplement
// ProtoMessage is the top-level interface that all proto messages implement. // ProtoMessage is the top-level interface that all proto messages implement.
// This is declared in the protoreflect package to avoid a cyclic dependency; // This is declared in the protoreflect package to avoid a cyclic dependency;
// use the proto.Message type instead, which aliases this type. // use the [google.golang.org/protobuf/proto.Message] type instead, which aliases this type.
type ProtoMessage interface{ ProtoReflect() Message } type ProtoMessage interface{ ProtoReflect() Message }
// Syntax is the language version of the proto file. // Syntax is the language version of the proto file.
@ -151,8 +153,9 @@ type Syntax syntax
type syntax int8 // keep exact type opaque as the int type may change type syntax int8 // keep exact type opaque as the int type may change
const ( const (
Proto2 Syntax = 2 Proto2 Syntax = 2
Proto3 Syntax = 3 Proto3 Syntax = 3
Editions Syntax = 4
) )
// IsValid reports whether the syntax is valid. // IsValid reports whether the syntax is valid.
@ -172,6 +175,8 @@ func (s Syntax) String() string {
return "proto2" return "proto2"
case Proto3: case Proto3:
return "proto3" return "proto3"
case Editions:
return "editions"
default: default:
return fmt.Sprintf("<unknown:%d>", s) return fmt.Sprintf("<unknown:%d>", s)
} }
@ -436,7 +441,7 @@ type Names interface {
// FullName is a qualified name that uniquely identifies a proto declaration. // FullName is a qualified name that uniquely identifies a proto declaration.
// A qualified name is the concatenation of the proto package along with the // A qualified name is the concatenation of the proto package along with the
// fully-declared name (i.e., name of parent preceding the name of the child), // fully-declared name (i.e., name of parent preceding the name of the child),
// with a '.' delimiter placed between each Name. // with a '.' delimiter placed between each [Name].
// //
// This should not have any leading or trailing dots. // This should not have any leading or trailing dots.
type FullName string // e.g., "google.protobuf.Field.Kind" type FullName string // e.g., "google.protobuf.Field.Kind"
@ -480,7 +485,7 @@ func isLetterDigit(c byte) bool {
} }
// Name returns the short name, which is the last identifier segment. // Name returns the short name, which is the last identifier segment.
// A single segment FullName is the Name itself. // A single segment FullName is the [Name] itself.
func (n FullName) Name() Name { func (n FullName) Name() Name {
if i := strings.LastIndexByte(string(n), '.'); i >= 0 { if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
return Name(n[i+1:]) return Name(n[i+1:])

View File

@ -35,6 +35,8 @@ func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte {
b = p.appendSingularField(b, "source_code_info", (*SourcePath).appendSourceCodeInfo) b = p.appendSingularField(b, "source_code_info", (*SourcePath).appendSourceCodeInfo)
case 12: case 12:
b = p.appendSingularField(b, "syntax", nil) b = p.appendSingularField(b, "syntax", nil)
case 14:
b = p.appendSingularField(b, "edition", nil)
} }
return b return b
} }
@ -158,8 +160,6 @@ func (p *SourcePath) appendFileOptions(b []byte) []byte {
b = p.appendSingularField(b, "java_generic_services", nil) b = p.appendSingularField(b, "java_generic_services", nil)
case 18: case 18:
b = p.appendSingularField(b, "py_generic_services", nil) b = p.appendSingularField(b, "py_generic_services", nil)
case 42:
b = p.appendSingularField(b, "php_generic_services", nil)
case 23: case 23:
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 31: case 31:
@ -178,6 +178,8 @@ func (p *SourcePath) appendFileOptions(b []byte) []byte {
b = p.appendSingularField(b, "php_metadata_namespace", nil) b = p.appendSingularField(b, "php_metadata_namespace", nil)
case 45: case 45:
b = p.appendSingularField(b, "ruby_package", nil) b = p.appendSingularField(b, "ruby_package", nil)
case 50:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -236,6 +238,10 @@ func (p *SourcePath) appendMessageOptions(b []byte) []byte {
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 7: case 7:
b = p.appendSingularField(b, "map_entry", nil) b = p.appendSingularField(b, "map_entry", nil)
case 11:
b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil)
case 12:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -279,6 +285,10 @@ func (p *SourcePath) appendEnumOptions(b []byte) []byte {
b = p.appendSingularField(b, "allow_alias", nil) b = p.appendSingularField(b, "allow_alias", nil)
case 3: case 3:
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 6:
b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil)
case 7:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -324,6 +334,8 @@ func (p *SourcePath) appendServiceOptions(b []byte) []byte {
return b return b
} }
switch (*p)[0] { switch (*p)[0] {
case 34:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 33: case 33:
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 999: case 999:
@ -345,16 +357,49 @@ func (p *SourcePath) appendFieldOptions(b []byte) []byte {
b = p.appendSingularField(b, "jstype", nil) b = p.appendSingularField(b, "jstype", nil)
case 5: case 5:
b = p.appendSingularField(b, "lazy", nil) b = p.appendSingularField(b, "lazy", nil)
case 15:
b = p.appendSingularField(b, "unverified_lazy", nil)
case 3: case 3:
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 10: case 10:
b = p.appendSingularField(b, "weak", nil) b = p.appendSingularField(b, "weak", nil)
case 16:
b = p.appendSingularField(b, "debug_redact", nil)
case 17:
b = p.appendSingularField(b, "retention", nil)
case 19:
b = p.appendRepeatedField(b, "targets", nil)
case 20:
b = p.appendRepeatedField(b, "edition_defaults", (*SourcePath).appendFieldOptions_EditionDefault)
case 21:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
return b return b
} }
func (p *SourcePath) appendFeatureSet(b []byte) []byte {
if len(*p) == 0 {
return b
}
switch (*p)[0] {
case 1:
b = p.appendSingularField(b, "field_presence", nil)
case 2:
b = p.appendSingularField(b, "enum_type", nil)
case 3:
b = p.appendSingularField(b, "repeated_field_encoding", nil)
case 4:
b = p.appendSingularField(b, "utf8_validation", nil)
case 5:
b = p.appendSingularField(b, "message_encoding", nil)
case 6:
b = p.appendSingularField(b, "json_format", nil)
}
return b
}
func (p *SourcePath) appendUninterpretedOption(b []byte) []byte { func (p *SourcePath) appendUninterpretedOption(b []byte) []byte {
if len(*p) == 0 { if len(*p) == 0 {
return b return b
@ -404,6 +449,12 @@ func (p *SourcePath) appendExtensionRangeOptions(b []byte) []byte {
switch (*p)[0] { switch (*p)[0] {
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
case 2:
b = p.appendRepeatedField(b, "declaration", (*SourcePath).appendExtensionRangeOptions_Declaration)
case 50:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 3:
b = p.appendSingularField(b, "verification", nil)
} }
return b return b
} }
@ -413,6 +464,8 @@ func (p *SourcePath) appendOneofOptions(b []byte) []byte {
return b return b
} }
switch (*p)[0] { switch (*p)[0] {
case 1:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -426,6 +479,10 @@ func (p *SourcePath) appendEnumValueOptions(b []byte) []byte {
switch (*p)[0] { switch (*p)[0] {
case 1: case 1:
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 2:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 3:
b = p.appendSingularField(b, "debug_redact", nil)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
@ -441,12 +498,27 @@ func (p *SourcePath) appendMethodOptions(b []byte) []byte {
b = p.appendSingularField(b, "deprecated", nil) b = p.appendSingularField(b, "deprecated", nil)
case 34: case 34:
b = p.appendSingularField(b, "idempotency_level", nil) b = p.appendSingularField(b, "idempotency_level", nil)
case 35:
b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999: case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
} }
return b return b
} }
func (p *SourcePath) appendFieldOptions_EditionDefault(b []byte) []byte {
if len(*p) == 0 {
return b
}
switch (*p)[0] {
case 3:
b = p.appendSingularField(b, "edition", nil)
case 2:
b = p.appendSingularField(b, "value", nil)
}
return b
}
func (p *SourcePath) appendUninterpretedOption_NamePart(b []byte) []byte { func (p *SourcePath) appendUninterpretedOption_NamePart(b []byte) []byte {
if len(*p) == 0 { if len(*p) == 0 {
return b return b
@ -459,3 +531,22 @@ func (p *SourcePath) appendUninterpretedOption_NamePart(b []byte) []byte {
} }
return b return b
} }
func (p *SourcePath) appendExtensionRangeOptions_Declaration(b []byte) []byte {
if len(*p) == 0 {
return b
}
switch (*p)[0] {
case 1:
b = p.appendSingularField(b, "number", nil)
case 2:
b = p.appendSingularField(b, "full_name", nil)
case 3:
b = p.appendSingularField(b, "type", nil)
case 5:
b = p.appendSingularField(b, "reserved", nil)
case 6:
b = p.appendSingularField(b, "repeated", nil)
}
return b
}

View File

@ -12,7 +12,7 @@ package protoreflect
// exactly identical. However, it is possible for the same semantically // exactly identical. However, it is possible for the same semantically
// identical proto type to be represented by multiple type descriptors. // identical proto type to be represented by multiple type descriptors.
// //
// For example, suppose we have t1 and t2 which are both MessageDescriptors. // For example, suppose we have t1 and t2 which are both an [MessageDescriptor].
// If t1 == t2, then the types are definitely equal and all accessors return // If t1 == t2, then the types are definitely equal and all accessors return
// the same information. However, if t1 != t2, then it is still possible that // the same information. However, if t1 != t2, then it is still possible that
// they still represent the same proto type (e.g., t1.FullName == t2.FullName). // they still represent the same proto type (e.g., t1.FullName == t2.FullName).
@ -115,7 +115,7 @@ type Descriptor interface {
// corresponds with the google.protobuf.FileDescriptorProto message. // corresponds with the google.protobuf.FileDescriptorProto message.
// //
// Top-level declarations: // Top-level declarations:
// EnumDescriptor, MessageDescriptor, FieldDescriptor, and/or ServiceDescriptor. // [EnumDescriptor], [MessageDescriptor], [FieldDescriptor], and/or [ServiceDescriptor].
type FileDescriptor interface { type FileDescriptor interface {
Descriptor // Descriptor.FullName is identical to Package Descriptor // Descriptor.FullName is identical to Package
@ -180,8 +180,8 @@ type FileImport struct {
// corresponds with the google.protobuf.DescriptorProto message. // corresponds with the google.protobuf.DescriptorProto message.
// //
// Nested declarations: // Nested declarations:
// FieldDescriptor, OneofDescriptor, FieldDescriptor, EnumDescriptor, // [FieldDescriptor], [OneofDescriptor], [FieldDescriptor], [EnumDescriptor],
// and/or MessageDescriptor. // and/or [MessageDescriptor].
type MessageDescriptor interface { type MessageDescriptor interface {
Descriptor Descriptor
@ -214,7 +214,7 @@ type MessageDescriptor interface {
ExtensionRanges() FieldRanges ExtensionRanges() FieldRanges
// ExtensionRangeOptions returns the ith extension range options. // ExtensionRangeOptions returns the ith extension range options.
// //
// To avoid a dependency cycle, this method returns a proto.Message value, // To avoid a dependency cycle, this method returns a proto.Message] value,
// which always contains a google.protobuf.ExtensionRangeOptions message. // which always contains a google.protobuf.ExtensionRangeOptions message.
// This method returns a typed nil-pointer if no options are present. // This method returns a typed nil-pointer if no options are present.
// The caller must import the descriptorpb package to use this. // The caller must import the descriptorpb package to use this.
@ -231,9 +231,9 @@ type MessageDescriptor interface {
} }
type isMessageDescriptor interface{ ProtoType(MessageDescriptor) } type isMessageDescriptor interface{ ProtoType(MessageDescriptor) }
// MessageType encapsulates a MessageDescriptor with a concrete Go implementation. // MessageType encapsulates a [MessageDescriptor] with a concrete Go implementation.
// It is recommended that implementations of this interface also implement the // It is recommended that implementations of this interface also implement the
// MessageFieldTypes interface. // [MessageFieldTypes] interface.
type MessageType interface { type MessageType interface {
// New returns a newly allocated empty message. // New returns a newly allocated empty message.
// It may return nil for synthetic messages representing a map entry. // It may return nil for synthetic messages representing a map entry.
@ -249,19 +249,19 @@ type MessageType interface {
Descriptor() MessageDescriptor Descriptor() MessageDescriptor
} }
// MessageFieldTypes extends a MessageType by providing type information // MessageFieldTypes extends a [MessageType] by providing type information
// regarding enums and messages referenced by the message fields. // regarding enums and messages referenced by the message fields.
type MessageFieldTypes interface { type MessageFieldTypes interface {
MessageType MessageType
// Enum returns the EnumType for the ith field in Descriptor.Fields. // Enum returns the EnumType for the ith field in MessageDescriptor.Fields.
// It returns nil if the ith field is not an enum kind. // It returns nil if the ith field is not an enum kind.
// It panics if out of bounds. // It panics if out of bounds.
// //
// Invariant: mt.Enum(i).Descriptor() == mt.Descriptor().Fields(i).Enum() // Invariant: mt.Enum(i).Descriptor() == mt.Descriptor().Fields(i).Enum()
Enum(i int) EnumType Enum(i int) EnumType
// Message returns the MessageType for the ith field in Descriptor.Fields. // Message returns the MessageType for the ith field in MessageDescriptor.Fields.
// It returns nil if the ith field is not a message or group kind. // It returns nil if the ith field is not a message or group kind.
// It panics if out of bounds. // It panics if out of bounds.
// //
@ -286,8 +286,8 @@ type MessageDescriptors interface {
// corresponds with the google.protobuf.FieldDescriptorProto message. // corresponds with the google.protobuf.FieldDescriptorProto message.
// //
// It is used for both normal fields defined within the parent message // It is used for both normal fields defined within the parent message
// (e.g., MessageDescriptor.Fields) and fields that extend some remote message // (e.g., [MessageDescriptor.Fields]) and fields that extend some remote message
// (e.g., FileDescriptor.Extensions or MessageDescriptor.Extensions). // (e.g., [FileDescriptor.Extensions] or [MessageDescriptor.Extensions]).
type FieldDescriptor interface { type FieldDescriptor interface {
Descriptor Descriptor
@ -344,7 +344,7 @@ type FieldDescriptor interface {
// IsMap reports whether this field represents a map, // IsMap reports whether this field represents a map,
// where the value type for the associated field is a Map. // where the value type for the associated field is a Map.
// It is equivalent to checking whether Cardinality is Repeated, // It is equivalent to checking whether Cardinality is Repeated,
// that the Kind is MessageKind, and that Message.IsMapEntry reports true. // that the Kind is MessageKind, and that MessageDescriptor.IsMapEntry reports true.
IsMap() bool IsMap() bool
// MapKey returns the field descriptor for the key in the map entry. // MapKey returns the field descriptor for the key in the map entry.
@ -419,7 +419,7 @@ type OneofDescriptor interface {
// IsSynthetic reports whether this is a synthetic oneof created to support // IsSynthetic reports whether this is a synthetic oneof created to support
// proto3 optional semantics. If true, Fields contains exactly one field // proto3 optional semantics. If true, Fields contains exactly one field
// with HasOptionalKeyword specified. // with FieldDescriptor.HasOptionalKeyword specified.
IsSynthetic() bool IsSynthetic() bool
// Fields is a list of fields belonging to this oneof. // Fields is a list of fields belonging to this oneof.
@ -442,10 +442,10 @@ type OneofDescriptors interface {
doNotImplement doNotImplement
} }
// ExtensionDescriptor is an alias of FieldDescriptor for documentation. // ExtensionDescriptor is an alias of [FieldDescriptor] for documentation.
type ExtensionDescriptor = FieldDescriptor type ExtensionDescriptor = FieldDescriptor
// ExtensionTypeDescriptor is an ExtensionDescriptor with an associated ExtensionType. // ExtensionTypeDescriptor is an [ExtensionDescriptor] with an associated [ExtensionType].
type ExtensionTypeDescriptor interface { type ExtensionTypeDescriptor interface {
ExtensionDescriptor ExtensionDescriptor
@ -470,12 +470,12 @@ type ExtensionDescriptors interface {
doNotImplement doNotImplement
} }
// ExtensionType encapsulates an ExtensionDescriptor with a concrete // ExtensionType encapsulates an [ExtensionDescriptor] with a concrete
// Go implementation. The nested field descriptor must be for a extension field. // Go implementation. The nested field descriptor must be for a extension field.
// //
// While a normal field is a member of the parent message that it is declared // While a normal field is a member of the parent message that it is declared
// within (see Descriptor.Parent), an extension field is a member of some other // within (see [Descriptor.Parent]), an extension field is a member of some other
// target message (see ExtensionDescriptor.Extendee) and may have no // target message (see [FieldDescriptor.ContainingMessage]) and may have no
// relationship with the parent. However, the full name of an extension field is // relationship with the parent. However, the full name of an extension field is
// relative to the parent that it is declared within. // relative to the parent that it is declared within.
// //
@ -532,7 +532,7 @@ type ExtensionType interface {
// corresponds with the google.protobuf.EnumDescriptorProto message. // corresponds with the google.protobuf.EnumDescriptorProto message.
// //
// Nested declarations: // Nested declarations:
// EnumValueDescriptor. // [EnumValueDescriptor].
type EnumDescriptor interface { type EnumDescriptor interface {
Descriptor Descriptor
@ -548,7 +548,7 @@ type EnumDescriptor interface {
} }
type isEnumDescriptor interface{ ProtoType(EnumDescriptor) } type isEnumDescriptor interface{ ProtoType(EnumDescriptor) }
// EnumType encapsulates an EnumDescriptor with a concrete Go implementation. // EnumType encapsulates an [EnumDescriptor] with a concrete Go implementation.
type EnumType interface { type EnumType interface {
// New returns an instance of this enum type with its value set to n. // New returns an instance of this enum type with its value set to n.
New(n EnumNumber) Enum New(n EnumNumber) Enum
@ -610,7 +610,7 @@ type EnumValueDescriptors interface {
// ServiceDescriptor describes a service and // ServiceDescriptor describes a service and
// corresponds with the google.protobuf.ServiceDescriptorProto message. // corresponds with the google.protobuf.ServiceDescriptorProto message.
// //
// Nested declarations: MethodDescriptor. // Nested declarations: [MethodDescriptor].
type ServiceDescriptor interface { type ServiceDescriptor interface {
Descriptor Descriptor

View File

@ -27,16 +27,16 @@ type Enum interface {
// Message is a reflective interface for a concrete message value, // Message is a reflective interface for a concrete message value,
// encapsulating both type and value information for the message. // encapsulating both type and value information for the message.
// //
// Accessor/mutators for individual fields are keyed by FieldDescriptor. // Accessor/mutators for individual fields are keyed by [FieldDescriptor].
// For non-extension fields, the descriptor must exactly match the // For non-extension fields, the descriptor must exactly match the
// field known by the parent message. // field known by the parent message.
// For extension fields, the descriptor must implement ExtensionTypeDescriptor, // For extension fields, the descriptor must implement [ExtensionTypeDescriptor],
// extend the parent message (i.e., have the same message FullName), and // extend the parent message (i.e., have the same message [FullName]), and
// be within the parent's extension range. // be within the parent's extension range.
// //
// Each field Value can be a scalar or a composite type (Message, List, or Map). // Each field [Value] can be a scalar or a composite type ([Message], [List], or [Map]).
// See Value for the Go types associated with a FieldDescriptor. // See [Value] for the Go types associated with a [FieldDescriptor].
// Providing a Value that is invalid or of an incorrect type panics. // Providing a [Value] that is invalid or of an incorrect type panics.
type Message interface { type Message interface {
// Descriptor returns message descriptor, which contains only the protobuf // Descriptor returns message descriptor, which contains only the protobuf
// type information for the message. // type information for the message.
@ -148,11 +148,11 @@ type Message interface {
// be preserved in marshaling or other operations. // be preserved in marshaling or other operations.
IsValid() bool IsValid() bool
// ProtoMethods returns optional fast-path implementions of various operations. // ProtoMethods returns optional fast-path implementations of various operations.
// This method may return nil. // This method may return nil.
// //
// The returned methods type is identical to // The returned methods type is identical to
// "google.golang.org/protobuf/runtime/protoiface".Methods. // google.golang.org/protobuf/runtime/protoiface.Methods.
// Consult the protoiface package documentation for details. // Consult the protoiface package documentation for details.
ProtoMethods() *methods ProtoMethods() *methods
} }
@ -175,8 +175,8 @@ func (b RawFields) IsValid() bool {
} }
// List is a zero-indexed, ordered list. // List is a zero-indexed, ordered list.
// The element Value type is determined by FieldDescriptor.Kind. // The element [Value] type is determined by [FieldDescriptor.Kind].
// Providing a Value that is invalid or of an incorrect type panics. // Providing a [Value] that is invalid or of an incorrect type panics.
type List interface { type List interface {
// Len reports the number of entries in the List. // Len reports the number of entries in the List.
// Get, Set, and Truncate panic with out of bound indexes. // Get, Set, and Truncate panic with out of bound indexes.
@ -226,9 +226,9 @@ type List interface {
} }
// Map is an unordered, associative map. // Map is an unordered, associative map.
// The entry MapKey type is determined by FieldDescriptor.MapKey.Kind. // The entry [MapKey] type is determined by [FieldDescriptor.MapKey].Kind.
// The entry Value type is determined by FieldDescriptor.MapValue.Kind. // The entry [Value] type is determined by [FieldDescriptor.MapValue].Kind.
// Providing a MapKey or Value that is invalid or of an incorrect type panics. // Providing a [MapKey] or [Value] that is invalid or of an incorrect type panics.
type Map interface { type Map interface {
// Len reports the number of elements in the map. // Len reports the number of elements in the map.
Len() int Len() int

View File

@ -0,0 +1,168 @@
// Copyright 2022 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 protoreflect
import (
"bytes"
"fmt"
"math"
"reflect"
"google.golang.org/protobuf/encoding/protowire"
)
// Equal reports whether v1 and v2 are recursively equal.
//
// - Values of different types are always unequal.
//
// - Bytes values are equal if they contain identical bytes.
// Empty bytes (regardless of nil-ness) are considered equal.
//
// - Floating point values are equal if they contain the same value.
// Unlike the == operator, a NaN is equal to another NaN.
//
// - Enums are equal if they contain the same number.
// Since [Value] does not contain an enum descriptor,
// enum values do not consider the type of the enum.
//
// - Other scalar values are equal if they contain the same value.
//
// - [Message] values are equal if they belong to the same message descriptor,
// have the same set of populated known and extension field values,
// and the same set of unknown fields values.
//
// - [List] values are equal if they are the same length and
// each corresponding element is equal.
//
// - [Map] values are equal if they have the same set of keys and
// the corresponding value for each key is equal.
func (v1 Value) Equal(v2 Value) bool {
return equalValue(v1, v2)
}
func equalValue(x, y Value) bool {
eqType := x.typ == y.typ
switch x.typ {
case nilType:
return eqType
case boolType:
return eqType && x.Bool() == y.Bool()
case int32Type, int64Type:
return eqType && x.Int() == y.Int()
case uint32Type, uint64Type:
return eqType && x.Uint() == y.Uint()
case float32Type, float64Type:
return eqType && equalFloat(x.Float(), y.Float())
case stringType:
return eqType && x.String() == y.String()
case bytesType:
return eqType && bytes.Equal(x.Bytes(), y.Bytes())
case enumType:
return eqType && x.Enum() == y.Enum()
default:
switch x := x.Interface().(type) {
case Message:
y, ok := y.Interface().(Message)
return ok && equalMessage(x, y)
case List:
y, ok := y.Interface().(List)
return ok && equalList(x, y)
case Map:
y, ok := y.Interface().(Map)
return ok && equalMap(x, y)
default:
panic(fmt.Sprintf("unknown type: %T", x))
}
}
}
// equalFloat compares two floats, where NaNs are treated as equal.
func equalFloat(x, y float64) bool {
if math.IsNaN(x) || math.IsNaN(y) {
return math.IsNaN(x) && math.IsNaN(y)
}
return x == y
}
// equalMessage compares two messages.
func equalMessage(mx, my Message) bool {
if mx.Descriptor() != my.Descriptor() {
return false
}
nx := 0
equal := true
mx.Range(func(fd FieldDescriptor, vx Value) bool {
nx++
vy := my.Get(fd)
equal = my.Has(fd) && equalValue(vx, vy)
return equal
})
if !equal {
return false
}
ny := 0
my.Range(func(fd FieldDescriptor, vx Value) bool {
ny++
return true
})
if nx != ny {
return false
}
return equalUnknown(mx.GetUnknown(), my.GetUnknown())
}
// equalList compares two lists.
func equalList(x, y List) bool {
if x.Len() != y.Len() {
return false
}
for i := x.Len() - 1; i >= 0; i-- {
if !equalValue(x.Get(i), y.Get(i)) {
return false
}
}
return true
}
// equalMap compares two maps.
func equalMap(x, y Map) bool {
if x.Len() != y.Len() {
return false
}
equal := true
x.Range(func(k MapKey, vx Value) bool {
vy := y.Get(k)
equal = y.Has(k) && equalValue(vx, vy)
return equal
})
return equal
}
// equalUnknown compares unknown fields by direct comparison on the raw bytes
// of each individual field number.
func equalUnknown(x, y RawFields) bool {
if len(x) != len(y) {
return false
}
if bytes.Equal([]byte(x), []byte(y)) {
return true
}
mx := make(map[FieldNumber]RawFields)
my := make(map[FieldNumber]RawFields)
for len(x) > 0 {
fnum, _, n := protowire.ConsumeField(x)
mx[fnum] = append(mx[fnum], x[:n]...)
x = x[n:]
}
for len(y) > 0 {
fnum, _, n := protowire.ConsumeField(y)
my[fnum] = append(my[fnum], y[:n]...)
y = y[n:]
}
return reflect.DeepEqual(mx, my)
}

View File

@ -11,7 +11,7 @@ import (
// Value is a union where only one Go type may be set at a time. // Value is a union where only one Go type may be set at a time.
// The Value is used to represent all possible values a field may take. // The Value is used to represent all possible values a field may take.
// The following shows which Go type is used to represent each proto Kind: // The following shows which Go type is used to represent each proto [Kind]:
// //
// ╔════════════╤═════════════════════════════════════╗ // ╔════════════╤═════════════════════════════════════╗
// ║ Go type │ Protobuf kind ║ // ║ Go type │ Protobuf kind ║
@ -31,22 +31,22 @@ import (
// //
// Multiple protobuf Kinds may be represented by a single Go type if the type // Multiple protobuf Kinds may be represented by a single Go type if the type
// can losslessly represent the information for the proto kind. For example, // can losslessly represent the information for the proto kind. For example,
// Int64Kind, Sint64Kind, and Sfixed64Kind are all represented by int64, // [Int64Kind], [Sint64Kind], and [Sfixed64Kind] are all represented by int64,
// but use different integer encoding methods. // but use different integer encoding methods.
// //
// The List or Map types are used if the field cardinality is repeated. // The [List] or [Map] types are used if the field cardinality is repeated.
// A field is a List if FieldDescriptor.IsList reports true. // A field is a [List] if [FieldDescriptor.IsList] reports true.
// A field is a Map if FieldDescriptor.IsMap reports true. // A field is a [Map] if [FieldDescriptor.IsMap] reports true.
// //
// Converting to/from a Value and a concrete Go value panics on type mismatch. // Converting to/from a Value and a concrete Go value panics on type mismatch.
// For example, ValueOf("hello").Int() panics because this attempts to // For example, [ValueOf]("hello").Int() panics because this attempts to
// retrieve an int64 from a string. // retrieve an int64 from a string.
// //
// List, Map, and Message Values are called "composite" values. // [List], [Map], and [Message] Values are called "composite" values.
// //
// A composite Value may alias (reference) memory at some location, // A composite Value may alias (reference) memory at some location,
// such that changes to the Value updates the that location. // such that changes to the Value updates the that location.
// A composite value acquired with a Mutable method, such as Message.Mutable, // A composite value acquired with a Mutable method, such as [Message.Mutable],
// always references the source object. // always references the source object.
// //
// For example: // For example:
@ -54,18 +54,18 @@ import (
// // Append a 0 to a "repeated int32" field. // // Append a 0 to a "repeated int32" field.
// // Since the Value returned by Mutable is guaranteed to alias // // Since the Value returned by Mutable is guaranteed to alias
// // the source message, modifying the Value modifies the message. // // the source message, modifying the Value modifies the message.
// message.Mutable(fieldDesc).(List).Append(protoreflect.ValueOfInt32(0)) // message.Mutable(fieldDesc).List().Append(protoreflect.ValueOfInt32(0))
// //
// // Assign [0] to a "repeated int32" field by creating a new Value, // // Assign [0] to a "repeated int32" field by creating a new Value,
// // modifying it, and assigning it. // // modifying it, and assigning it.
// list := message.NewField(fieldDesc).(List) // list := message.NewField(fieldDesc).List()
// list.Append(protoreflect.ValueOfInt32(0)) // list.Append(protoreflect.ValueOfInt32(0))
// message.Set(fieldDesc, list) // message.Set(fieldDesc, list)
// // ERROR: Since it is not defined whether Set aliases the source, // // ERROR: Since it is not defined whether Set aliases the source,
// // appending to the List here may or may not modify the message. // // appending to the List here may or may not modify the message.
// list.Append(protoreflect.ValueOfInt32(0)) // list.Append(protoreflect.ValueOfInt32(0))
// //
// Some operations, such as Message.Get, may return an "empty, read-only" // Some operations, such as [Message.Get], may return an "empty, read-only"
// composite Value. Modifying an empty, read-only value panics. // composite Value. Modifying an empty, read-only value panics.
type Value value type Value value
@ -306,7 +306,7 @@ func (v Value) Float() float64 {
} }
} }
// String returns v as a string. Since this method implements fmt.Stringer, // String returns v as a string. Since this method implements [fmt.Stringer],
// this returns the formatted string value for any non-string type. // this returns the formatted string value for any non-string type.
func (v Value) String() string { func (v Value) String() string {
switch v.typ { switch v.typ {
@ -327,7 +327,7 @@ func (v Value) Bytes() []byte {
} }
} }
// Enum returns v as a EnumNumber and panics if the type is not a EnumNumber. // Enum returns v as a [EnumNumber] and panics if the type is not a [EnumNumber].
func (v Value) Enum() EnumNumber { func (v Value) Enum() EnumNumber {
switch v.typ { switch v.typ {
case enumType: case enumType:
@ -337,7 +337,7 @@ func (v Value) Enum() EnumNumber {
} }
} }
// Message returns v as a Message and panics if the type is not a Message. // Message returns v as a [Message] and panics if the type is not a [Message].
func (v Value) Message() Message { func (v Value) Message() Message {
switch vi := v.getIface().(type) { switch vi := v.getIface().(type) {
case Message: case Message:
@ -347,7 +347,7 @@ func (v Value) Message() Message {
} }
} }
// List returns v as a List and panics if the type is not a List. // List returns v as a [List] and panics if the type is not a [List].
func (v Value) List() List { func (v Value) List() List {
switch vi := v.getIface().(type) { switch vi := v.getIface().(type) {
case List: case List:
@ -357,7 +357,7 @@ func (v Value) List() List {
} }
} }
// Map returns v as a Map and panics if the type is not a Map. // Map returns v as a [Map] and panics if the type is not a [Map].
func (v Value) Map() Map { func (v Value) Map() Map {
switch vi := v.getIface().(type) { switch vi := v.getIface().(type) {
case Map: case Map:
@ -367,7 +367,7 @@ func (v Value) Map() Map {
} }
} }
// MapKey returns v as a MapKey and panics for invalid MapKey types. // MapKey returns v as a [MapKey] and panics for invalid [MapKey] types.
func (v Value) MapKey() MapKey { func (v Value) MapKey() MapKey {
switch v.typ { switch v.typ {
case boolType, int32Type, int64Type, uint32Type, uint64Type, stringType: case boolType, int32Type, int64Type, uint32Type, uint64Type, stringType:
@ -378,8 +378,8 @@ func (v Value) MapKey() MapKey {
} }
// MapKey is used to index maps, where the Go type of the MapKey must match // MapKey is used to index maps, where the Go type of the MapKey must match
// the specified key Kind (see MessageDescriptor.IsMapEntry). // the specified key [Kind] (see [MessageDescriptor.IsMapEntry]).
// The following shows what Go type is used to represent each proto Kind: // The following shows what Go type is used to represent each proto [Kind]:
// //
// ╔═════════╤═════════════════════════════════════╗ // ╔═════════╤═════════════════════════════════════╗
// ║ Go type │ Protobuf kind ║ // ║ Go type │ Protobuf kind ║
@ -392,13 +392,13 @@ func (v Value) MapKey() MapKey {
// ║ string │ StringKind ║ // ║ string │ StringKind ║
// ╚═════════╧═════════════════════════════════════╝ // ╚═════════╧═════════════════════════════════════╝
// //
// A MapKey is constructed and accessed through a Value: // A MapKey is constructed and accessed through a [Value]:
// //
// k := ValueOf("hash").MapKey() // convert string to MapKey // k := ValueOf("hash").MapKey() // convert string to MapKey
// s := k.String() // convert MapKey to string // s := k.String() // convert MapKey to string
// //
// The MapKey is a strict subset of valid types used in Value; // The MapKey is a strict subset of valid types used in [Value];
// converting a Value to a MapKey with an invalid type panics. // converting a [Value] to a MapKey with an invalid type panics.
type MapKey value type MapKey value
// IsValid reports whether k is populated with a value. // IsValid reports whether k is populated with a value.
@ -426,13 +426,13 @@ func (k MapKey) Uint() uint64 {
return Value(k).Uint() return Value(k).Uint()
} }
// String returns k as a string. Since this method implements fmt.Stringer, // String returns k as a string. Since this method implements [fmt.Stringer],
// this returns the formatted string value for any non-string type. // this returns the formatted string value for any non-string type.
func (k MapKey) String() string { func (k MapKey) String() string {
return Value(k).String() return Value(k).String()
} }
// Value returns k as a Value. // Value returns k as a [Value].
func (k MapKey) Value() Value { func (k MapKey) Value() Value {
return Value(k) return Value(k)
} }

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !purego && !appengine //go:build !purego && !appengine && !go1.21
// +build !purego,!appengine // +build !purego,!appengine,!go1.21
package protoreflect package protoreflect

View File

@ -0,0 +1,87 @@
// Copyright 2018 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.
//go:build !purego && !appengine && go1.21
// +build !purego,!appengine,go1.21
package protoreflect
import (
"unsafe"
"google.golang.org/protobuf/internal/pragma"
)
type (
ifaceHeader struct {
_ [0]interface{} // if interfaces have greater alignment than unsafe.Pointer, this will enforce it.
Type unsafe.Pointer
Data unsafe.Pointer
}
)
var (
nilType = typeOf(nil)
boolType = typeOf(*new(bool))
int32Type = typeOf(*new(int32))
int64Type = typeOf(*new(int64))
uint32Type = typeOf(*new(uint32))
uint64Type = typeOf(*new(uint64))
float32Type = typeOf(*new(float32))
float64Type = typeOf(*new(float64))
stringType = typeOf(*new(string))
bytesType = typeOf(*new([]byte))
enumType = typeOf(*new(EnumNumber))
)
// typeOf returns a pointer to the Go type information.
// The pointer is comparable and equal if and only if the types are identical.
func typeOf(t interface{}) unsafe.Pointer {
return (*ifaceHeader)(unsafe.Pointer(&t)).Type
}
// value is a union where only one type can be represented at a time.
// The struct is 24B large on 64-bit systems and requires the minimum storage
// necessary to represent each possible type.
//
// The Go GC needs to be able to scan variables containing pointers.
// As such, pointers and non-pointers cannot be intermixed.
type value struct {
pragma.DoNotCompare // 0B
// typ stores the type of the value as a pointer to the Go type.
typ unsafe.Pointer // 8B
// ptr stores the data pointer for a String, Bytes, or interface value.
ptr unsafe.Pointer // 8B
// num stores a Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, or
// Enum value as a raw uint64.
//
// It is also used to store the length of a String or Bytes value;
// the capacity is ignored.
num uint64 // 8B
}
func valueOfString(v string) Value {
return Value{typ: stringType, ptr: unsafe.Pointer(unsafe.StringData(v)), num: uint64(len(v))}
}
func valueOfBytes(v []byte) Value {
return Value{typ: bytesType, ptr: unsafe.Pointer(unsafe.SliceData(v)), num: uint64(len(v))}
}
func valueOfIface(v interface{}) Value {
p := (*ifaceHeader)(unsafe.Pointer(&v))
return Value{typ: p.Type, ptr: p.Data}
}
func (v Value) getString() string {
return unsafe.String((*byte)(v.ptr), v.num)
}
func (v Value) getBytes() []byte {
return unsafe.Slice((*byte)(v.ptr), v.num)
}
func (v Value) getIface() (x interface{}) {
*(*ifaceHeader)(unsafe.Pointer(&x)) = ifaceHeader{Type: v.typ, Data: v.ptr}
return x
}

View File

@ -5,12 +5,12 @@
// Package protoregistry provides data structures to register and lookup // Package protoregistry provides data structures to register and lookup
// protobuf descriptor types. // protobuf descriptor types.
// //
// The Files registry contains file descriptors and provides the ability // The [Files] registry contains file descriptors and provides the ability
// to iterate over the files or lookup a specific descriptor within the files. // to iterate over the files or lookup a specific descriptor within the files.
// Files only contains protobuf descriptors and has no understanding of Go // [Files] only contains protobuf descriptors and has no understanding of Go
// type information that may be associated with each descriptor. // type information that may be associated with each descriptor.
// //
// The Types registry contains descriptor types for which there is a known // The [Types] registry contains descriptor types for which there is a known
// Go type associated with that descriptor. It provides the ability to iterate // Go type associated with that descriptor. It provides the ability to iterate
// over the registered types or lookup a type by name. // over the registered types or lookup a type by name.
package protoregistry package protoregistry
@ -46,7 +46,7 @@ var conflictPolicy = "panic" // "panic" | "warn" | "ignore"
// It is a variable so that the behavior is easily overridden in another file. // It is a variable so that the behavior is easily overridden in another file.
var ignoreConflict = func(d protoreflect.Descriptor, err error) bool { var ignoreConflict = func(d protoreflect.Descriptor, err error) bool {
const env = "GOLANG_PROTOBUF_REGISTRATION_CONFLICT" const env = "GOLANG_PROTOBUF_REGISTRATION_CONFLICT"
const faq = "https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict" const faq = "https://protobuf.dev/reference/go/faq#namespace-conflict"
policy := conflictPolicy policy := conflictPolicy
if v := os.Getenv(env); v != "" { if v := os.Getenv(env); v != "" {
policy = v policy = v
@ -218,7 +218,7 @@ func (r *Files) checkGenProtoConflict(path string) {
// FindDescriptorByName looks up a descriptor by the full name. // FindDescriptorByName looks up a descriptor by the full name.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Files) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) { func (r *Files) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound
@ -310,7 +310,7 @@ func (s *nameSuffix) Pop() (name protoreflect.Name) {
// FindFileByPath looks up a file by the path. // FindFileByPath looks up a file by the path.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
// This returns an error if multiple files have the same path. // This returns an error if multiple files have the same path.
func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) { func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
if r == nil { if r == nil {
@ -431,7 +431,7 @@ func rangeTopLevelDescriptors(fd protoreflect.FileDescriptor, f func(protoreflec
// A compliant implementation must deterministically return the same type // A compliant implementation must deterministically return the same type
// if no error is encountered. // if no error is encountered.
// //
// The Types type implements this interface. // The [Types] type implements this interface.
type MessageTypeResolver interface { type MessageTypeResolver interface {
// FindMessageByName looks up a message by its full name. // FindMessageByName looks up a message by its full name.
// E.g., "google.protobuf.Any" // E.g., "google.protobuf.Any"
@ -451,7 +451,7 @@ type MessageTypeResolver interface {
// A compliant implementation must deterministically return the same type // A compliant implementation must deterministically return the same type
// if no error is encountered. // if no error is encountered.
// //
// The Types type implements this interface. // The [Types] type implements this interface.
type ExtensionTypeResolver interface { type ExtensionTypeResolver interface {
// FindExtensionByName looks up a extension field by the field's full name. // FindExtensionByName looks up a extension field by the field's full name.
// Note that this is the full name of the field as determined by // Note that this is the full name of the field as determined by
@ -590,7 +590,7 @@ func (r *Types) register(kind string, desc protoreflect.Descriptor, typ interfac
// FindEnumByName looks up an enum by its full name. // FindEnumByName looks up an enum by its full name.
// E.g., "google.protobuf.Field.Kind". // E.g., "google.protobuf.Field.Kind".
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) { func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound
@ -611,7 +611,7 @@ func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumTyp
// FindMessageByName looks up a message by its full name, // FindMessageByName looks up a message by its full name,
// e.g. "google.protobuf.Any". // e.g. "google.protobuf.Any".
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) { func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound
@ -632,7 +632,7 @@ func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.M
// FindMessageByURL looks up a message by a URL identifier. // FindMessageByURL looks up a message by a URL identifier.
// See documentation on google.protobuf.Any.type_url for the URL format. // See documentation on google.protobuf.Any.type_url for the URL format.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) { func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
// This function is similar to FindMessageByName but // This function is similar to FindMessageByName but
// truncates anything before and including '/' in the URL. // truncates anything before and including '/' in the URL.
@ -662,7 +662,7 @@ func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
// where the extension is declared and is unrelated to the full name of the // where the extension is declared and is unrelated to the full name of the
// message being extended. // message being extended.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) { func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound
@ -703,7 +703,7 @@ func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.E
// FindExtensionByNumber looks up a extension field by the field number // FindExtensionByNumber looks up a extension field by the field number
// within some parent message, identified by full name. // within some parent message, identified by full name.
// //
// This returns (nil, NotFound) if not found. // This returns (nil, [NotFound]) if not found.
func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) { func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
if r == nil { if r == nil {
return nil, NotFound return nil, NotFound

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: reflect/protodesc/proto/go_features.proto
package proto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
descriptorpb "google.golang.org/protobuf/types/descriptorpb"
reflect "reflect"
sync "sync"
)
type GoFeatures struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Whether or not to generate the deprecated UnmarshalJSON method for enums.
LegacyUnmarshalJsonEnum *bool `protobuf:"varint,1,opt,name=legacy_unmarshal_json_enum,json=legacyUnmarshalJsonEnum" json:"legacy_unmarshal_json_enum,omitempty"`
}
func (x *GoFeatures) Reset() {
*x = GoFeatures{}
if protoimpl.UnsafeEnabled {
mi := &file_reflect_protodesc_proto_go_features_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GoFeatures) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GoFeatures) ProtoMessage() {}
func (x *GoFeatures) ProtoReflect() protoreflect.Message {
mi := &file_reflect_protodesc_proto_go_features_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 GoFeatures.ProtoReflect.Descriptor instead.
func (*GoFeatures) Descriptor() ([]byte, []int) {
return file_reflect_protodesc_proto_go_features_proto_rawDescGZIP(), []int{0}
}
func (x *GoFeatures) GetLegacyUnmarshalJsonEnum() bool {
if x != nil && x.LegacyUnmarshalJsonEnum != nil {
return *x.LegacyUnmarshalJsonEnum
}
return false
}
var file_reflect_protodesc_proto_go_features_proto_extTypes = []protoimpl.ExtensionInfo{
{
ExtendedType: (*descriptorpb.FeatureSet)(nil),
ExtensionType: (*GoFeatures)(nil),
Field: 1002,
Name: "google.protobuf.go",
Tag: "bytes,1002,opt,name=go",
Filename: "reflect/protodesc/proto/go_features.proto",
},
}
// Extension fields to descriptorpb.FeatureSet.
var (
// optional google.protobuf.GoFeatures go = 1002;
E_Go = &file_reflect_protodesc_proto_go_features_proto_extTypes[0]
)
var File_reflect_protodesc_proto_go_features_proto protoreflect.FileDescriptor
var file_reflect_protodesc_proto_go_features_proto_rawDesc = []byte{
0x0a, 0x29, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x64,
0x65, 0x73, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x5f, 0x66, 0x65, 0x61,
0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x1a, 0x20, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a,
0x0a, 0x0a, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x1a,
0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x75, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c,
0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
0x42, 0x1f, 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x74, 0x72, 0x75,
0x65, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0a, 0x12, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x18, 0xe7,
0x07, 0x52, 0x17, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68,
0x61, 0x6c, 0x4a, 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x3a, 0x49, 0x0a, 0x02, 0x67, 0x6f,
0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x18, 0xea, 0x07,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
0x73, 0x52, 0x02, 0x67, 0x6f, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x64, 0x65, 0x73, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
file_reflect_protodesc_proto_go_features_proto_rawDescOnce sync.Once
file_reflect_protodesc_proto_go_features_proto_rawDescData = file_reflect_protodesc_proto_go_features_proto_rawDesc
)
func file_reflect_protodesc_proto_go_features_proto_rawDescGZIP() []byte {
file_reflect_protodesc_proto_go_features_proto_rawDescOnce.Do(func() {
file_reflect_protodesc_proto_go_features_proto_rawDescData = protoimpl.X.CompressGZIP(file_reflect_protodesc_proto_go_features_proto_rawDescData)
})
return file_reflect_protodesc_proto_go_features_proto_rawDescData
}
var file_reflect_protodesc_proto_go_features_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_reflect_protodesc_proto_go_features_proto_goTypes = []interface{}{
(*GoFeatures)(nil), // 0: google.protobuf.GoFeatures
(*descriptorpb.FeatureSet)(nil), // 1: google.protobuf.FeatureSet
}
var file_reflect_protodesc_proto_go_features_proto_depIdxs = []int32{
1, // 0: google.protobuf.go:extendee -> google.protobuf.FeatureSet
0, // 1: google.protobuf.go:type_name -> google.protobuf.GoFeatures
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
1, // [1:2] is the sub-list for extension type_name
0, // [0:1] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_reflect_protodesc_proto_go_features_proto_init() }
func file_reflect_protodesc_proto_go_features_proto_init() {
if File_reflect_protodesc_proto_go_features_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_reflect_protodesc_proto_go_features_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GoFeatures); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_reflect_protodesc_proto_go_features_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 1,
NumServices: 0,
},
GoTypes: file_reflect_protodesc_proto_go_features_proto_goTypes,
DependencyIndexes: file_reflect_protodesc_proto_go_features_proto_depIdxs,
MessageInfos: file_reflect_protodesc_proto_go_features_proto_msgTypes,
ExtensionInfos: file_reflect_protodesc_proto_go_features_proto_extTypes,
}.Build()
File_reflect_protodesc_proto_go_features_proto = out.File
file_reflect_protodesc_proto_go_features_proto_rawDesc = nil
file_reflect_protodesc_proto_go_features_proto_goTypes = nil
file_reflect_protodesc_proto_go_features_proto_depIdxs = nil
}

View File

@ -0,0 +1,28 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
syntax = "proto2";
package google.protobuf;
import "google/protobuf/descriptor.proto";
option go_package = "google.golang.org/protobuf/types/gofeaturespb";
extend google.protobuf.FeatureSet {
optional GoFeatures go = 1002;
}
message GoFeatures {
// Whether or not to generate the deprecated UnmarshalJSON method for enums.
optional bool legacy_unmarshal_json_enum = 1 [
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_ENUM,
edition_defaults = { edition: EDITION_PROTO2, value: "true" },
edition_defaults = { edition: EDITION_PROTO3, value: "false" }
];
}

View File

@ -37,8 +37,7 @@
// It is functionally a tuple of the full name of the remote message type and // It is functionally a tuple of the full name of the remote message type and
// the serialized bytes of the remote message value. // the serialized bytes of the remote message value.
// //
// // # Constructing an Any
// Constructing an Any
// //
// An Any message containing another message value is constructed using New: // An Any message containing another message value is constructed using New:
// //
@ -48,8 +47,7 @@
// } // }
// ... // make use of any // ... // make use of any
// //
// // # Unmarshaling an Any
// Unmarshaling an Any
// //
// With a populated Any message, the underlying message can be serialized into // With a populated Any message, the underlying message can be serialized into
// a remote concrete message value in a few ways. // a remote concrete message value in a few ways.
@ -95,8 +93,7 @@
// listed in the case clauses are linked into the Go binary and therefore also // listed in the case clauses are linked into the Go binary and therefore also
// registered in the global registry. // registered in the global registry.
// //
// // # Type checking an Any
// Type checking an Any
// //
// In order to type check whether an Any message represents some other message, // In order to type check whether an Any message represents some other message,
// then use the MessageIs method: // then use the MessageIs method:
@ -115,7 +112,6 @@
// } // }
// ... // make use of m // ... // make use of m
// } // }
//
package anypb package anypb
import ( import (
@ -136,45 +132,49 @@ import (
// //
// Example 1: Pack and unpack a message in C++. // Example 1: Pack and unpack a message in C++.
// //
// Foo foo = ...; // Foo foo = ...;
// Any any; // Any any;
// any.PackFrom(foo); // any.PackFrom(foo);
// ... // ...
// if (any.UnpackTo(&foo)) { // if (any.UnpackTo(&foo)) {
// ... // ...
// } // }
// //
// Example 2: Pack and unpack a message in Java. // Example 2: Pack and unpack a message in Java.
// //
// Foo foo = ...; // Foo foo = ...;
// Any any = Any.pack(foo); // Any any = Any.pack(foo);
// ... // ...
// if (any.is(Foo.class)) { // if (any.is(Foo.class)) {
// foo = any.unpack(Foo.class); // foo = any.unpack(Foo.class);
// } // }
// // or ...
// if (any.isSameTypeAs(Foo.getDefaultInstance())) {
// foo = any.unpack(Foo.getDefaultInstance());
// }
// //
// Example 3: Pack and unpack a message in Python. // Example 3: Pack and unpack a message in Python.
// //
// foo = Foo(...) // foo = Foo(...)
// any = Any() // any = Any()
// any.Pack(foo) // any.Pack(foo)
// ... // ...
// if any.Is(Foo.DESCRIPTOR): // if any.Is(Foo.DESCRIPTOR):
// any.Unpack(foo) // any.Unpack(foo)
// ... // ...
// //
// Example 4: Pack and unpack a message in Go // Example 4: Pack and unpack a message in Go
// //
// foo := &pb.Foo{...} // foo := &pb.Foo{...}
// any, err := anypb.New(foo) // any, err := anypb.New(foo)
// if err != nil { // if err != nil {
// ... // ...
// } // }
// ... // ...
// foo := &pb.Foo{} // foo := &pb.Foo{}
// if err := any.UnmarshalTo(foo); err != nil { // if err := any.UnmarshalTo(foo); err != nil {
// ... // ...
// } // }
// //
// The pack methods provided by protobuf library will by default use // The pack methods provided by protobuf library will by default use
// 'type.googleapis.com/full.type.name' as the type URL and the unpack // 'type.googleapis.com/full.type.name' as the type URL and the unpack
@ -182,35 +182,33 @@ import (
// in the type URL, for example "foo.bar.com/x/y.z" will yield type // in the type URL, for example "foo.bar.com/x/y.z" will yield type
// name "y.z". // name "y.z".
// //
//
// JSON // JSON
// ==== // ====
// The JSON representation of an `Any` value uses the regular // The JSON representation of an `Any` value uses the regular
// representation of the deserialized, embedded message, with an // representation of the deserialized, embedded message, with an
// additional field `@type` which contains the type URL. Example: // additional field `@type` which contains the type URL. Example:
// //
// package google.profile; // package google.profile;
// message Person { // message Person {
// string first_name = 1; // string first_name = 1;
// string last_name = 2; // string last_name = 2;
// } // }
// //
// { // {
// "@type": "type.googleapis.com/google.profile.Person", // "@type": "type.googleapis.com/google.profile.Person",
// "firstName": <string>, // "firstName": <string>,
// "lastName": <string> // "lastName": <string>
// } // }
// //
// If the embedded message type is well-known and has a custom JSON // If the embedded message type is well-known and has a custom JSON
// representation, that representation will be embedded adding a field // representation, that representation will be embedded adding a field
// `value` which holds the custom JSON in addition to the `@type` // `value` which holds the custom JSON in addition to the `@type`
// field. Example (for message [google.protobuf.Duration][]): // field. Example (for message [google.protobuf.Duration][]):
// //
// { // {
// "@type": "type.googleapis.com/google.protobuf.Duration", // "@type": "type.googleapis.com/google.protobuf.Duration",
// "value": "1.212s" // "value": "1.212s"
// } // }
//
type Any struct { type Any struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -228,22 +226,22 @@ type Any struct {
// scheme `http`, `https`, or no scheme, one can optionally set up a type // scheme `http`, `https`, or no scheme, one can optionally set up a type
// server that maps type URLs to message definitions as follows: // server that maps type URLs to message definitions as follows:
// //
// * If no scheme is provided, `https` is assumed. // - If no scheme is provided, `https` is assumed.
// * An HTTP GET on the URL must yield a [google.protobuf.Type][] // - An HTTP GET on the URL must yield a [google.protobuf.Type][]
// value in binary format, or produce an error. // value in binary format, or produce an error.
// * Applications are allowed to cache lookup results based on the // - Applications are allowed to cache lookup results based on the
// URL, or have them precompiled into a binary to avoid any // URL, or have them precompiled into a binary to avoid any
// lookup. Therefore, binary compatibility needs to be preserved // lookup. Therefore, binary compatibility needs to be preserved
// on changes to types. (Use versioned type names to manage // on changes to types. (Use versioned type names to manage
// breaking changes.) // breaking changes.)
// //
// Note: this functionality is not currently available in the official // Note: this functionality is not currently available in the official
// protobuf release, and it is not used for type URLs beginning with // protobuf release, and it is not used for type URLs beginning with
// type.googleapis.com. // type.googleapis.com. As of May 2023, there are no widely used type server
// implementations and no plans to implement one.
// //
// Schemes other than `http`, `https` (or the empty scheme) might be // Schemes other than `http`, `https` (or the empty scheme) might be
// used with implementation specific semantics. // used with implementation specific semantics.
//
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`
// Must be a valid serialized protocol buffer of the above specified type. // Must be a valid serialized protocol buffer of the above specified type.
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`

View File

@ -35,8 +35,7 @@
// //
// The Duration message represents a signed span of time. // The Duration message represents a signed span of time.
// //
// // # Conversion to a Go Duration
// Conversion to a Go Duration
// //
// The AsDuration method can be used to convert a Duration message to a // The AsDuration method can be used to convert a Duration message to a
// standard Go time.Duration value: // standard Go time.Duration value:
@ -65,15 +64,13 @@
// the resulting value to the closest representable value (e.g., math.MaxInt64 // the resulting value to the closest representable value (e.g., math.MaxInt64
// for positive overflow and math.MinInt64 for negative overflow). // for positive overflow and math.MinInt64 for negative overflow).
// //
// // # Conversion from a Go Duration
// Conversion from a Go Duration
// //
// The durationpb.New function can be used to construct a Duration message // The durationpb.New function can be used to construct a Duration message
// from a standard Go time.Duration value: // from a standard Go time.Duration value:
// //
// dur := durationpb.New(d) // dur := durationpb.New(d)
// ... // make use of d as a *durationpb.Duration // ... // make use of d as a *durationpb.Duration
//
package durationpb package durationpb
import ( import (
@ -96,43 +93,43 @@ import (
// //
// Example 1: Compute Duration from two Timestamps in pseudo code. // Example 1: Compute Duration from two Timestamps in pseudo code.
// //
// Timestamp start = ...; // Timestamp start = ...;
// Timestamp end = ...; // Timestamp end = ...;
// Duration duration = ...; // Duration duration = ...;
// //
// duration.seconds = end.seconds - start.seconds; // duration.seconds = end.seconds - start.seconds;
// duration.nanos = end.nanos - start.nanos; // duration.nanos = end.nanos - start.nanos;
// //
// if (duration.seconds < 0 && duration.nanos > 0) { // if (duration.seconds < 0 && duration.nanos > 0) {
// duration.seconds += 1; // duration.seconds += 1;
// duration.nanos -= 1000000000; // duration.nanos -= 1000000000;
// } else if (duration.seconds > 0 && duration.nanos < 0) { // } else if (duration.seconds > 0 && duration.nanos < 0) {
// duration.seconds -= 1; // duration.seconds -= 1;
// duration.nanos += 1000000000; // duration.nanos += 1000000000;
// } // }
// //
// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. // Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
// //
// Timestamp start = ...; // Timestamp start = ...;
// Duration duration = ...; // Duration duration = ...;
// Timestamp end = ...; // Timestamp end = ...;
// //
// end.seconds = start.seconds + duration.seconds; // end.seconds = start.seconds + duration.seconds;
// end.nanos = start.nanos + duration.nanos; // end.nanos = start.nanos + duration.nanos;
// //
// if (end.nanos < 0) { // if (end.nanos < 0) {
// end.seconds -= 1; // end.seconds -= 1;
// end.nanos += 1000000000; // end.nanos += 1000000000;
// } else if (end.nanos >= 1000000000) { // } else if (end.nanos >= 1000000000) {
// end.seconds += 1; // end.seconds += 1;
// end.nanos -= 1000000000; // end.nanos -= 1000000000;
// } // }
// //
// Example 3: Compute Duration from datetime.timedelta in Python. // Example 3: Compute Duration from datetime.timedelta in Python.
// //
// td = datetime.timedelta(days=3, minutes=10) // td = datetime.timedelta(days=3, minutes=10)
// duration = Duration() // duration = Duration()
// duration.FromTimedelta(td) // duration.FromTimedelta(td)
// //
// # JSON Mapping // # JSON Mapping
// //
@ -143,8 +140,6 @@ import (
// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should // encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 // be expressed in JSON format as "3.000000001s", and 3 seconds and 1
// microsecond should be expressed in JSON format as "3.000001s". // microsecond should be expressed in JSON format as "3.000001s".
//
//
type Duration struct { type Duration struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache

View File

@ -44,11 +44,9 @@ import (
// empty messages in your APIs. A typical example is to use it as the request // empty messages in your APIs. A typical example is to use it as the request
// or the response type of an API method. For instance: // or the response type of an API method. For instance:
// //
// service Foo { // service Foo {
// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); // rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
// } // }
//
// The JSON representation for `Empty` is empty JSON object `{}`.
type Empty struct { type Empty struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache

View File

@ -36,8 +36,7 @@
// The Timestamp message represents a timestamp, // The Timestamp message represents a timestamp,
// an instant in time since the Unix epoch (January 1st, 1970). // an instant in time since the Unix epoch (January 1st, 1970).
// //
// // # Conversion to a Go Time
// Conversion to a Go Time
// //
// The AsTime method can be used to convert a Timestamp message to a // The AsTime method can be used to convert a Timestamp message to a
// standard Go time.Time value in UTC: // standard Go time.Time value in UTC:
@ -59,8 +58,7 @@
// ... // handle error // ... // handle error
// } // }
// //
// // # Conversion from a Go Time
// Conversion from a Go Time
// //
// The timestamppb.New function can be used to construct a Timestamp message // The timestamppb.New function can be used to construct a Timestamp message
// from a standard Go time.Time value: // from a standard Go time.Time value:
@ -72,7 +70,6 @@
// //
// ts := timestamppb.Now() // ts := timestamppb.Now()
// ... // make use of ts as a *timestamppb.Timestamp // ... // make use of ts as a *timestamppb.Timestamp
//
package timestamppb package timestamppb
import ( import (
@ -101,52 +98,50 @@ import (
// //
// Example 1: Compute Timestamp from POSIX `time()`. // Example 1: Compute Timestamp from POSIX `time()`.
// //
// Timestamp timestamp; // Timestamp timestamp;
// timestamp.set_seconds(time(NULL)); // timestamp.set_seconds(time(NULL));
// timestamp.set_nanos(0); // timestamp.set_nanos(0);
// //
// Example 2: Compute Timestamp from POSIX `gettimeofday()`. // Example 2: Compute Timestamp from POSIX `gettimeofday()`.
// //
// struct timeval tv; // struct timeval tv;
// gettimeofday(&tv, NULL); // gettimeofday(&tv, NULL);
// //
// Timestamp timestamp; // Timestamp timestamp;
// timestamp.set_seconds(tv.tv_sec); // timestamp.set_seconds(tv.tv_sec);
// timestamp.set_nanos(tv.tv_usec * 1000); // timestamp.set_nanos(tv.tv_usec * 1000);
// //
// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. // Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
// //
// FILETIME ft; // FILETIME ft;
// GetSystemTimeAsFileTime(&ft); // GetSystemTimeAsFileTime(&ft);
// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; // UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
// //
// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z // // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. // // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
// Timestamp timestamp; // Timestamp timestamp;
// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); // timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); // timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
// //
// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. // Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
// //
// long millis = System.currentTimeMillis(); // long millis = System.currentTimeMillis();
//
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
// .setNanos((int) ((millis % 1000) * 1000000)).build();
// //
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
// .setNanos((int) ((millis % 1000) * 1000000)).build();
// //
// Example 5: Compute Timestamp from Java `Instant.now()`. // Example 5: Compute Timestamp from Java `Instant.now()`.
// //
// Instant now = Instant.now(); // Instant now = Instant.now();
//
// Timestamp timestamp =
// Timestamp.newBuilder().setSeconds(now.getEpochSecond())
// .setNanos(now.getNano()).build();
// //
// Timestamp timestamp =
// Timestamp.newBuilder().setSeconds(now.getEpochSecond())
// .setNanos(now.getNano()).build();
// //
// Example 6: Compute Timestamp from current time in Python. // Example 6: Compute Timestamp from current time in Python.
// //
// timestamp = Timestamp() // timestamp = Timestamp()
// timestamp.GetCurrentTime() // timestamp.GetCurrentTime()
// //
// # JSON Mapping // # JSON Mapping
// //
@ -172,10 +167,8 @@ import (
// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with // [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use // the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
// the Joda Time's [`ISODateTimeFormat.dateTime()`]( // the Joda Time's [`ISODateTimeFormat.dateTime()`](
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D // http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()
// ) to obtain a formatter capable of generating timestamps in this format. // ) to obtain a formatter capable of generating timestamps in this format.
//
//
type Timestamp struct { type Timestamp struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache

6
vendor/modules.txt vendored
View File

@ -841,14 +841,15 @@ google.golang.org/grpc/serviceconfig
google.golang.org/grpc/stats google.golang.org/grpc/stats
google.golang.org/grpc/status google.golang.org/grpc/status
google.golang.org/grpc/tap google.golang.org/grpc/tap
# google.golang.org/protobuf v1.28.1 # google.golang.org/protobuf v1.33.0
## explicit; go 1.11 ## explicit; go 1.17
google.golang.org/protobuf/encoding/protojson google.golang.org/protobuf/encoding/protojson
google.golang.org/protobuf/encoding/prototext google.golang.org/protobuf/encoding/prototext
google.golang.org/protobuf/encoding/protowire google.golang.org/protobuf/encoding/protowire
google.golang.org/protobuf/internal/descfmt google.golang.org/protobuf/internal/descfmt
google.golang.org/protobuf/internal/descopts google.golang.org/protobuf/internal/descopts
google.golang.org/protobuf/internal/detrand google.golang.org/protobuf/internal/detrand
google.golang.org/protobuf/internal/editiondefaults
google.golang.org/protobuf/internal/encoding/defval google.golang.org/protobuf/internal/encoding/defval
google.golang.org/protobuf/internal/encoding/json google.golang.org/protobuf/internal/encoding/json
google.golang.org/protobuf/internal/encoding/messageset google.golang.org/protobuf/internal/encoding/messageset
@ -872,6 +873,7 @@ google.golang.org/protobuf/reflect/protoregistry
google.golang.org/protobuf/runtime/protoiface google.golang.org/protobuf/runtime/protoiface
google.golang.org/protobuf/runtime/protoimpl google.golang.org/protobuf/runtime/protoimpl
google.golang.org/protobuf/types/descriptorpb google.golang.org/protobuf/types/descriptorpb
google.golang.org/protobuf/types/gofeaturespb
google.golang.org/protobuf/types/known/anypb google.golang.org/protobuf/types/known/anypb
google.golang.org/protobuf/types/known/durationpb google.golang.org/protobuf/types/known/durationpb
google.golang.org/protobuf/types/known/emptypb google.golang.org/protobuf/types/known/emptypb