Bumps google.golang.org/protobuf from 1.36.10 to 1.36.11.
---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
dependency-version: 1.36.11
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
golang.org/x/time v0.14.0
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217
google.golang.org/grpc v1.77.0
- google.golang.org/protobuf v1.36.10
+ google.golang.org/protobuf v1.36.11
gopkg.in/inf.v0 v0.9.1
k8s.io/apimachinery v0.34.3
k8s.io/client-go v0.34.3
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
-google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
+google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
+google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
return nil, fmt.Errorf("cannot use module= with paths=source_relative")
}
+ // Instead of generating each gen.Request.ProtoFile,
+ // generate gen.Request.FileToGenerate and its transitive dependencies.
+ //
+ // This effectively filters out 'import option' dependencies.
+ files := gatherTransitiveDependencies(gen.Request)
+
// Figure out the import path and package name for each file.
//
// The rules here are complicated and have grown organically over time.
//
// Alternatively, build systems which want to exert full control over
// import paths may specify M<filename>=<import_path> flags.
- for _, fdesc := range gen.Request.ProtoFile {
+ for _, fdesc := range files {
filename := fdesc.GetName()
// The "M" command-line flags take precedence over
// the "go_package" option in the .proto source file.
// The extracted types from the full import set
typeRegistry := newExtensionRegistry()
- for _, fdesc := range gen.Request.ProtoFile {
+ for _, fdesc := range files {
filename := fdesc.GetName()
if gen.FilesByPath[filename] != nil {
return nil, fmt.Errorf("duplicate file name: %q", filename)
return gen, nil
}
+type transitiveDependencies struct {
+ files map[string]*descriptorpb.FileDescriptorProto
+ deps map[string]bool
+ sortedDeps []*descriptorpb.FileDescriptorProto
+}
+
+func newTransitiveDependencies(req *pluginpb.CodeGeneratorRequest) *transitiveDependencies {
+ files := make(map[string]*descriptorpb.FileDescriptorProto)
+ for _, f := range req.GetProtoFile() {
+ files[f.GetName()] = f
+ }
+ return &transitiveDependencies{
+ files: files,
+ deps: make(map[string]bool),
+ }
+}
+
+func (td *transitiveDependencies) add(name string) {
+ if td.deps[name] {
+ return
+ }
+ f := td.files[name]
+ if f == nil {
+ // This shouldn't happen, but will fail later if it does.
+ return
+ }
+ td.deps[name] = true
+ for _, dep := range f.GetDependency() {
+ td.add(dep)
+ }
+ td.sortedDeps = append(td.sortedDeps, f)
+}
+
+func gatherTransitiveDependencies(req *pluginpb.CodeGeneratorRequest) []*descriptorpb.FileDescriptorProto {
+ if len(req.GetFileToGenerate()) == 0 {
+ return req.GetProtoFile()
+ }
+ td := newTransitiveDependencies(req)
+ for _, f := range req.GetFileToGenerate() {
+ td.add(f)
+ }
+ return td.sortedDeps
+}
+
// InternalStripForEditionsDiff returns whether or not to strip non-functional
// codegen for editions diff testing.
//
func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor {
f := new(filedesc.Field)
f.L0.ParentFile = filedesc.SurrogateProto2
- f.L1.EditionFeatures = f.L0.ParentFile.L1.EditionFeatures
+ packed := false
for len(tag) > 0 {
i := strings.IndexByte(tag, ',')
if i < 0 {
f.L1.StringName.InitJSON(jsonName)
}
case s == "packed":
- f.L1.EditionFeatures.IsPacked = true
+ packed = true
case strings.HasPrefix(s, "def="):
// The default tag is special in that everything afterwards is the
// default regardless of the presence of commas.
tag = strings.TrimPrefix(tag[i:], ",")
}
+ // Update EditionFeatures after the loop and after we know whether this is
+ // a proto2 or proto3 field.
+ f.L1.EditionFeatures = f.L0.ParentFile.L1.EditionFeatures
+ if packed {
+ f.L1.EditionFeatures.IsPacked = true
+ }
+
// The generator uses the group message name instead of the field name.
// We obtain the real field name by lowercasing the group name.
if f.L1.Kind == protoreflect.GroupKind {
return Token{}, d.newSyntaxError("invalid field name: %s", errId(d.in))
}
-// parseTypeName parses Any type URL or extension field name. The name is
-// enclosed in [ and ] characters. The C++ parser does not handle many legal URL
-// strings. This implementation is more liberal and allows for the pattern
-// ^[-_a-zA-Z0-9]+([./][-_a-zA-Z0-9]+)*`). Whitespaces and comments are allowed
-// in between [ ], '.', '/' and the sub names.
+// parseTypeName parses an Any type URL or an extension field name. The name is
+// enclosed in [ and ] characters. We allow almost arbitrary type URL prefixes,
+// closely following the text-format spec [1,2]. We implement "ExtensionName |
+// AnyName" as follows (with some exceptions for backwards compatibility):
+//
+// char = [-_a-zA-Z0-9]
+// url_char = char | [.~!$&'()*+,;=] | "%", hex, hex
+//
+// Ident = char, { char }
+// TypeName = Ident, { ".", Ident } ;
+// UrlPrefix = url_char, { url_char | "/" } ;
+// ExtensionName = "[", TypeName, "]" ;
+// AnyName = "[", UrlPrefix, "/", TypeName, "]" ;
+//
+// Additionally, we allow arbitrary whitespace and comments between [ and ].
+//
+// [1] https://protobuf.dev/reference/protobuf/textformat-spec/#characters
+// [2] https://protobuf.dev/reference/protobuf/textformat-spec/#field-names
func (d *Decoder) parseTypeName() (Token, error) {
- startPos := len(d.orig) - len(d.in)
// Use alias s to advance first in order to use d.in for error handling.
- // Caller already checks for [ as first character.
+ // Caller already checks for [ as first character (d.in[0] == '[').
s := consume(d.in[1:], 0)
if len(s) == 0 {
return Token{}, ErrUnexpectedEOF
}
+ // Collect everything between [ and ] in name.
var name []byte
- for len(s) > 0 && isTypeNameChar(s[0]) {
- name = append(name, s[0])
- s = s[1:]
- }
- s = consume(s, 0)
-
var closed bool
for len(s) > 0 && !closed {
switch {
s = s[1:]
closed = true
- case s[0] == '/', s[0] == '.':
- if len(name) > 0 && (name[len(name)-1] == '/' || name[len(name)-1] == '.') {
- return Token{}, d.newSyntaxError("invalid type URL/extension field name: %s",
- d.orig[startPos:len(d.orig)-len(s)+1])
- }
+ case s[0] == '/' || isTypeNameChar(s[0]) || isUrlExtraChar(s[0]):
name = append(name, s[0])
- s = s[1:]
- s = consume(s, 0)
- for len(s) > 0 && isTypeNameChar(s[0]) {
- name = append(name, s[0])
- s = s[1:]
+ s = consume(s[1:], 0)
+
+ // URL percent-encoded chars
+ case s[0] == '%':
+ if len(s) < 3 || !isHexChar(s[1]) || !isHexChar(s[2]) {
+ return Token{}, d.parseTypeNameError(s, 3)
}
- s = consume(s, 0)
+ name = append(name, s[0], s[1], s[2])
+ s = consume(s[3:], 0)
default:
- return Token{}, d.newSyntaxError(
- "invalid type URL/extension field name: %s", d.orig[startPos:len(d.orig)-len(s)+1])
+ return Token{}, d.parseTypeNameError(s, 1)
}
}
return Token{}, ErrUnexpectedEOF
}
- // First character cannot be '.'. Last character cannot be '.' or '/'.
- size := len(name)
- if size == 0 || name[0] == '.' || name[size-1] == '.' || name[size-1] == '/' {
- return Token{}, d.newSyntaxError("invalid type URL/extension field name: %s",
- d.orig[startPos:len(d.orig)-len(s)])
+ // Split collected name on last '/' into urlPrefix and typeName (if '/' is
+ // present).
+ typeName := name
+ if i := bytes.LastIndexByte(name, '/'); i != -1 {
+ urlPrefix := name[:i]
+ typeName = name[i+1:]
+
+ // urlPrefix may be empty (for backwards compatibility).
+ // If non-empty, it must not start with '/'.
+ if len(urlPrefix) > 0 && urlPrefix[0] == '/' {
+ return Token{}, d.parseTypeNameError(s, 0)
+ }
}
+ // typeName must not be empty (note: "" splits to [""]) and all identifier
+ // parts must not be empty.
+ for _, ident := range bytes.Split(typeName, []byte{'.'}) {
+ if len(ident) == 0 {
+ return Token{}, d.parseTypeNameError(s, 0)
+ }
+ }
+
+ // typeName must not contain any percent-encoded or special URL chars.
+ for _, b := range typeName {
+ if b == '%' || (b != '.' && isUrlExtraChar(b)) {
+ return Token{}, d.parseTypeNameError(s, 0)
+ }
+ }
+
+ startPos := len(d.orig) - len(d.in)
+ endPos := len(d.orig) - len(s)
d.in = s
- endPos := len(d.orig) - len(d.in)
d.consume(0)
return Token{
}, nil
}
+func (d *Decoder) parseTypeNameError(s []byte, numUnconsumedChars int) error {
+ return d.newSyntaxError(
+ "invalid type URL/extension field name: %s",
+ d.in[:len(d.in)-len(s)+min(numUnconsumedChars, len(s))],
+ )
+}
+
+func isHexChar(b byte) bool {
+ return ('0' <= b && b <= '9') ||
+ ('a' <= b && b <= 'f') ||
+ ('A' <= b && b <= 'F')
+}
+
func isTypeNameChar(b byte) bool {
- return (b == '-' || b == '_' ||
+ return b == '-' || b == '_' ||
('0' <= b && b <= '9') ||
('a' <= b && b <= 'z') ||
- ('A' <= b && b <= 'Z'))
+ ('A' <= b && b <= 'Z')
}
-func isWhiteSpace(b byte) bool {
+// isUrlExtraChar complements isTypeNameChar with extra characters that we allow
+// in URLs but not in type names. Note that '/' is not included so that it can
+// be treated specially.
+func isUrlExtraChar(b byte) bool {
switch b {
- case ' ', '\n', '\r', '\t':
+ case '.', '~', '!', '$', '&', '(', ')', '*', '+', ',', ';', '=':
return true
default:
return false
EditionProto3 Edition = 999
Edition2023 Edition = 1000
Edition2024 Edition = 1001
+ EditionUnstable Edition = 9999
EditionUnsupported Edition = 100000
)
md.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb)
extensionIdx++
case genid.DescriptorProto_Options_field_number:
- md.unmarshalOptions(v)
rawOptions = appendOptions(rawOptions, v)
}
default:
md.L2.Options = md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Message, rawOptions)
}
-func (md *Message) unmarshalOptions(b []byte) {
- 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.MessageOptions_MapEntry_field_number:
- md.L1.IsMapEntry = protowire.DecodeBool(v)
- case genid.MessageOptions_MessageSetWireFormat_field_number:
- md.L1.IsMessageSet = protowire.DecodeBool(v)
- }
- default:
- m := protowire.ConsumeFieldValue(num, typ, b)
- b = b[m:]
- }
- }
-}
-
func unmarshalMessageReservedRange(b []byte) (r [2]protoreflect.FieldNumber) {
for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b)
Edition_EDITION_PROTO3_enum_value = 999
Edition_EDITION_2023_enum_value = 1000
Edition_EDITION_2024_enum_value = 1001
+ Edition_EDITION_UNSTABLE_enum_value = 9999
Edition_EDITION_1_TEST_ONLY_enum_value = 1
Edition_EDITION_2_TEST_ONLY_enum_value = 2
Edition_EDITION_99997_TEST_ONLY_enum_value = 99997
}
func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
+ if opts.depth--; opts.depth < 0 {
+ return out, errRecursionDepth
+ }
if wtyp != protowire.BytesType {
return out, errUnknown
}
}
func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
+ if opts.depth--; opts.depth < 0 {
+ return out, errRecursionDepth
+ }
if wtyp != protowire.BytesType {
return out, errUnknown
}
func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag protowire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) {
mi.init()
- opts.depth--
- if opts.depth < 0 {
+ if opts.depth--; opts.depth < 0 {
return out, errRecursionDepth
}
if flags.ProtoLegacy && mi.isMessageSet {
if in.Resolver == nil {
in.Resolver = protoregistry.GlobalTypes
}
+ if in.Depth == 0 {
+ in.Depth = protowire.DefaultRecursionLimit
+ }
o, st := mi.validate(in.Buf, 0, unmarshalOptions{
flags: in.Flags,
resolver: in.Resolver,
+ depth: in.Depth,
})
if o.initialized {
out.Flags |= protoiface.UnmarshalInitialized
states[0].typ = validationTypeGroup
states[0].endGroup = groupTag
}
+ if opts.depth--; opts.depth < 0 {
+ return out, ValidationInvalid
+ }
initialized := true
start := len(b)
State:
mi: vi.mi,
tail: b,
})
+ if vi.typ == validationTypeMessage ||
+ vi.typ == validationTypeGroup ||
+ vi.typ == validationTypeMap {
+ if opts.depth--; opts.depth < 0 {
+ return out, ValidationInvalid
+ }
+ }
b = v
continue State
case validationTypeRepeatedVarint:
mi: vi.mi,
endGroup: num,
})
+ if opts.depth--; opts.depth < 0 {
+ return out, ValidationInvalid
+ }
continue State
case flags.ProtoLegacy && vi.typ == validationTypeMessageSetItem:
typeid, v, n, err := messageset.ConsumeFieldValue(b, false)
mi: xvi.mi,
tail: b[n:],
})
+ if xvi.typ == validationTypeMessage ||
+ xvi.typ == validationTypeGroup ||
+ xvi.typ == validationTypeMap {
+ if opts.depth--; opts.depth < 0 {
+ return out, ValidationInvalid
+ }
+ }
b = v
continue State
}
switch st.typ {
case validationTypeMessage, validationTypeGroup:
numRequiredFields = int(st.mi.numRequiredFields)
+ opts.depth++
case validationTypeMap:
// If this is a map field with a message value that contains
// required fields, require that the value be present.
if st.mi != nil && st.mi.numRequiredFields > 0 {
numRequiredFields = 1
}
+ opts.depth++
}
// If there are more than 64 required fields, this check will
// always fail and we will report that the message is potentially
const (
Major = 1
Minor = 36
- Patch = 10
+ Patch = 11
PreRelease = ""
)
out, err = methods.Unmarshal(in)
} else {
- o.RecursionLimit--
- if o.RecursionLimit < 0 {
- return out, errors.New("exceeded max recursion depth")
+ if o.RecursionLimit--; o.RecursionLimit < 0 {
+ return out, errRecursionDepth
}
err = o.unmarshalMessageSlow(b, m)
}
}
func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv protoreflect.Map, fd protoreflect.FieldDescriptor) (n int, err error) {
+ if o.RecursionLimit--; o.RecursionLimit < 0 {
+ return 0, errRecursionDepth
+ }
if wtyp != protowire.BytesType {
return 0, errUnknown
}
var errUnknown = errors.New("BUG: internal error (unknown)")
var errDecode = errors.New("cannot parse invalid wire-format data")
+
+var errRecursionDepth = errors.New("exceeded maximum recursion depth")
if f.L1.Path == "" {
return nil, errors.New("file path must be populated")
}
- if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < editionssupport.Minimum || fd.GetEdition() > editionssupport.Maximum) {
+ if f.L1.Syntax == protoreflect.Editions &&
+ (fd.GetEdition() < editionssupport.Minimum || fd.GetEdition() > editionssupport.Maximum) &&
+ fd.GetEdition() != descriptorpb.Edition_EDITION_UNSTABLE {
// Allow cmd/protoc-gen-go/testdata to use any edition for easier
// testing of upcoming edition features.
if !strings.HasPrefix(fd.GetName(), "cmd/protoc-gen-go/testdata/") {
imp := &f.L2.Imports[i]
imps.importPublic(imp.Imports())
}
+ optionImps := importSet{f.Path(): true}
if len(fd.GetOptionDependency()) > 0 {
optionImports := make(filedesc.FileImports, len(fd.GetOptionDependency()))
for i, path := range fd.GetOptionDependency() {
}
imp.FileDescriptor = f
- if imps[imp.Path()] {
+ if imps[imp.Path()] || optionImps[imp.Path()] {
return nil, errors.New("already imported %q", path)
}
- imps[imp.Path()] = true
+ // This needs to be a separate map so that we don't recognize non-options
+ // symbols coming from option imports.
+ optionImps[imp.Path()] = true
}
f.L2.OptionImports = func() protoreflect.FileImports {
return &optionImports
return descriptorpb.Edition_EDITION_2023
case filedesc.Edition2024:
return descriptorpb.Edition_EDITION_2024
+ case filedesc.EditionUnstable:
+ return descriptorpb.Edition_EDITION_UNSTABLE
default:
panic(fmt.Sprintf("unknown value for edition: %v", ed))
}
return def
}
edpb := toEditionProto(ed)
- if defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb {
+ if (defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb) && edpb != descriptorpb.Edition_EDITION_UNSTABLE {
// This should never happen protodesc.(FileOptions).New would fail when
// initializing the file descriptor.
// This most likely means the embedded defaults were not updated.
// comparison.
Edition_EDITION_2023 Edition = 1000
Edition_EDITION_2024 Edition = 1001
+ // A placeholder edition for developing and testing unscheduled features.
+ Edition_EDITION_UNSTABLE Edition = 9999
// Placeholder editions for testing feature resolution. These should not be
// used or relied on outside of tests.
Edition_EDITION_1_TEST_ONLY Edition = 1
999: "EDITION_PROTO3",
1000: "EDITION_2023",
1001: "EDITION_2024",
+ 9999: "EDITION_UNSTABLE",
1: "EDITION_1_TEST_ONLY",
2: "EDITION_2_TEST_ONLY",
99997: "EDITION_99997_TEST_ONLY",
"EDITION_PROTO3": 999,
"EDITION_2023": 1000,
"EDITION_2024": 1001,
+ "EDITION_UNSTABLE": 9999,
"EDITION_1_TEST_ONLY": 1,
"EDITION_2_TEST_ONLY": 2,
"EDITION_99997_TEST_ONLY": 99997,
"\x18EnumValueDescriptorProto\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12\x16\n" +
"\x06number\x18\x02 \x01(\x05R\x06number\x12;\n" +
- "\aoptions\x18\x03 \x01(\v2!.google.protobuf.EnumValueOptionsR\aoptions\"\xa7\x01\n" +
+ "\aoptions\x18\x03 \x01(\v2!.google.protobuf.EnumValueOptionsR\aoptions\"\xb5\x01\n" +
"\x16ServiceDescriptorProto\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12>\n" +
"\x06method\x18\x02 \x03(\v2&.google.protobuf.MethodDescriptorProtoR\x06method\x129\n" +
- "\aoptions\x18\x03 \x01(\v2\x1f.google.protobuf.ServiceOptionsR\aoptions\"\x89\x02\n" +
+ "\aoptions\x18\x03 \x01(\v2\x1f.google.protobuf.ServiceOptionsR\aoptionsJ\x04\b\x04\x10\x05R\x06stream\"\x89\x02\n" +
"\x15MethodDescriptorProto\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12\x1d\n" +
"\n" +
"\bSemantic\x12\b\n" +
"\x04NONE\x10\x00\x12\a\n" +
"\x03SET\x10\x01\x12\t\n" +
- "\x05ALIAS\x10\x02*\xa7\x02\n" +
+ "\x05ALIAS\x10\x02*\xbe\x02\n" +
"\aEdition\x12\x13\n" +
"\x0fEDITION_UNKNOWN\x10\x00\x12\x13\n" +
"\x0eEDITION_LEGACY\x10\x84\a\x12\x13\n" +
"\x0eEDITION_PROTO2\x10\xe6\a\x12\x13\n" +
"\x0eEDITION_PROTO3\x10\xe7\a\x12\x11\n" +
"\fEDITION_2023\x10\xe8\a\x12\x11\n" +
- "\fEDITION_2024\x10\xe9\a\x12\x17\n" +
+ "\fEDITION_2024\x10\xe9\a\x12\x15\n" +
+ "\x10EDITION_UNSTABLE\x10\x8fN\x12\x17\n" +
"\x13EDITION_1_TEST_ONLY\x10\x01\x12\x17\n" +
"\x13EDITION_2_TEST_ONLY\x10\x02\x12\x1d\n" +
"\x17EDITION_99997_TEST_ONLY\x10\x9d\x8d\x06\x12\x1d\n" +
// ) to obtain a formatter capable of generating timestamps in this format.
type Timestamp struct {
state protoimpl.MessageState `protogen:"open.v1"`
- // Represents seconds of UTC time since Unix epoch
- // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
- // 9999-12-31T23:59:59Z inclusive.
+ // Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must
+ // be between -315576000000 and 315576000000 inclusive (which corresponds to
+ // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z).
Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
- // Non-negative fractions of a second at nanosecond resolution. Negative
- // second values with fractions must still have non-negative nanos values
- // that count forward in time. Must be from 0 to 999,999,999
+ // Non-negative fractions of a second at nanosecond resolution. This field is
+ // the nanosecond portion of the duration, not an alternative to seconds.
+ // Negative second values with fractions must still have non-negative nanos
+ // values that count forward in time. Must be between 0 and 999,999,999
// inclusive.
Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
unknownFields protoimpl.UnknownFields
google.golang.org/grpc/stats
google.golang.org/grpc/status
google.golang.org/grpc/tap
-# google.golang.org/protobuf v1.36.10
+# google.golang.org/protobuf v1.36.11
## explicit; go 1.23
google.golang.org/protobuf/compiler/protogen
google.golang.org/protobuf/encoding/protodelim