Committing vendored dependencies and generated protos
Change-Id: I349c149b513d9de7d9f60bde2c954a939da2fc54
diff --git a/vendor/github.com/jhump/protoreflect/LICENSE b/vendor/github.com/jhump/protoreflect/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/jhump/protoreflect/codec/buffer.go b/vendor/github.com/jhump/protoreflect/codec/buffer.go
new file mode 100644
index 0000000..b9de99c
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/buffer.go
@@ -0,0 +1,112 @@
+package codec
+
+import (
+ "fmt"
+ "io"
+)
+
+// Buffer is a reader and a writer that wraps a slice of bytes and also
+// provides API for decoding and encoding the protobuf binary format.
+//
+// Its operation is similar to that of a bytes.Buffer: writing pushes
+// data to the end of the buffer while reading pops data from the head
+// of the buffer. So the same buffer can be used to both read and write.
+type Buffer struct {
+ buf []byte
+ index int
+
+ // tmp is used when another byte slice is needed, such as when
+ // serializing messages, since we need to know the length before
+ // we can write the length prefix; by caching this, including
+ // after it is grown by serialization operations, we reduce the
+ // number of allocations needed
+ tmp []byte
+
+ deterministic bool
+}
+
+// NewBuffer creates a new buffer with the given slice of bytes as the
+// buffer's initial contents.
+func NewBuffer(buf []byte) *Buffer {
+ return &Buffer{buf: buf}
+}
+
+// SetDeterministic sets this buffer to encode messages deterministically. This
+// is useful for tests. But the overhead is non-zero, so it should not likely be
+// used outside of tests. When true, map fields in a message must have their
+// keys sorted before serialization to ensure deterministic output. Otherwise,
+// values in a map field will be serialized in map iteration order.
+func (cb *Buffer) SetDeterministic(deterministic bool) {
+ cb.deterministic = deterministic
+}
+
+// Reset resets this buffer back to empty. Any subsequent writes/encodes
+// to the buffer will allocate a new backing slice of bytes.
+func (cb *Buffer) Reset() {
+ cb.buf = []byte(nil)
+ cb.index = 0
+}
+
+// Bytes returns the slice of bytes remaining in the buffer. Note that
+// this does not perform a copy: if the contents of the returned slice
+// are modified, the modifications will be visible to subsequent reads
+// via the buffer.
+func (cb *Buffer) Bytes() []byte {
+ return cb.buf[cb.index:]
+}
+
+// String returns the remaining bytes in the buffer as a string.
+func (cb *Buffer) String() string {
+ return string(cb.Bytes())
+}
+
+// EOF returns true if there are no more bytes remaining to read.
+func (cb *Buffer) EOF() bool {
+ return cb.index >= len(cb.buf)
+}
+
+// Skip attempts to skip the given number of bytes in the input. If
+// the input has fewer bytes than the given count, false is returned
+// and the buffer is unchanged. Otherwise, the given number of bytes
+// are skipped and true is returned.
+func (cb *Buffer) Skip(count int) error {
+ if count < 0 {
+ return fmt.Errorf("proto: bad byte length %d", count)
+ }
+ newIndex := cb.index + count
+ if newIndex < cb.index || newIndex > len(cb.buf) {
+ return io.ErrUnexpectedEOF
+ }
+ cb.index = newIndex
+ return nil
+}
+
+// Len returns the remaining number of bytes in the buffer.
+func (cb *Buffer) Len() int {
+ return len(cb.buf) - cb.index
+}
+
+// Read implements the io.Reader interface. If there are no bytes
+// remaining in the buffer, it will return 0, io.EOF. Otherwise,
+// it reads max(len(dest), cb.Len()) bytes from input and copies
+// them into dest. It returns the number of bytes copied and a nil
+// error in this case.
+func (cb *Buffer) Read(dest []byte) (int, error) {
+ if cb.index == len(cb.buf) {
+ return 0, io.EOF
+ }
+ copied := copy(dest, cb.buf[cb.index:])
+ cb.index += copied
+ return copied, nil
+}
+
+var _ io.Reader = (*Buffer)(nil)
+
+// Write implements the io.Writer interface. It always returns
+// len(data), nil.
+func (cb *Buffer) Write(data []byte) (int, error) {
+ cb.buf = append(cb.buf, data...)
+ return len(data), nil
+}
+
+var _ io.Writer = (*Buffer)(nil)
diff --git a/vendor/github.com/jhump/protoreflect/codec/decode.go b/vendor/github.com/jhump/protoreflect/codec/decode.go
new file mode 100644
index 0000000..2a7e59f
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/decode.go
@@ -0,0 +1,372 @@
+package codec
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "math"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/protoc-gen-go/descriptor"
+)
+
+// ErrOverflow is returned when an integer is too large to be represented.
+var ErrOverflow = errors.New("proto: integer overflow")
+
+// ErrBadWireType is returned when decoding a wire-type from a buffer that
+// is not valid.
+var ErrBadWireType = errors.New("proto: bad wiretype")
+
+var varintTypes = map[descriptor.FieldDescriptorProto_Type]bool{}
+var fixed32Types = map[descriptor.FieldDescriptorProto_Type]bool{}
+var fixed64Types = map[descriptor.FieldDescriptorProto_Type]bool{}
+
+func init() {
+ varintTypes[descriptor.FieldDescriptorProto_TYPE_BOOL] = true
+ varintTypes[descriptor.FieldDescriptorProto_TYPE_INT32] = true
+ varintTypes[descriptor.FieldDescriptorProto_TYPE_INT64] = true
+ varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT32] = true
+ varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT64] = true
+ varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT32] = true
+ varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT64] = true
+ varintTypes[descriptor.FieldDescriptorProto_TYPE_ENUM] = true
+
+ fixed32Types[descriptor.FieldDescriptorProto_TYPE_FIXED32] = true
+ fixed32Types[descriptor.FieldDescriptorProto_TYPE_SFIXED32] = true
+ fixed32Types[descriptor.FieldDescriptorProto_TYPE_FLOAT] = true
+
+ fixed64Types[descriptor.FieldDescriptorProto_TYPE_FIXED64] = true
+ fixed64Types[descriptor.FieldDescriptorProto_TYPE_SFIXED64] = true
+ fixed64Types[descriptor.FieldDescriptorProto_TYPE_DOUBLE] = true
+}
+
+func (cb *Buffer) decodeVarintSlow() (x uint64, err error) {
+ i := cb.index
+ l := len(cb.buf)
+
+ for shift := uint(0); shift < 64; shift += 7 {
+ if i >= l {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ b := cb.buf[i]
+ i++
+ x |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ cb.index = i
+ return
+ }
+ }
+
+ // The number is too large to represent in a 64-bit value.
+ err = ErrOverflow
+ return
+}
+
+// DecodeVarint reads a varint-encoded integer from the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (cb *Buffer) DecodeVarint() (uint64, error) {
+ i := cb.index
+ buf := cb.buf
+
+ if i >= len(buf) {
+ return 0, io.ErrUnexpectedEOF
+ } else if buf[i] < 0x80 {
+ cb.index++
+ return uint64(buf[i]), nil
+ } else if len(buf)-i < 10 {
+ return cb.decodeVarintSlow()
+ }
+
+ var b uint64
+ // we already checked the first byte
+ x := uint64(buf[i]) - 0x80
+ i++
+
+ b = uint64(buf[i])
+ i++
+ x += b << 7
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 7
+
+ b = uint64(buf[i])
+ i++
+ x += b << 14
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 14
+
+ b = uint64(buf[i])
+ i++
+ x += b << 21
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 21
+
+ b = uint64(buf[i])
+ i++
+ x += b << 28
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 28
+
+ b = uint64(buf[i])
+ i++
+ x += b << 35
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 35
+
+ b = uint64(buf[i])
+ i++
+ x += b << 42
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 42
+
+ b = uint64(buf[i])
+ i++
+ x += b << 49
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 49
+
+ b = uint64(buf[i])
+ i++
+ x += b << 56
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 56
+
+ b = uint64(buf[i])
+ i++
+ x += b << 63
+ if b&0x80 == 0 {
+ goto done
+ }
+ // x -= 0x80 << 63 // Always zero.
+
+ return 0, ErrOverflow
+
+done:
+ cb.index = i
+ return x, nil
+}
+
+// DecodeTagAndWireType decodes a field tag and wire type from input.
+// This reads a varint and then extracts the two fields from the varint
+// value read.
+func (cb *Buffer) DecodeTagAndWireType() (tag int32, wireType int8, err error) {
+ var v uint64
+ v, err = cb.DecodeVarint()
+ if err != nil {
+ return
+ }
+ // low 7 bits is wire type
+ wireType = int8(v & 7)
+ // rest is int32 tag number
+ v = v >> 3
+ if v > math.MaxInt32 {
+ err = fmt.Errorf("tag number out of range: %d", v)
+ return
+ }
+ tag = int32(v)
+ return
+}
+
+// DecodeFixed64 reads a 64-bit integer from the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (cb *Buffer) DecodeFixed64() (x uint64, err error) {
+ // x, err already 0
+ i := cb.index + 8
+ if i < 0 || i > len(cb.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ cb.index = i
+
+ x = uint64(cb.buf[i-8])
+ x |= uint64(cb.buf[i-7]) << 8
+ x |= uint64(cb.buf[i-6]) << 16
+ x |= uint64(cb.buf[i-5]) << 24
+ x |= uint64(cb.buf[i-4]) << 32
+ x |= uint64(cb.buf[i-3]) << 40
+ x |= uint64(cb.buf[i-2]) << 48
+ x |= uint64(cb.buf[i-1]) << 56
+ return
+}
+
+// DecodeFixed32 reads a 32-bit integer from the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (cb *Buffer) DecodeFixed32() (x uint64, err error) {
+ // x, err already 0
+ i := cb.index + 4
+ if i < 0 || i > len(cb.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ cb.index = i
+
+ x = uint64(cb.buf[i-4])
+ x |= uint64(cb.buf[i-3]) << 8
+ x |= uint64(cb.buf[i-2]) << 16
+ x |= uint64(cb.buf[i-1]) << 24
+ return
+}
+
+// DecodeZigZag32 decodes a signed 32-bit integer from the given
+// zig-zag encoded value.
+func DecodeZigZag32(v uint64) int32 {
+ return int32((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31))
+}
+
+// DecodeZigZag64 decodes a signed 64-bit integer from the given
+// zig-zag encoded value.
+func DecodeZigZag64(v uint64) int64 {
+ return int64((v >> 1) ^ uint64((int64(v&1)<<63)>>63))
+}
+
+// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (cb *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
+ n, err := cb.DecodeVarint()
+ if err != nil {
+ return nil, err
+ }
+
+ nb := int(n)
+ if nb < 0 {
+ return nil, fmt.Errorf("proto: bad byte length %d", nb)
+ }
+ end := cb.index + nb
+ if end < cb.index || end > len(cb.buf) {
+ return nil, io.ErrUnexpectedEOF
+ }
+
+ if !alloc {
+ buf = cb.buf[cb.index:end]
+ cb.index = end
+ return
+ }
+
+ buf = make([]byte, nb)
+ copy(buf, cb.buf[cb.index:])
+ cb.index = end
+ return
+}
+
+// ReadGroup reads the input until a "group end" tag is found
+// and returns the data up to that point. Subsequent reads from
+// the buffer will read data after the group end tag. If alloc
+// is true, the data is copied to a new slice before being returned.
+// Otherwise, the returned slice is a view into the buffer's
+// underlying byte slice.
+//
+// This function correctly handles nested groups: if a "group start"
+// tag is found, then that group's end tag will be included in the
+// returned data.
+func (cb *Buffer) ReadGroup(alloc bool) ([]byte, error) {
+ var groupEnd, dataEnd int
+ groupEnd, dataEnd, err := cb.findGroupEnd()
+ if err != nil {
+ return nil, err
+ }
+ var results []byte
+ if !alloc {
+ results = cb.buf[cb.index:dataEnd]
+ } else {
+ results = make([]byte, dataEnd-cb.index)
+ copy(results, cb.buf[cb.index:])
+ }
+ cb.index = groupEnd
+ return results, nil
+}
+
+// SkipGroup is like ReadGroup, except that it discards the
+// data and just advances the buffer to point to the input
+// right *after* the "group end" tag.
+func (cb *Buffer) SkipGroup() error {
+ groupEnd, _, err := cb.findGroupEnd()
+ if err != nil {
+ return err
+ }
+ cb.index = groupEnd
+ return nil
+}
+
+func (cb *Buffer) findGroupEnd() (groupEnd int, dataEnd int, err error) {
+ bs := cb.buf
+ start := cb.index
+ defer func() {
+ cb.index = start
+ }()
+ for {
+ fieldStart := cb.index
+ // read a field tag
+ _, wireType, err := cb.DecodeTagAndWireType()
+ if err != nil {
+ return 0, 0, err
+ }
+ // skip past the field's data
+ switch wireType {
+ case proto.WireFixed32:
+ if err := cb.Skip(4); err != nil {
+ return 0, 0, err
+ }
+ case proto.WireFixed64:
+ if err := cb.Skip(8); err != nil {
+ return 0, 0, err
+ }
+ case proto.WireVarint:
+ // skip varint by finding last byte (has high bit unset)
+ i := cb.index
+ limit := i + 10 // varint cannot be >10 bytes
+ for {
+ if i >= limit {
+ return 0, 0, ErrOverflow
+ }
+ if i >= len(bs) {
+ return 0, 0, io.ErrUnexpectedEOF
+ }
+ if bs[i]&0x80 == 0 {
+ break
+ }
+ i++
+ }
+ // TODO: This would only overflow if buffer length was MaxInt and we
+ // read the last byte. This is not a real/feasible concern on 64-bit
+ // systems. Something to worry about for 32-bit systems? Do we care?
+ cb.index = i + 1
+ case proto.WireBytes:
+ l, err := cb.DecodeVarint()
+ if err != nil {
+ return 0, 0, err
+ }
+ if err := cb.Skip(int(l)); err != nil {
+ return 0, 0, err
+ }
+ case proto.WireStartGroup:
+ if err := cb.SkipGroup(); err != nil {
+ return 0, 0, err
+ }
+ case proto.WireEndGroup:
+ return cb.index, fieldStart, nil
+ default:
+ return 0, 0, ErrBadWireType
+ }
+ }
+}
diff --git a/vendor/github.com/jhump/protoreflect/codec/decode_fields.go b/vendor/github.com/jhump/protoreflect/codec/decode_fields.go
new file mode 100644
index 0000000..938b4d9
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/decode_fields.go
@@ -0,0 +1,283 @@
+package codec
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "math"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+ "github.com/jhump/protoreflect/desc"
+)
+
+// ErrWireTypeEndGroup is returned from DecodeFieldValue if the tag and wire-type
+// it reads indicates an end-group marker.
+var ErrWireTypeEndGroup = errors.New("unexpected wire type: end group")
+
+// MessageFactory is used to instantiate messages when DecodeFieldValue needs to
+// decode a message value.
+//
+// Also see MessageFactory in "github.com/jhump/protoreflect/dynamic", which
+// implements this interface.
+type MessageFactory interface {
+ NewMessage(md *desc.MessageDescriptor) proto.Message
+}
+
+// UnknownField represents a field that was parsed from the binary wire
+// format for a message, but was not a recognized field number. Enough
+// information is preserved so that re-serializing the message won't lose
+// any of the unrecognized data.
+type UnknownField struct {
+ // The tag number for the unrecognized field.
+ Tag int32
+
+ // Encoding indicates how the unknown field was encoded on the wire. If it
+ // is proto.WireBytes or proto.WireGroupStart then Contents will be set to
+ // the raw bytes. If it is proto.WireTypeFixed32 then the data is in the least
+ // significant 32 bits of Value. Otherwise, the data is in all 64 bits of
+ // Value.
+ Encoding int8
+ Contents []byte
+ Value uint64
+}
+
+// DecodeFieldValue will read a field value from the buffer and return its
+// value and the corresponding field descriptor. The given function is used
+// to lookup a field descriptor by tag number. The given factory is used to
+// instantiate a message if the field value is (or contains) a message value.
+//
+// On error, the field descriptor and value are typically nil. However, if the
+// error returned is ErrWireTypeEndGroup, the returned value will indicate any
+// tag number encoded in the end-group marker.
+//
+// If the field descriptor returned is nil, that means that the given function
+// returned nil. This is expected to happen for unrecognized tag numbers. In
+// that case, no error is returned, and the value will be an UnknownField.
+func (cb *Buffer) DecodeFieldValue(fieldFinder func(int32) *desc.FieldDescriptor, fact MessageFactory) (*desc.FieldDescriptor, interface{}, error) {
+ if cb.EOF() {
+ return nil, nil, io.EOF
+ }
+ tagNumber, wireType, err := cb.DecodeTagAndWireType()
+ if err != nil {
+ return nil, nil, err
+ }
+ if wireType == proto.WireEndGroup {
+ return nil, tagNumber, ErrWireTypeEndGroup
+ }
+ fd := fieldFinder(tagNumber)
+ if fd == nil {
+ val, err := cb.decodeUnknownField(tagNumber, wireType)
+ return nil, val, err
+ }
+ val, err := cb.decodeKnownField(fd, wireType, fact)
+ return fd, val, err
+}
+
+// DecodeScalarField extracts a properly-typed value from v. The returned value's
+// type depends on the given field descriptor type. It will be the same type as
+// generated structs use for the field descriptor's type. Enum types will return
+// an int32. If the given field type uses length-delimited encoding (nested
+// messages, bytes, and strings), an error is returned.
+func DecodeScalarField(fd *desc.FieldDescriptor, v uint64) (interface{}, error) {
+ switch fd.GetType() {
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ return v != 0, nil
+ case descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ if v > math.MaxUint32 {
+ return nil, ErrOverflow
+ }
+ return uint32(v), nil
+
+ case descriptor.FieldDescriptorProto_TYPE_INT32,
+ descriptor.FieldDescriptorProto_TYPE_ENUM:
+ s := int64(v)
+ if s > math.MaxInt32 || s < math.MinInt32 {
+ return nil, ErrOverflow
+ }
+ return int32(s), nil
+
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ if v > math.MaxUint32 {
+ return nil, ErrOverflow
+ }
+ return int32(v), nil
+
+ case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ if v > math.MaxUint32 {
+ return nil, ErrOverflow
+ }
+ return DecodeZigZag32(v), nil
+
+ case descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ return v, nil
+
+ case descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ return int64(v), nil
+
+ case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ return DecodeZigZag64(v), nil
+
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ if v > math.MaxUint32 {
+ return nil, ErrOverflow
+ }
+ return math.Float32frombits(uint32(v)), nil
+
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ return math.Float64frombits(v), nil
+
+ default:
+ // bytes, string, message, and group cannot be represented as a simple numeric value
+ return nil, fmt.Errorf("bad input; field %s requires length-delimited wire type", fd.GetFullyQualifiedName())
+ }
+}
+
+// DecodeLengthDelimitedField extracts a properly-typed value from bytes. The
+// returned value's type will usually be []byte, string, or, for nested messages,
+// the type returned from the given message factory. However, since repeated
+// scalar fields can be length-delimited, when they used packed encoding, it can
+// also return an []interface{}, where each element is a scalar value. Furthermore,
+// it could return a scalar type, not in a slice, if the given field descriptor is
+// not repeated. This is to support cases where a field is changed from optional
+// to repeated. New code may emit a packed repeated representation, but old code
+// still expects a single scalar value. In this case, if the actual data in bytes
+// contains multiple values, only the last value is returned.
+func DecodeLengthDelimitedField(fd *desc.FieldDescriptor, bytes []byte, mf MessageFactory) (interface{}, error) {
+ switch {
+ case fd.GetType() == descriptor.FieldDescriptorProto_TYPE_BYTES:
+ return bytes, nil
+
+ case fd.GetType() == descriptor.FieldDescriptorProto_TYPE_STRING:
+ return string(bytes), nil
+
+ case fd.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE ||
+ fd.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP:
+ msg := mf.NewMessage(fd.GetMessageType())
+ err := proto.Unmarshal(bytes, msg)
+ if err != nil {
+ return nil, err
+ } else {
+ return msg, nil
+ }
+
+ default:
+ // even if the field is not repeated or not packed, we still parse it as such for
+ // backwards compatibility (e.g. message we are de-serializing could have been both
+ // repeated and packed at the time of serialization)
+ packedBuf := NewBuffer(bytes)
+ var slice []interface{}
+ var val interface{}
+ for !packedBuf.EOF() {
+ var v uint64
+ var err error
+ if varintTypes[fd.GetType()] {
+ v, err = packedBuf.DecodeVarint()
+ } else if fixed32Types[fd.GetType()] {
+ v, err = packedBuf.DecodeFixed32()
+ } else if fixed64Types[fd.GetType()] {
+ v, err = packedBuf.DecodeFixed64()
+ } else {
+ return nil, fmt.Errorf("bad input; cannot parse length-delimited wire type for field %s", fd.GetFullyQualifiedName())
+ }
+ if err != nil {
+ return nil, err
+ }
+ val, err = DecodeScalarField(fd, v)
+ if err != nil {
+ return nil, err
+ }
+ if fd.IsRepeated() {
+ slice = append(slice, val)
+ }
+ }
+ if fd.IsRepeated() {
+ return slice, nil
+ } else {
+ // if not a repeated field, last value wins
+ return val, nil
+ }
+ }
+}
+
+func (b *Buffer) decodeKnownField(fd *desc.FieldDescriptor, encoding int8, fact MessageFactory) (interface{}, error) {
+ var val interface{}
+ var err error
+ switch encoding {
+ case proto.WireFixed32:
+ var num uint64
+ num, err = b.DecodeFixed32()
+ if err == nil {
+ val, err = DecodeScalarField(fd, num)
+ }
+ case proto.WireFixed64:
+ var num uint64
+ num, err = b.DecodeFixed64()
+ if err == nil {
+ val, err = DecodeScalarField(fd, num)
+ }
+ case proto.WireVarint:
+ var num uint64
+ num, err = b.DecodeVarint()
+ if err == nil {
+ val, err = DecodeScalarField(fd, num)
+ }
+
+ case proto.WireBytes:
+ alloc := fd.GetType() == descriptor.FieldDescriptorProto_TYPE_BYTES
+ var raw []byte
+ raw, err = b.DecodeRawBytes(alloc)
+ if err == nil {
+ val, err = DecodeLengthDelimitedField(fd, raw, fact)
+ }
+
+ case proto.WireStartGroup:
+ if fd.GetMessageType() == nil {
+ return nil, fmt.Errorf("cannot parse field %s from group-encoded wire type", fd.GetFullyQualifiedName())
+ }
+ msg := fact.NewMessage(fd.GetMessageType())
+ var data []byte
+ data, err = b.ReadGroup(false)
+ if err == nil {
+ err = proto.Unmarshal(data, msg)
+ if err == nil {
+ val = msg
+ }
+ }
+
+ default:
+ return nil, ErrBadWireType
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ return val, nil
+}
+
+func (b *Buffer) decodeUnknownField(tagNumber int32, encoding int8) (interface{}, error) {
+ u := UnknownField{Tag: tagNumber, Encoding: encoding}
+ var err error
+ switch encoding {
+ case proto.WireFixed32:
+ u.Value, err = b.DecodeFixed32()
+ case proto.WireFixed64:
+ u.Value, err = b.DecodeFixed64()
+ case proto.WireVarint:
+ u.Value, err = b.DecodeVarint()
+ case proto.WireBytes:
+ u.Contents, err = b.DecodeRawBytes(true)
+ case proto.WireStartGroup:
+ u.Contents, err = b.ReadGroup(true)
+ default:
+ err = ErrBadWireType
+ }
+ if err != nil {
+ return nil, err
+ }
+ return u, nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/codec/doc.go b/vendor/github.com/jhump/protoreflect/codec/doc.go
new file mode 100644
index 0000000..f76499f
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/doc.go
@@ -0,0 +1,7 @@
+// Package codec contains a reader/write type that assists with encoding
+// and decoding protobuf's binary representation.
+//
+// The code in this package began as a fork of proto.Buffer but provides
+// additional API to make it more useful to code that needs to dynamically
+// process or produce the protobuf binary format.
+package codec
diff --git a/vendor/github.com/jhump/protoreflect/codec/encode.go b/vendor/github.com/jhump/protoreflect/codec/encode.go
new file mode 100644
index 0000000..c84523f
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/encode.go
@@ -0,0 +1,163 @@
+package codec
+
+import "github.com/golang/protobuf/proto"
+
+// EncodeVarint writes a varint-encoded integer to the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (cb *Buffer) EncodeVarint(x uint64) error {
+ for x >= 1<<7 {
+ cb.buf = append(cb.buf, uint8(x&0x7f|0x80))
+ x >>= 7
+ }
+ cb.buf = append(cb.buf, uint8(x))
+ return nil
+}
+
+// EncodeTagAndWireType encodes the given field tag and wire type to the
+// buffer. This combines the two values and then writes them as a varint.
+func (cb *Buffer) EncodeTagAndWireType(tag int32, wireType int8) error {
+ v := uint64((int64(tag) << 3) | int64(wireType))
+ return cb.EncodeVarint(v)
+}
+
+// EncodeFixed64 writes a 64-bit integer to the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (cb *Buffer) EncodeFixed64(x uint64) error {
+ cb.buf = append(cb.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24),
+ uint8(x>>32),
+ uint8(x>>40),
+ uint8(x>>48),
+ uint8(x>>56))
+ return nil
+}
+
+// EncodeFixed32 writes a 32-bit integer to the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (cb *Buffer) EncodeFixed32(x uint64) error {
+ cb.buf = append(cb.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24))
+ return nil
+}
+
+// EncodeZigZag64 does zig-zag encoding to convert the given
+// signed 64-bit integer into a form that can be expressed
+// efficiently as a varint, even for negative values.
+func EncodeZigZag64(v int64) uint64 {
+ return (uint64(v) << 1) ^ uint64(v>>63)
+}
+
+// EncodeZigZag32 does zig-zag encoding to convert the given
+// signed 32-bit integer into a form that can be expressed
+// efficiently as a varint, even for negative values.
+func EncodeZigZag32(v int32) uint64 {
+ return uint64((uint32(v) << 1) ^ uint32((v >> 31)))
+}
+
+// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (cb *Buffer) EncodeRawBytes(b []byte) error {
+ if err := cb.EncodeVarint(uint64(len(b))); err != nil {
+ return err
+ }
+ cb.buf = append(cb.buf, b...)
+ return nil
+}
+
+// EncodeMessage writes the given message to the buffer.
+func (cb *Buffer) EncodeMessage(pm proto.Message) error {
+ bytes, err := marshalMessage(cb.buf, pm, cb.deterministic)
+ if err != nil {
+ return err
+ }
+ cb.buf = bytes
+ return nil
+}
+
+// EncodeDelimitedMessage writes the given message to the buffer with a
+// varint-encoded length prefix (the delimiter).
+func (cb *Buffer) EncodeDelimitedMessage(pm proto.Message) error {
+ bytes, err := marshalMessage(cb.tmp, pm, cb.deterministic)
+ if err != nil {
+ return err
+ }
+ // save truncated buffer if it was grown (so we can re-use it and
+ // curtail future allocations)
+ if cap(bytes) > cap(cb.tmp) {
+ cb.tmp = bytes[:0]
+ }
+ return cb.EncodeRawBytes(bytes)
+}
+
+func marshalMessage(b []byte, pm proto.Message, deterministic bool) ([]byte, error) {
+ // we try to use the most efficient way to marshal to existing slice
+ nm, ok := pm.(interface {
+ // this interface is implemented by generated messages
+ XXX_Size() int
+ XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
+ })
+ if ok {
+ sz := nm.XXX_Size()
+ if cap(b) < len(b)+sz {
+ // re-allocate to fit
+ bytes := make([]byte, len(b), len(b)+sz)
+ copy(bytes, b)
+ b = bytes
+ }
+ return nm.XXX_Marshal(b, deterministic)
+ }
+
+ if deterministic {
+ // see if the message has custom deterministic methods, preferring an
+ // "append" method over one that must always re-allocate
+ madm, ok := pm.(interface {
+ MarshalAppendDeterministic(b []byte) ([]byte, error)
+ })
+ if ok {
+ return madm.MarshalAppendDeterministic(b)
+ }
+
+ mdm, ok := pm.(interface {
+ MarshalDeterministic() ([]byte, error)
+ })
+ if ok {
+ bytes, err := mdm.MarshalDeterministic()
+ if err != nil {
+ return nil, err
+ }
+ if len(b) == 0 {
+ return bytes, nil
+ }
+ return append(b, bytes...), nil
+ }
+ }
+
+ mam, ok := pm.(interface {
+ // see if we can append the message, vs. having to re-allocate
+ MarshalAppend(b []byte) ([]byte, error)
+ })
+ if ok {
+ return mam.MarshalAppend(b)
+ }
+
+ // lowest common denominator
+ bytes, err := proto.Marshal(pm)
+ if err != nil {
+ return nil, err
+ }
+ if len(b) == 0 {
+ return bytes, nil
+ }
+ return append(b, bytes...), nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/codec/encode_fields.go b/vendor/github.com/jhump/protoreflect/codec/encode_fields.go
new file mode 100644
index 0000000..cda7299
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/encode_fields.go
@@ -0,0 +1,267 @@
+package codec
+
+import (
+ "fmt"
+ "math"
+ "reflect"
+ "sort"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+ "github.com/jhump/protoreflect/desc"
+)
+
+func (cb *Buffer) EncodeFieldValue(fd *desc.FieldDescriptor, val interface{}) error {
+ if fd.IsMap() {
+ mp := val.(map[interface{}]interface{})
+ entryType := fd.GetMessageType()
+ keyType := entryType.FindFieldByNumber(1)
+ valType := entryType.FindFieldByNumber(2)
+ var entryBuffer Buffer
+ if cb.deterministic {
+ keys := make([]interface{}, 0, len(mp))
+ for k := range mp {
+ keys = append(keys, k)
+ }
+ sort.Sort(sortable(keys))
+ for _, k := range keys {
+ v := mp[k]
+ entryBuffer.Reset()
+ if err := entryBuffer.encodeFieldElement(keyType, k); err != nil {
+ return err
+ }
+ if err := entryBuffer.encodeFieldElement(valType, v); err != nil {
+ return err
+ }
+ if err := cb.EncodeTagAndWireType(fd.GetNumber(), proto.WireBytes); err != nil {
+ return err
+ }
+ if err := cb.EncodeRawBytes(entryBuffer.Bytes()); err != nil {
+ return err
+ }
+ }
+ } else {
+ for k, v := range mp {
+ entryBuffer.Reset()
+ if err := entryBuffer.encodeFieldElement(keyType, k); err != nil {
+ return err
+ }
+ if err := entryBuffer.encodeFieldElement(valType, v); err != nil {
+ return err
+ }
+ if err := cb.EncodeTagAndWireType(fd.GetNumber(), proto.WireBytes); err != nil {
+ return err
+ }
+ if err := cb.EncodeRawBytes(entryBuffer.Bytes()); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+ } else if fd.IsRepeated() {
+ sl := val.([]interface{})
+ wt, err := getWireType(fd.GetType())
+ if err != nil {
+ return err
+ }
+ if isPacked(fd) && len(sl) > 1 &&
+ (wt == proto.WireVarint || wt == proto.WireFixed32 || wt == proto.WireFixed64) {
+ // packed repeated field
+ var packedBuffer Buffer
+ for _, v := range sl {
+ if err := packedBuffer.encodeFieldValue(fd, v); err != nil {
+ return err
+ }
+ }
+ if err := cb.EncodeTagAndWireType(fd.GetNumber(), proto.WireBytes); err != nil {
+ return err
+ }
+ return cb.EncodeRawBytes(packedBuffer.Bytes())
+ } else {
+ // non-packed repeated field
+ for _, v := range sl {
+ if err := cb.encodeFieldElement(fd, v); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ } else {
+ return cb.encodeFieldElement(fd, val)
+ }
+}
+
+func isPacked(fd *desc.FieldDescriptor) bool {
+ opts := fd.AsFieldDescriptorProto().GetOptions()
+ // if set, use that value
+ if opts != nil && opts.Packed != nil {
+ return opts.GetPacked()
+ }
+ // if unset: proto2 defaults to false, proto3 to true
+ return fd.GetFile().IsProto3()
+}
+
+// sortable is used to sort map keys. Values will be integers (int32, int64, uint32, and uint64),
+// bools, or strings.
+type sortable []interface{}
+
+func (s sortable) Len() int {
+ return len(s)
+}
+
+func (s sortable) Less(i, j int) bool {
+ vi := s[i]
+ vj := s[j]
+ switch reflect.TypeOf(vi).Kind() {
+ case reflect.Int32:
+ return vi.(int32) < vj.(int32)
+ case reflect.Int64:
+ return vi.(int64) < vj.(int64)
+ case reflect.Uint32:
+ return vi.(uint32) < vj.(uint32)
+ case reflect.Uint64:
+ return vi.(uint64) < vj.(uint64)
+ case reflect.String:
+ return vi.(string) < vj.(string)
+ case reflect.Bool:
+ return !vi.(bool) && vj.(bool)
+ default:
+ panic(fmt.Sprintf("cannot compare keys of type %v", reflect.TypeOf(vi)))
+ }
+}
+
+func (s sortable) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (b *Buffer) encodeFieldElement(fd *desc.FieldDescriptor, val interface{}) error {
+ wt, err := getWireType(fd.GetType())
+ if err != nil {
+ return err
+ }
+ if err := b.EncodeTagAndWireType(fd.GetNumber(), wt); err != nil {
+ return err
+ }
+ if err := b.encodeFieldValue(fd, val); err != nil {
+ return err
+ }
+ if wt == proto.WireStartGroup {
+ return b.EncodeTagAndWireType(fd.GetNumber(), proto.WireEndGroup)
+ }
+ return nil
+}
+
+func (b *Buffer) encodeFieldValue(fd *desc.FieldDescriptor, val interface{}) error {
+ switch fd.GetType() {
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ v := val.(bool)
+ if v {
+ return b.EncodeVarint(1)
+ }
+ return b.EncodeVarint(0)
+
+ case descriptor.FieldDescriptorProto_TYPE_ENUM,
+ descriptor.FieldDescriptorProto_TYPE_INT32:
+ v := val.(int32)
+ return b.EncodeVarint(uint64(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ v := val.(int32)
+ return b.EncodeFixed32(uint64(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_SINT32:
+ v := val.(int32)
+ return b.EncodeVarint(EncodeZigZag32(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_UINT32:
+ v := val.(uint32)
+ return b.EncodeVarint(uint64(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ v := val.(uint32)
+ return b.EncodeFixed32(uint64(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_INT64:
+ v := val.(int64)
+ return b.EncodeVarint(uint64(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ v := val.(int64)
+ return b.EncodeFixed64(uint64(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_SINT64:
+ v := val.(int64)
+ return b.EncodeVarint(EncodeZigZag64(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_UINT64:
+ v := val.(uint64)
+ return b.EncodeVarint(v)
+
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ v := val.(uint64)
+ return b.EncodeFixed64(v)
+
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ v := val.(float64)
+ return b.EncodeFixed64(math.Float64bits(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ v := val.(float32)
+ return b.EncodeFixed32(uint64(math.Float32bits(v)))
+
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ v := val.([]byte)
+ return b.EncodeRawBytes(v)
+
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ v := val.(string)
+ return b.EncodeRawBytes(([]byte)(v))
+
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ return b.EncodeDelimitedMessage(val.(proto.Message))
+
+ case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ // just append the nested message to this buffer
+ return b.EncodeMessage(val.(proto.Message))
+ // whosoever writeth start-group tag (e.g. caller) is responsible for writing end-group tag
+
+ default:
+ return fmt.Errorf("unrecognized field type: %v", fd.GetType())
+ }
+}
+
+func getWireType(t descriptor.FieldDescriptorProto_Type) (int8, error) {
+ switch t {
+ case descriptor.FieldDescriptorProto_TYPE_ENUM,
+ descriptor.FieldDescriptorProto_TYPE_BOOL,
+ descriptor.FieldDescriptorProto_TYPE_INT32,
+ descriptor.FieldDescriptorProto_TYPE_SINT32,
+ descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_SINT64,
+ descriptor.FieldDescriptorProto_TYPE_UINT64:
+ return proto.WireVarint, nil
+
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32,
+ descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ return proto.WireFixed32, nil
+
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64,
+ descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ return proto.WireFixed64, nil
+
+ case descriptor.FieldDescriptorProto_TYPE_BYTES,
+ descriptor.FieldDescriptorProto_TYPE_STRING,
+ descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+ return proto.WireBytes, nil
+
+ case descriptor.FieldDescriptorProto_TYPE_GROUP:
+ return proto.WireStartGroup, nil
+
+ default:
+ return 0, ErrBadWireType
+ }
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/convert.go b/vendor/github.com/jhump/protoreflect/desc/convert.go
new file mode 100644
index 0000000..538820c
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/convert.go
@@ -0,0 +1,231 @@
+package desc
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+
+ dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+ "github.com/jhump/protoreflect/desc/internal"
+ intn "github.com/jhump/protoreflect/internal"
+)
+
+// CreateFileDescriptor instantiates a new file descriptor for the given descriptor proto.
+// The file's direct dependencies must be provided. If the given dependencies do not include
+// all of the file's dependencies or if the contents of the descriptors are internally
+// inconsistent (e.g. contain unresolvable symbols) then an error is returned.
+func CreateFileDescriptor(fd *dpb.FileDescriptorProto, deps ...*FileDescriptor) (*FileDescriptor, error) {
+ return createFileDescriptor(fd, deps, nil)
+}
+
+func createFileDescriptor(fd *dpb.FileDescriptorProto, deps []*FileDescriptor, r *ImportResolver) (*FileDescriptor, error) {
+ ret := &FileDescriptor{
+ proto: fd,
+ symbols: map[string]Descriptor{},
+ fieldIndex: map[string]map[int32]*FieldDescriptor{},
+ }
+ pkg := fd.GetPackage()
+
+ // populate references to file descriptor dependencies
+ files := map[string]*FileDescriptor{}
+ for _, f := range deps {
+ files[f.proto.GetName()] = f
+ }
+ ret.deps = make([]*FileDescriptor, len(fd.GetDependency()))
+ for i, d := range fd.GetDependency() {
+ resolved := r.ResolveImport(fd.GetName(), d)
+ ret.deps[i] = files[resolved]
+ if ret.deps[i] == nil {
+ if resolved != d {
+ ret.deps[i] = files[d]
+ }
+ if ret.deps[i] == nil {
+ return nil, intn.ErrNoSuchFile(d)
+ }
+ }
+ }
+ ret.publicDeps = make([]*FileDescriptor, len(fd.GetPublicDependency()))
+ for i, pd := range fd.GetPublicDependency() {
+ ret.publicDeps[i] = ret.deps[pd]
+ }
+ ret.weakDeps = make([]*FileDescriptor, len(fd.GetWeakDependency()))
+ for i, wd := range fd.GetWeakDependency() {
+ ret.weakDeps[i] = ret.deps[wd]
+ }
+ ret.isProto3 = fd.GetSyntax() == "proto3"
+
+ // populate all tables of child descriptors
+ for _, m := range fd.GetMessageType() {
+ md, n := createMessageDescriptor(ret, ret, pkg, m, ret.symbols)
+ ret.symbols[n] = md
+ ret.messages = append(ret.messages, md)
+ }
+ for _, e := range fd.GetEnumType() {
+ ed, n := createEnumDescriptor(ret, ret, pkg, e, ret.symbols)
+ ret.symbols[n] = ed
+ ret.enums = append(ret.enums, ed)
+ }
+ for _, ex := range fd.GetExtension() {
+ exd, n := createFieldDescriptor(ret, ret, pkg, ex)
+ ret.symbols[n] = exd
+ ret.extensions = append(ret.extensions, exd)
+ }
+ for _, s := range fd.GetService() {
+ sd, n := createServiceDescriptor(ret, pkg, s, ret.symbols)
+ ret.symbols[n] = sd
+ ret.services = append(ret.services, sd)
+ }
+
+ ret.sourceInfo = internal.CreateSourceInfoMap(fd)
+ ret.sourceInfoRecomputeFunc = ret.recomputeSourceInfo
+
+ // now we can resolve all type references and source code info
+ scopes := []scope{fileScope(ret)}
+ path := make([]int32, 1, 8)
+ path[0] = internal.File_messagesTag
+ for i, md := range ret.messages {
+ if err := md.resolve(append(path, int32(i)), scopes); err != nil {
+ return nil, err
+ }
+ }
+ path[0] = internal.File_enumsTag
+ for i, ed := range ret.enums {
+ ed.resolve(append(path, int32(i)))
+ }
+ path[0] = internal.File_extensionsTag
+ for i, exd := range ret.extensions {
+ if err := exd.resolve(append(path, int32(i)), scopes); err != nil {
+ return nil, err
+ }
+ }
+ path[0] = internal.File_servicesTag
+ for i, sd := range ret.services {
+ if err := sd.resolve(append(path, int32(i)), scopes); err != nil {
+ return nil, err
+ }
+ }
+
+ return ret, nil
+}
+
+// CreateFileDescriptors constructs a set of descriptors, one for each of the
+// given descriptor protos. The given set of descriptor protos must include all
+// transitive dependencies for every file.
+func CreateFileDescriptors(fds []*dpb.FileDescriptorProto) (map[string]*FileDescriptor, error) {
+ return createFileDescriptors(fds, nil)
+}
+
+func createFileDescriptors(fds []*dpb.FileDescriptorProto, r *ImportResolver) (map[string]*FileDescriptor, error) {
+ if len(fds) == 0 {
+ return nil, nil
+ }
+ files := map[string]*dpb.FileDescriptorProto{}
+ resolved := map[string]*FileDescriptor{}
+ var name string
+ for _, fd := range fds {
+ name = fd.GetName()
+ files[name] = fd
+ }
+ for _, fd := range fds {
+ _, err := createFromSet(fd.GetName(), r, nil, files, resolved)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return resolved, nil
+}
+
+// ToFileDescriptorSet creates a FileDescriptorSet proto that contains all of the given
+// file descriptors and their transitive dependencies. The files are topologically sorted
+// so that a file will always appear after its dependencies.
+func ToFileDescriptorSet(fds ...*FileDescriptor) *dpb.FileDescriptorSet {
+ var fdps []*dpb.FileDescriptorProto
+ addAllFiles(fds, &fdps, map[string]struct{}{})
+ return &dpb.FileDescriptorSet{File: fdps}
+}
+
+func addAllFiles(src []*FileDescriptor, results *[]*dpb.FileDescriptorProto, seen map[string]struct{}) {
+ for _, fd := range src {
+ if _, ok := seen[fd.GetName()]; ok {
+ continue
+ }
+ seen[fd.GetName()] = struct{}{}
+ addAllFiles(fd.GetDependencies(), results, seen)
+ *results = append(*results, fd.AsFileDescriptorProto())
+ }
+}
+
+// CreateFileDescriptorFromSet creates a descriptor from the given file descriptor set. The
+// set's *last* file will be the returned descriptor. The set's remaining files must comprise
+// the full set of transitive dependencies of that last file. This is the same format and
+// order used by protoc when emitting a FileDescriptorSet file with an invocation like so:
+// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
+func CreateFileDescriptorFromSet(fds *dpb.FileDescriptorSet) (*FileDescriptor, error) {
+ return createFileDescriptorFromSet(fds, nil)
+}
+
+func createFileDescriptorFromSet(fds *dpb.FileDescriptorSet, r *ImportResolver) (*FileDescriptor, error) {
+ result, err := createFileDescriptorsFromSet(fds, r)
+ if err != nil {
+ return nil, err
+ }
+ files := fds.GetFile()
+ lastFilename := files[len(files)-1].GetName()
+ return result[lastFilename], nil
+}
+
+// CreateFileDescriptorsFromSet creates file descriptors from the given file descriptor set.
+// The returned map includes all files in the set, keyed b name. The set must include the
+// full set of transitive dependencies for all files therein or else a link error will occur
+// and be returned instead of the slice of descriptors. This is the same format used by
+// protoc when a FileDescriptorSet file with an invocation like so:
+// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
+func CreateFileDescriptorsFromSet(fds *dpb.FileDescriptorSet) (map[string]*FileDescriptor, error) {
+ return createFileDescriptorsFromSet(fds, nil)
+}
+
+func createFileDescriptorsFromSet(fds *dpb.FileDescriptorSet, r *ImportResolver) (map[string]*FileDescriptor, error) {
+ files := fds.GetFile()
+ if len(files) == 0 {
+ return nil, errors.New("file descriptor set is empty")
+ }
+ return createFileDescriptors(files, r)
+}
+
+// createFromSet creates a descriptor for the given filename. It recursively
+// creates descriptors for the given file's dependencies.
+func createFromSet(filename string, r *ImportResolver, seen []string, files map[string]*dpb.FileDescriptorProto, resolved map[string]*FileDescriptor) (*FileDescriptor, error) {
+ for _, s := range seen {
+ if filename == s {
+ return nil, fmt.Errorf("cycle in imports: %s", strings.Join(append(seen, filename), " -> "))
+ }
+ }
+ seen = append(seen, filename)
+
+ if d, ok := resolved[filename]; ok {
+ return d, nil
+ }
+ fdp := files[filename]
+ if fdp == nil {
+ return nil, intn.ErrNoSuchFile(filename)
+ }
+ deps := make([]*FileDescriptor, len(fdp.GetDependency()))
+ for i, depName := range fdp.GetDependency() {
+ resolvedDep := r.ResolveImport(filename, depName)
+ dep, err := createFromSet(resolvedDep, r, seen, files, resolved)
+ if _, ok := err.(intn.ErrNoSuchFile); ok && resolvedDep != depName {
+ dep, err = createFromSet(depName, r, seen, files, resolved)
+ }
+ if err != nil {
+ return nil, err
+ }
+ deps[i] = dep
+ }
+ d, err := createFileDescriptor(fdp, deps, r)
+ if err != nil {
+ return nil, err
+ }
+ resolved[filename] = d
+ return d, nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/descriptor.go b/vendor/github.com/jhump/protoreflect/desc/descriptor.go
new file mode 100644
index 0000000..ab235a3
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/descriptor.go
@@ -0,0 +1,1666 @@
+package desc
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+ "strconv"
+ "strings"
+ "unicode/utf8"
+
+ "github.com/golang/protobuf/proto"
+ dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+ "github.com/jhump/protoreflect/desc/internal"
+)
+
+// Descriptor is the common interface implemented by all descriptor objects.
+type Descriptor interface {
+ // GetName returns the name of the object described by the descriptor. This will
+ // be a base name that does not include enclosing message names or the package name.
+ // For file descriptors, this indicates the path and name to the described file.
+ GetName() string
+ // GetFullyQualifiedName returns the fully-qualified name of the object described by
+ // the descriptor. This will include the package name and any enclosing message names.
+ // For file descriptors, this returns the path and name to the described file (same as
+ // GetName).
+ GetFullyQualifiedName() string
+ // GetParent returns the enclosing element in a proto source file. If the described
+ // object is a top-level object, this returns the file descriptor. Otherwise, it returns
+ // the element in which the described object was declared. File descriptors have no
+ // parent and return nil.
+ GetParent() Descriptor
+ // GetFile returns the file descriptor in which this element was declared. File
+ // descriptors return themselves.
+ GetFile() *FileDescriptor
+ // GetOptions returns the options proto containing options for the described element.
+ GetOptions() proto.Message
+ // GetSourceInfo returns any source code information that was present in the file
+ // descriptor. Source code info is optional. If no source code info is available for
+ // the element (including if there is none at all in the file descriptor) then this
+ // returns nil
+ GetSourceInfo() *dpb.SourceCodeInfo_Location
+ // AsProto returns the underlying descriptor proto for this descriptor.
+ AsProto() proto.Message
+}
+
+type sourceInfoRecomputeFunc = internal.SourceInfoComputeFunc
+
+// FileDescriptor describes a proto source file.
+type FileDescriptor struct {
+ proto *dpb.FileDescriptorProto
+ symbols map[string]Descriptor
+ deps []*FileDescriptor
+ publicDeps []*FileDescriptor
+ weakDeps []*FileDescriptor
+ messages []*MessageDescriptor
+ enums []*EnumDescriptor
+ extensions []*FieldDescriptor
+ services []*ServiceDescriptor
+ fieldIndex map[string]map[int32]*FieldDescriptor
+ isProto3 bool
+ sourceInfo internal.SourceInfoMap
+ sourceInfoRecomputeFunc
+}
+
+func (fd *FileDescriptor) recomputeSourceInfo() {
+ internal.PopulateSourceInfoMap(fd.proto, fd.sourceInfo)
+}
+
+func (fd *FileDescriptor) registerField(field *FieldDescriptor) {
+ fields := fd.fieldIndex[field.owner.GetFullyQualifiedName()]
+ if fields == nil {
+ fields = map[int32]*FieldDescriptor{}
+ fd.fieldIndex[field.owner.GetFullyQualifiedName()] = fields
+ }
+ fields[field.GetNumber()] = field
+}
+
+// GetName returns the name of the file, as it was given to the protoc invocation
+// to compile it, possibly including path (relative to a directory in the proto
+// import path).
+func (fd *FileDescriptor) GetName() string {
+ return fd.proto.GetName()
+}
+
+// GetFullyQualifiedName returns the name of the file, same as GetName. It is
+// present to satisfy the Descriptor interface.
+func (fd *FileDescriptor) GetFullyQualifiedName() string {
+ return fd.proto.GetName()
+}
+
+// GetPackage returns the name of the package declared in the file.
+func (fd *FileDescriptor) GetPackage() string {
+ return fd.proto.GetPackage()
+}
+
+// GetParent always returns nil: files are the root of descriptor hierarchies.
+// Is it present to satisfy the Descriptor interface.
+func (fd *FileDescriptor) GetParent() Descriptor {
+ return nil
+}
+
+// GetFile returns the receiver, which is a file descriptor. This is present
+// to satisfy the Descriptor interface.
+func (fd *FileDescriptor) GetFile() *FileDescriptor {
+ return fd
+}
+
+// GetOptions returns the file's options. Most usages will be more interested
+// in GetFileOptions, which has a concrete return type. This generic version
+// is present to satisfy the Descriptor interface.
+func (fd *FileDescriptor) GetOptions() proto.Message {
+ return fd.proto.GetOptions()
+}
+
+// GetFileOptions returns the file's options.
+func (fd *FileDescriptor) GetFileOptions() *dpb.FileOptions {
+ return fd.proto.GetOptions()
+}
+
+// GetSourceInfo returns nil for files. It is present to satisfy the Descriptor
+// interface.
+func (fd *FileDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+ return nil
+}
+
+// AsProto returns the underlying descriptor proto. Most usages will be more
+// interested in AsFileDescriptorProto, which has a concrete return type. This
+// generic version is present to satisfy the Descriptor interface.
+func (fd *FileDescriptor) AsProto() proto.Message {
+ return fd.proto
+}
+
+// AsFileDescriptorProto returns the underlying descriptor proto.
+func (fd *FileDescriptor) AsFileDescriptorProto() *dpb.FileDescriptorProto {
+ return fd.proto
+}
+
+// String returns the underlying descriptor proto, in compact text format.
+func (fd *FileDescriptor) String() string {
+ return fd.proto.String()
+}
+
+// IsProto3 returns true if the file declares a syntax of "proto3".
+func (fd *FileDescriptor) IsProto3() bool {
+ return fd.isProto3
+}
+
+// GetDependencies returns all of this file's dependencies. These correspond to
+// import statements in the file.
+func (fd *FileDescriptor) GetDependencies() []*FileDescriptor {
+ return fd.deps
+}
+
+// GetPublicDependencies returns all of this file's public dependencies. These
+// correspond to public import statements in the file.
+func (fd *FileDescriptor) GetPublicDependencies() []*FileDescriptor {
+ return fd.publicDeps
+}
+
+// GetWeakDependencies returns all of this file's weak dependencies. These
+// correspond to weak import statements in the file.
+func (fd *FileDescriptor) GetWeakDependencies() []*FileDescriptor {
+ return fd.weakDeps
+}
+
+// GetMessageTypes returns all top-level messages declared in this file.
+func (fd *FileDescriptor) GetMessageTypes() []*MessageDescriptor {
+ return fd.messages
+}
+
+// GetEnumTypes returns all top-level enums declared in this file.
+func (fd *FileDescriptor) GetEnumTypes() []*EnumDescriptor {
+ return fd.enums
+}
+
+// GetExtensions returns all top-level extensions declared in this file.
+func (fd *FileDescriptor) GetExtensions() []*FieldDescriptor {
+ return fd.extensions
+}
+
+// GetServices returns all services declared in this file.
+func (fd *FileDescriptor) GetServices() []*ServiceDescriptor {
+ return fd.services
+}
+
+// FindSymbol returns the descriptor contained within this file for the
+// element with the given fully-qualified symbol name. If no such element
+// exists then this method returns nil.
+func (fd *FileDescriptor) FindSymbol(symbol string) Descriptor {
+ if symbol[0] == '.' {
+ symbol = symbol[1:]
+ }
+ return fd.symbols[symbol]
+}
+
+// FindMessage finds the message with the given fully-qualified name. If no
+// such element exists in this file then nil is returned.
+func (fd *FileDescriptor) FindMessage(msgName string) *MessageDescriptor {
+ if md, ok := fd.symbols[msgName].(*MessageDescriptor); ok {
+ return md
+ } else {
+ return nil
+ }
+}
+
+// FindEnum finds the enum with the given fully-qualified name. If no such
+// element exists in this file then nil is returned.
+func (fd *FileDescriptor) FindEnum(enumName string) *EnumDescriptor {
+ if ed, ok := fd.symbols[enumName].(*EnumDescriptor); ok {
+ return ed
+ } else {
+ return nil
+ }
+}
+
+// FindService finds the service with the given fully-qualified name. If no
+// such element exists in this file then nil is returned.
+func (fd *FileDescriptor) FindService(serviceName string) *ServiceDescriptor {
+ if sd, ok := fd.symbols[serviceName].(*ServiceDescriptor); ok {
+ return sd
+ } else {
+ return nil
+ }
+}
+
+// FindExtension finds the extension field for the given extended type name and
+// tag number. If no such element exists in this file then nil is returned.
+func (fd *FileDescriptor) FindExtension(extendeeName string, tagNumber int32) *FieldDescriptor {
+ if exd, ok := fd.fieldIndex[extendeeName][tagNumber]; ok && exd.IsExtension() {
+ return exd
+ } else {
+ return nil
+ }
+}
+
+// FindExtensionByName finds the extension field with the given fully-qualified
+// name. If no such element exists in this file then nil is returned.
+func (fd *FileDescriptor) FindExtensionByName(extName string) *FieldDescriptor {
+ if exd, ok := fd.symbols[extName].(*FieldDescriptor); ok && exd.IsExtension() {
+ return exd
+ } else {
+ return nil
+ }
+}
+
+// MessageDescriptor describes a protocol buffer message.
+type MessageDescriptor struct {
+ proto *dpb.DescriptorProto
+ parent Descriptor
+ file *FileDescriptor
+ fields []*FieldDescriptor
+ nested []*MessageDescriptor
+ enums []*EnumDescriptor
+ extensions []*FieldDescriptor
+ oneOfs []*OneOfDescriptor
+ extRanges extRanges
+ fqn string
+ sourceInfoPath []int32
+ jsonNames jsonNameMap
+ isProto3 bool
+ isMapEntry bool
+}
+
+func createMessageDescriptor(fd *FileDescriptor, parent Descriptor, enclosing string, md *dpb.DescriptorProto, symbols map[string]Descriptor) (*MessageDescriptor, string) {
+ msgName := merge(enclosing, md.GetName())
+ ret := &MessageDescriptor{proto: md, parent: parent, file: fd, fqn: msgName}
+ for _, f := range md.GetField() {
+ fld, n := createFieldDescriptor(fd, ret, msgName, f)
+ symbols[n] = fld
+ ret.fields = append(ret.fields, fld)
+ }
+ for _, nm := range md.NestedType {
+ nmd, n := createMessageDescriptor(fd, ret, msgName, nm, symbols)
+ symbols[n] = nmd
+ ret.nested = append(ret.nested, nmd)
+ }
+ for _, e := range md.EnumType {
+ ed, n := createEnumDescriptor(fd, ret, msgName, e, symbols)
+ symbols[n] = ed
+ ret.enums = append(ret.enums, ed)
+ }
+ for _, ex := range md.GetExtension() {
+ exd, n := createFieldDescriptor(fd, ret, msgName, ex)
+ symbols[n] = exd
+ ret.extensions = append(ret.extensions, exd)
+ }
+ for i, o := range md.GetOneofDecl() {
+ od, n := createOneOfDescriptor(fd, ret, i, msgName, o)
+ symbols[n] = od
+ ret.oneOfs = append(ret.oneOfs, od)
+ }
+ for _, r := range md.GetExtensionRange() {
+ // proto.ExtensionRange is inclusive (and that's how extension ranges are defined in code).
+ // but protoc converts range to exclusive end in descriptor, so we must convert back
+ end := r.GetEnd() - 1
+ ret.extRanges = append(ret.extRanges, proto.ExtensionRange{
+ Start: r.GetStart(),
+ End: end})
+ }
+ sort.Sort(ret.extRanges)
+ ret.isProto3 = fd.isProto3
+ ret.isMapEntry = md.GetOptions().GetMapEntry() &&
+ len(ret.fields) == 2 &&
+ ret.fields[0].GetNumber() == 1 &&
+ ret.fields[1].GetNumber() == 2
+
+ return ret, msgName
+}
+
+func (md *MessageDescriptor) resolve(path []int32, scopes []scope) error {
+ md.sourceInfoPath = append([]int32(nil), path...) // defensive copy
+ path = append(path, internal.Message_nestedMessagesTag)
+ scopes = append(scopes, messageScope(md))
+ for i, nmd := range md.nested {
+ if err := nmd.resolve(append(path, int32(i)), scopes); err != nil {
+ return err
+ }
+ }
+ path[len(path)-1] = internal.Message_enumsTag
+ for i, ed := range md.enums {
+ ed.resolve(append(path, int32(i)))
+ }
+ path[len(path)-1] = internal.Message_fieldsTag
+ for i, fld := range md.fields {
+ if err := fld.resolve(append(path, int32(i)), scopes); err != nil {
+ return err
+ }
+ }
+ path[len(path)-1] = internal.Message_extensionsTag
+ for i, exd := range md.extensions {
+ if err := exd.resolve(append(path, int32(i)), scopes); err != nil {
+ return err
+ }
+ }
+ path[len(path)-1] = internal.Message_oneOfsTag
+ for i, od := range md.oneOfs {
+ od.resolve(append(path, int32(i)))
+ }
+ return nil
+}
+
+// GetName returns the simple (unqualified) name of the message.
+func (md *MessageDescriptor) GetName() string {
+ return md.proto.GetName()
+}
+
+// GetFullyQualifiedName returns the fully qualified name of the message. This
+// includes the package name (if there is one) as well as the names of any
+// enclosing messages.
+func (md *MessageDescriptor) GetFullyQualifiedName() string {
+ return md.fqn
+}
+
+// GetParent returns the message's enclosing descriptor. For top-level messages,
+// this will be a file descriptor. Otherwise it will be the descriptor for the
+// enclosing message.
+func (md *MessageDescriptor) GetParent() Descriptor {
+ return md.parent
+}
+
+// GetFile returns the descriptor for the file in which this message is defined.
+func (md *MessageDescriptor) GetFile() *FileDescriptor {
+ return md.file
+}
+
+// GetOptions returns the message's options. Most usages will be more interested
+// in GetMessageOptions, which has a concrete return type. This generic version
+// is present to satisfy the Descriptor interface.
+func (md *MessageDescriptor) GetOptions() proto.Message {
+ return md.proto.GetOptions()
+}
+
+// GetMessageOptions returns the message's options.
+func (md *MessageDescriptor) GetMessageOptions() *dpb.MessageOptions {
+ return md.proto.GetOptions()
+}
+
+// GetSourceInfo returns source info for the message, if present in the
+// descriptor. Not all descriptors will contain source info. If non-nil, the
+// returned info contains information about the location in the file where the
+// message was defined and also contains comments associated with the message
+// definition.
+func (md *MessageDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+ return md.file.sourceInfo.Get(md.sourceInfoPath)
+}
+
+// AsProto returns the underlying descriptor proto. Most usages will be more
+// interested in AsDescriptorProto, which has a concrete return type. This
+// generic version is present to satisfy the Descriptor interface.
+func (md *MessageDescriptor) AsProto() proto.Message {
+ return md.proto
+}
+
+// AsDescriptorProto returns the underlying descriptor proto.
+func (md *MessageDescriptor) AsDescriptorProto() *dpb.DescriptorProto {
+ return md.proto
+}
+
+// String returns the underlying descriptor proto, in compact text format.
+func (md *MessageDescriptor) String() string {
+ return md.proto.String()
+}
+
+// IsMapEntry returns true if this is a synthetic message type that represents an entry
+// in a map field.
+func (md *MessageDescriptor) IsMapEntry() bool {
+ return md.isMapEntry
+}
+
+// GetFields returns all of the fields for this message.
+func (md *MessageDescriptor) GetFields() []*FieldDescriptor {
+ return md.fields
+}
+
+// GetNestedMessageTypes returns all of the message types declared inside this message.
+func (md *MessageDescriptor) GetNestedMessageTypes() []*MessageDescriptor {
+ return md.nested
+}
+
+// GetNestedEnumTypes returns all of the enums declared inside this message.
+func (md *MessageDescriptor) GetNestedEnumTypes() []*EnumDescriptor {
+ return md.enums
+}
+
+// GetNestedExtensions returns all of the extensions declared inside this message.
+func (md *MessageDescriptor) GetNestedExtensions() []*FieldDescriptor {
+ return md.extensions
+}
+
+// GetOneOfs returns all of the one-of field sets declared inside this message.
+func (md *MessageDescriptor) GetOneOfs() []*OneOfDescriptor {
+ return md.oneOfs
+}
+
+// IsProto3 returns true if the file in which this message is defined declares a syntax of "proto3".
+func (md *MessageDescriptor) IsProto3() bool {
+ return md.isProto3
+}
+
+// GetExtensionRanges returns the ranges of extension field numbers for this message.
+func (md *MessageDescriptor) GetExtensionRanges() []proto.ExtensionRange {
+ return md.extRanges
+}
+
+// IsExtendable returns true if this message has any extension ranges.
+func (md *MessageDescriptor) IsExtendable() bool {
+ return len(md.extRanges) > 0
+}
+
+// IsExtension returns true if the given tag number is within any of this message's
+// extension ranges.
+func (md *MessageDescriptor) IsExtension(tagNumber int32) bool {
+ return md.extRanges.IsExtension(tagNumber)
+}
+
+type extRanges []proto.ExtensionRange
+
+func (er extRanges) String() string {
+ var buf bytes.Buffer
+ first := true
+ for _, r := range er {
+ if first {
+ first = false
+ } else {
+ buf.WriteString(",")
+ }
+ fmt.Fprintf(&buf, "%d..%d", r.Start, r.End)
+ }
+ return buf.String()
+}
+
+func (er extRanges) IsExtension(tagNumber int32) bool {
+ i := sort.Search(len(er), func(i int) bool { return er[i].End >= tagNumber })
+ return i < len(er) && tagNumber >= er[i].Start
+}
+
+func (er extRanges) Len() int {
+ return len(er)
+}
+
+func (er extRanges) Less(i, j int) bool {
+ return er[i].Start < er[j].Start
+}
+
+func (er extRanges) Swap(i, j int) {
+ er[i], er[j] = er[j], er[i]
+}
+
+// FindFieldByName finds the field with the given name. If no such field exists
+// then nil is returned. Only regular fields are returned, not extensions.
+func (md *MessageDescriptor) FindFieldByName(fieldName string) *FieldDescriptor {
+ fqn := fmt.Sprintf("%s.%s", md.fqn, fieldName)
+ if fd, ok := md.file.symbols[fqn].(*FieldDescriptor); ok && !fd.IsExtension() {
+ return fd
+ } else {
+ return nil
+ }
+}
+
+// FindFieldByNumber finds the field with the given tag number. If no such field
+// exists then nil is returned. Only regular fields are returned, not extensions.
+func (md *MessageDescriptor) FindFieldByNumber(tagNumber int32) *FieldDescriptor {
+ if fd, ok := md.file.fieldIndex[md.fqn][tagNumber]; ok && !fd.IsExtension() {
+ return fd
+ } else {
+ return nil
+ }
+}
+
+// FieldDescriptor describes a field of a protocol buffer message.
+type FieldDescriptor struct {
+ proto *dpb.FieldDescriptorProto
+ parent Descriptor
+ owner *MessageDescriptor
+ file *FileDescriptor
+ oneOf *OneOfDescriptor
+ msgType *MessageDescriptor
+ enumType *EnumDescriptor
+ fqn string
+ sourceInfoPath []int32
+ def memoizedDefault
+ isMap bool
+}
+
+func createFieldDescriptor(fd *FileDescriptor, parent Descriptor, enclosing string, fld *dpb.FieldDescriptorProto) (*FieldDescriptor, string) {
+ fldName := merge(enclosing, fld.GetName())
+ ret := &FieldDescriptor{proto: fld, parent: parent, file: fd, fqn: fldName}
+ if fld.GetExtendee() == "" {
+ ret.owner = parent.(*MessageDescriptor)
+ }
+ // owner for extensions, field type (be it message or enum), and one-ofs get resolved later
+ return ret, fldName
+}
+
+func (fd *FieldDescriptor) resolve(path []int32, scopes []scope) error {
+ if fd.proto.OneofIndex != nil && fd.oneOf == nil {
+ return fmt.Errorf("could not link field %s to one-of index %d", fd.fqn, *fd.proto.OneofIndex)
+ }
+ fd.sourceInfoPath = append([]int32(nil), path...) // defensive copy
+ if fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_ENUM {
+ if desc, err := resolve(fd.file, fd.proto.GetTypeName(), scopes); err != nil {
+ return err
+ } else {
+ fd.enumType = desc.(*EnumDescriptor)
+ }
+ }
+ if fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_MESSAGE || fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_GROUP {
+ if desc, err := resolve(fd.file, fd.proto.GetTypeName(), scopes); err != nil {
+ return err
+ } else {
+ fd.msgType = desc.(*MessageDescriptor)
+ }
+ }
+ if fd.proto.GetExtendee() != "" {
+ if desc, err := resolve(fd.file, fd.proto.GetExtendee(), scopes); err != nil {
+ return err
+ } else {
+ fd.owner = desc.(*MessageDescriptor)
+ }
+ }
+ fd.file.registerField(fd)
+ fd.isMap = fd.proto.GetLabel() == dpb.FieldDescriptorProto_LABEL_REPEATED &&
+ fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_MESSAGE &&
+ fd.GetMessageType().IsMapEntry()
+ return nil
+}
+
+func (fd *FieldDescriptor) determineDefault() interface{} {
+ if fd.IsMap() {
+ return map[interface{}]interface{}(nil)
+ } else if fd.IsRepeated() {
+ return []interface{}(nil)
+ } else if fd.msgType != nil {
+ return nil
+ }
+
+ proto3 := fd.file.isProto3
+ if !proto3 {
+ def := fd.AsFieldDescriptorProto().GetDefaultValue()
+ if def != "" {
+ ret := parseDefaultValue(fd, def)
+ if ret != nil {
+ return ret
+ }
+ // if we can't parse default value, fall-through to return normal default...
+ }
+ }
+
+ switch fd.GetType() {
+ case dpb.FieldDescriptorProto_TYPE_FIXED32,
+ dpb.FieldDescriptorProto_TYPE_UINT32:
+ return uint32(0)
+ case dpb.FieldDescriptorProto_TYPE_SFIXED32,
+ dpb.FieldDescriptorProto_TYPE_INT32,
+ dpb.FieldDescriptorProto_TYPE_SINT32:
+ return int32(0)
+ case dpb.FieldDescriptorProto_TYPE_FIXED64,
+ dpb.FieldDescriptorProto_TYPE_UINT64:
+ return uint64(0)
+ case dpb.FieldDescriptorProto_TYPE_SFIXED64,
+ dpb.FieldDescriptorProto_TYPE_INT64,
+ dpb.FieldDescriptorProto_TYPE_SINT64:
+ return int64(0)
+ case dpb.FieldDescriptorProto_TYPE_FLOAT:
+ return float32(0.0)
+ case dpb.FieldDescriptorProto_TYPE_DOUBLE:
+ return float64(0.0)
+ case dpb.FieldDescriptorProto_TYPE_BOOL:
+ return false
+ case dpb.FieldDescriptorProto_TYPE_BYTES:
+ return []byte(nil)
+ case dpb.FieldDescriptorProto_TYPE_STRING:
+ return ""
+ case dpb.FieldDescriptorProto_TYPE_ENUM:
+ if proto3 {
+ return int32(0)
+ }
+ enumVals := fd.GetEnumType().GetValues()
+ if len(enumVals) > 0 {
+ return enumVals[0].GetNumber()
+ } else {
+ return int32(0) // WTF?
+ }
+ default:
+ panic(fmt.Sprintf("Unknown field type: %v", fd.GetType()))
+ }
+}
+
+func parseDefaultValue(fd *FieldDescriptor, val string) interface{} {
+ switch fd.GetType() {
+ case dpb.FieldDescriptorProto_TYPE_ENUM:
+ vd := fd.GetEnumType().FindValueByName(val)
+ if vd != nil {
+ return vd.GetNumber()
+ }
+ return nil
+ case dpb.FieldDescriptorProto_TYPE_BOOL:
+ if val == "true" {
+ return true
+ } else if val == "false" {
+ return false
+ }
+ return nil
+ case dpb.FieldDescriptorProto_TYPE_BYTES:
+ return []byte(unescape(val))
+ case dpb.FieldDescriptorProto_TYPE_STRING:
+ return val
+ case dpb.FieldDescriptorProto_TYPE_FLOAT:
+ if f, err := strconv.ParseFloat(val, 32); err == nil {
+ return float32(f)
+ } else {
+ return float32(0)
+ }
+ case dpb.FieldDescriptorProto_TYPE_DOUBLE:
+ if f, err := strconv.ParseFloat(val, 64); err == nil {
+ return f
+ } else {
+ return float64(0)
+ }
+ case dpb.FieldDescriptorProto_TYPE_INT32,
+ dpb.FieldDescriptorProto_TYPE_SINT32,
+ dpb.FieldDescriptorProto_TYPE_SFIXED32:
+ if i, err := strconv.ParseInt(val, 10, 32); err == nil {
+ return int32(i)
+ } else {
+ return int32(0)
+ }
+ case dpb.FieldDescriptorProto_TYPE_UINT32,
+ dpb.FieldDescriptorProto_TYPE_FIXED32:
+ if i, err := strconv.ParseUint(val, 10, 32); err == nil {
+ return uint32(i)
+ } else {
+ return uint32(0)
+ }
+ case dpb.FieldDescriptorProto_TYPE_INT64,
+ dpb.FieldDescriptorProto_TYPE_SINT64,
+ dpb.FieldDescriptorProto_TYPE_SFIXED64:
+ if i, err := strconv.ParseInt(val, 10, 64); err == nil {
+ return i
+ } else {
+ return int64(0)
+ }
+ case dpb.FieldDescriptorProto_TYPE_UINT64,
+ dpb.FieldDescriptorProto_TYPE_FIXED64:
+ if i, err := strconv.ParseUint(val, 10, 64); err == nil {
+ return i
+ } else {
+ return uint64(0)
+ }
+ default:
+ return nil
+ }
+}
+
+func unescape(s string) string {
+ // protoc encodes default values for 'bytes' fields using C escaping,
+ // so this function reverses that escaping
+ out := make([]byte, 0, len(s))
+ var buf [4]byte
+ for len(s) > 0 {
+ if s[0] != '\\' || len(s) < 2 {
+ // not escape sequence, or too short to be well-formed escape
+ out = append(out, s[0])
+ s = s[1:]
+ } else if s[1] == 'x' || s[1] == 'X' {
+ n := matchPrefix(s[2:], 2, isHex)
+ if n == 0 {
+ // bad escape
+ out = append(out, s[:2]...)
+ s = s[2:]
+ } else {
+ c, err := strconv.ParseUint(s[2:2+n], 16, 8)
+ if err != nil {
+ // shouldn't really happen...
+ out = append(out, s[:2+n]...)
+ } else {
+ out = append(out, byte(c))
+ }
+ s = s[2+n:]
+ }
+ } else if s[1] >= '0' && s[1] <= '7' {
+ n := 1 + matchPrefix(s[2:], 2, isOctal)
+ c, err := strconv.ParseUint(s[1:1+n], 8, 8)
+ if err != nil || c > 0xff {
+ out = append(out, s[:1+n]...)
+ } else {
+ out = append(out, byte(c))
+ }
+ s = s[1+n:]
+ } else if s[1] == 'u' {
+ if len(s) < 6 {
+ // bad escape
+ out = append(out, s...)
+ s = s[len(s):]
+ } else {
+ c, err := strconv.ParseUint(s[2:6], 16, 16)
+ if err != nil {
+ // bad escape
+ out = append(out, s[:6]...)
+ } else {
+ w := utf8.EncodeRune(buf[:], rune(c))
+ out = append(out, buf[:w]...)
+ }
+ s = s[6:]
+ }
+ } else if s[1] == 'U' {
+ if len(s) < 10 {
+ // bad escape
+ out = append(out, s...)
+ s = s[len(s):]
+ } else {
+ c, err := strconv.ParseUint(s[2:10], 16, 32)
+ if err != nil || c > 0x10ffff {
+ // bad escape
+ out = append(out, s[:10]...)
+ } else {
+ w := utf8.EncodeRune(buf[:], rune(c))
+ out = append(out, buf[:w]...)
+ }
+ s = s[10:]
+ }
+ } else {
+ switch s[1] {
+ case 'a':
+ out = append(out, '\a')
+ case 'b':
+ out = append(out, '\b')
+ case 'f':
+ out = append(out, '\f')
+ case 'n':
+ out = append(out, '\n')
+ case 'r':
+ out = append(out, '\r')
+ case 't':
+ out = append(out, '\t')
+ case 'v':
+ out = append(out, '\v')
+ case '\\':
+ out = append(out, '\\')
+ case '\'':
+ out = append(out, '\'')
+ case '"':
+ out = append(out, '"')
+ case '?':
+ out = append(out, '?')
+ default:
+ // invalid escape, just copy it as-is
+ out = append(out, s[:2]...)
+ }
+ s = s[2:]
+ }
+ }
+ return string(out)
+}
+
+func isOctal(b byte) bool { return b >= '0' && b <= '7' }
+func isHex(b byte) bool {
+ return (b >= '0' && b <= '9') || (b >= 'a' && b <= 'f') || (b >= 'A' && b <= 'F')
+}
+func matchPrefix(s string, limit int, fn func(byte) bool) int {
+ l := len(s)
+ if l > limit {
+ l = limit
+ }
+ i := 0
+ for ; i < l; i++ {
+ if !fn(s[i]) {
+ return i
+ }
+ }
+ return i
+}
+
+// GetName returns the name of the field.
+func (fd *FieldDescriptor) GetName() string {
+ return fd.proto.GetName()
+}
+
+// GetNumber returns the tag number of this field.
+func (fd *FieldDescriptor) GetNumber() int32 {
+ return fd.proto.GetNumber()
+}
+
+// GetFullyQualifiedName returns the fully qualified name of the field. Unlike
+// GetName, this includes fully qualified name of the enclosing message for
+// regular fields.
+//
+// For extension fields, this includes the package (if there is one) as well as
+// any enclosing messages. The package and/or enclosing messages are for where
+// the extension is defined, not the message it extends.
+//
+// If this field is part of a one-of, the fully qualified name does *not*
+// include the name of the one-of, only of the enclosing message.
+func (fd *FieldDescriptor) GetFullyQualifiedName() string {
+ return fd.fqn
+}
+
+// GetParent returns the fields's enclosing descriptor. For normal
+// (non-extension) fields, this is the enclosing message. For extensions, this
+// is the descriptor in which the extension is defined, not the message that is
+// extended. The parent for an extension may be a file descriptor or a message,
+// depending on where the extension is defined.
+func (fd *FieldDescriptor) GetParent() Descriptor {
+ return fd.parent
+}
+
+// GetFile returns the descriptor for the file in which this field is defined.
+func (fd *FieldDescriptor) GetFile() *FileDescriptor {
+ return fd.file
+}
+
+// GetOptions returns the field's options. Most usages will be more interested
+// in GetFieldOptions, which has a concrete return type. This generic version
+// is present to satisfy the Descriptor interface.
+func (fd *FieldDescriptor) GetOptions() proto.Message {
+ return fd.proto.GetOptions()
+}
+
+// GetFieldOptions returns the field's options.
+func (fd *FieldDescriptor) GetFieldOptions() *dpb.FieldOptions {
+ return fd.proto.GetOptions()
+}
+
+// GetSourceInfo returns source info for the field, if present in the
+// descriptor. Not all descriptors will contain source info. If non-nil, the
+// returned info contains information about the location in the file where the
+// field was defined and also contains comments associated with the field
+// definition.
+func (fd *FieldDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+ return fd.file.sourceInfo.Get(fd.sourceInfoPath)
+}
+
+// AsProto returns the underlying descriptor proto. Most usages will be more
+// interested in AsFieldDescriptorProto, which has a concrete return type. This
+// generic version is present to satisfy the Descriptor interface.
+func (fd *FieldDescriptor) AsProto() proto.Message {
+ return fd.proto
+}
+
+// AsFieldDescriptorProto returns the underlying descriptor proto.
+func (fd *FieldDescriptor) AsFieldDescriptorProto() *dpb.FieldDescriptorProto {
+ return fd.proto
+}
+
+// String returns the underlying descriptor proto, in compact text format.
+func (fd *FieldDescriptor) String() string {
+ return fd.proto.String()
+}
+
+// GetJSONName returns the name of the field as referenced in the message's JSON
+// format.
+func (fd *FieldDescriptor) GetJSONName() string {
+ if jsonName := fd.proto.GetJsonName(); jsonName != "" {
+ return jsonName
+ }
+ return fd.proto.GetName()
+}
+
+// GetFullyQualifiedJSONName returns the JSON format name (same as GetJSONName),
+// but includes the fully qualified name of the enclosing message.
+//
+// If the field is an extension, it will return the package name (if there is
+// one) as well as the names of any enclosing messages. The package and/or
+// enclosing messages are for where the extension is defined, not the message it
+// extends.
+func (fd *FieldDescriptor) GetFullyQualifiedJSONName() string {
+ parent := fd.GetParent()
+ switch parent := parent.(type) {
+ case *FileDescriptor:
+ pkg := parent.GetPackage()
+ if pkg == "" {
+ return fd.GetJSONName()
+ }
+ return fmt.Sprintf("%s.%s", pkg, fd.GetJSONName())
+ default:
+ return fmt.Sprintf("%s.%s", parent.GetFullyQualifiedName(), fd.GetJSONName())
+ }
+}
+
+// GetOwner returns the message type that this field belongs to. If this is a normal
+// field then this is the same as GetParent. But for extensions, this will be the
+// extendee message whereas GetParent refers to where the extension was declared.
+func (fd *FieldDescriptor) GetOwner() *MessageDescriptor {
+ return fd.owner
+}
+
+// IsExtension returns true if this is an extension field.
+func (fd *FieldDescriptor) IsExtension() bool {
+ return fd.proto.GetExtendee() != ""
+}
+
+// GetOneOf returns the one-of field set to which this field belongs. If this field
+// is not part of a one-of then this method returns nil.
+func (fd *FieldDescriptor) GetOneOf() *OneOfDescriptor {
+ return fd.oneOf
+}
+
+// GetType returns the type of this field. If the type indicates an enum, the
+// enum type can be queried via GetEnumType. If the type indicates a message, the
+// message type can be queried via GetMessageType.
+func (fd *FieldDescriptor) GetType() dpb.FieldDescriptorProto_Type {
+ return fd.proto.GetType()
+}
+
+// GetLabel returns the label for this field. The label can be required (proto2-only),
+// optional (default for proto3), or required.
+func (fd *FieldDescriptor) GetLabel() dpb.FieldDescriptorProto_Label {
+ return fd.proto.GetLabel()
+}
+
+// IsRequired returns true if this field has the "required" label.
+func (fd *FieldDescriptor) IsRequired() bool {
+ return fd.proto.GetLabel() == dpb.FieldDescriptorProto_LABEL_REQUIRED
+}
+
+// IsRepeated returns true if this field has the "repeated" label.
+func (fd *FieldDescriptor) IsRepeated() bool {
+ return fd.proto.GetLabel() == dpb.FieldDescriptorProto_LABEL_REPEATED
+}
+
+// IsMap returns true if this is a map field. If so, it will have the "repeated"
+// label its type will be a message that represents a map entry. The map entry
+// message will have exactly two fields: tag #1 is the key and tag #2 is the value.
+func (fd *FieldDescriptor) IsMap() bool {
+ return fd.isMap
+}
+
+// GetMapKeyType returns the type of the key field if this is a map field. If it is
+// not a map field, nil is returned.
+func (fd *FieldDescriptor) GetMapKeyType() *FieldDescriptor {
+ if fd.isMap {
+ return fd.msgType.FindFieldByNumber(int32(1))
+ }
+ return nil
+}
+
+// GetMapValueType returns the type of the value field if this is a map field. If it
+// is not a map field, nil is returned.
+func (fd *FieldDescriptor) GetMapValueType() *FieldDescriptor {
+ if fd.isMap {
+ return fd.msgType.FindFieldByNumber(int32(2))
+ }
+ return nil
+}
+
+// GetMessageType returns the type of this field if it is a message type. If
+// this field is not a message type, it returns nil.
+func (fd *FieldDescriptor) GetMessageType() *MessageDescriptor {
+ return fd.msgType
+}
+
+// GetEnumType returns the type of this field if it is an enum type. If this
+// field is not an enum type, it returns nil.
+func (fd *FieldDescriptor) GetEnumType() *EnumDescriptor {
+ return fd.enumType
+}
+
+// GetDefaultValue returns the default value for this field.
+//
+// If this field represents a message type, this method always returns nil (even though
+// for proto2 files, the default value should be a default instance of the message type).
+// If the field represents an enum type, this method returns an int32 corresponding to the
+// enum value. If this field is a map, it returns a nil map[interface{}]interface{}. If
+// this field is repeated (and not a map), it returns a nil []interface{}.
+//
+// Otherwise, it returns the declared default value for the field or a zero value, if no
+// default is declared or if the file is proto3. The type of said return value corresponds
+// to the type of the field:
+// +-------------------------+-----------+
+// | Declared Type | Go Type |
+// +-------------------------+-----------+
+// | int32, sint32, sfixed32 | int32 |
+// | int64, sint64, sfixed64 | int64 |
+// | uint32, fixed32 | uint32 |
+// | uint64, fixed64 | uint64 |
+// | float | float32 |
+// | double | double32 |
+// | bool | bool |
+// | string | string |
+// | bytes | []byte |
+// +-------------------------+-----------+
+func (fd *FieldDescriptor) GetDefaultValue() interface{} {
+ return fd.getDefaultValue()
+}
+
+// EnumDescriptor describes an enum declared in a proto file.
+type EnumDescriptor struct {
+ proto *dpb.EnumDescriptorProto
+ parent Descriptor
+ file *FileDescriptor
+ values []*EnumValueDescriptor
+ valuesByNum sortedValues
+ fqn string
+ sourceInfoPath []int32
+}
+
+func createEnumDescriptor(fd *FileDescriptor, parent Descriptor, enclosing string, ed *dpb.EnumDescriptorProto, symbols map[string]Descriptor) (*EnumDescriptor, string) {
+ enumName := merge(enclosing, ed.GetName())
+ ret := &EnumDescriptor{proto: ed, parent: parent, file: fd, fqn: enumName}
+ for _, ev := range ed.GetValue() {
+ evd, n := createEnumValueDescriptor(fd, ret, enumName, ev)
+ symbols[n] = evd
+ ret.values = append(ret.values, evd)
+ }
+ if len(ret.values) > 0 {
+ ret.valuesByNum = make(sortedValues, len(ret.values))
+ copy(ret.valuesByNum, ret.values)
+ sort.Stable(ret.valuesByNum)
+ }
+ return ret, enumName
+}
+
+type sortedValues []*EnumValueDescriptor
+
+func (sv sortedValues) Len() int {
+ return len(sv)
+}
+
+func (sv sortedValues) Less(i, j int) bool {
+ return sv[i].GetNumber() < sv[j].GetNumber()
+}
+
+func (sv sortedValues) Swap(i, j int) {
+ sv[i], sv[j] = sv[j], sv[i]
+}
+
+func (ed *EnumDescriptor) resolve(path []int32) {
+ ed.sourceInfoPath = append([]int32(nil), path...) // defensive copy
+ path = append(path, internal.Enum_valuesTag)
+ for i, evd := range ed.values {
+ evd.resolve(append(path, int32(i)))
+ }
+}
+
+// GetName returns the simple (unqualified) name of the enum type.
+func (ed *EnumDescriptor) GetName() string {
+ return ed.proto.GetName()
+}
+
+// GetFullyQualifiedName returns the fully qualified name of the enum type.
+// This includes the package name (if there is one) as well as the names of any
+// enclosing messages.
+func (ed *EnumDescriptor) GetFullyQualifiedName() string {
+ return ed.fqn
+}
+
+// GetParent returns the enum type's enclosing descriptor. For top-level enums,
+// this will be a file descriptor. Otherwise it will be the descriptor for the
+// enclosing message.
+func (ed *EnumDescriptor) GetParent() Descriptor {
+ return ed.parent
+}
+
+// GetFile returns the descriptor for the file in which this enum is defined.
+func (ed *EnumDescriptor) GetFile() *FileDescriptor {
+ return ed.file
+}
+
+// GetOptions returns the enum type's options. Most usages will be more
+// interested in GetEnumOptions, which has a concrete return type. This generic
+// version is present to satisfy the Descriptor interface.
+func (ed *EnumDescriptor) GetOptions() proto.Message {
+ return ed.proto.GetOptions()
+}
+
+// GetEnumOptions returns the enum type's options.
+func (ed *EnumDescriptor) GetEnumOptions() *dpb.EnumOptions {
+ return ed.proto.GetOptions()
+}
+
+// GetSourceInfo returns source info for the enum type, if present in the
+// descriptor. Not all descriptors will contain source info. If non-nil, the
+// returned info contains information about the location in the file where the
+// enum type was defined and also contains comments associated with the enum
+// definition.
+func (ed *EnumDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+ return ed.file.sourceInfo.Get(ed.sourceInfoPath)
+}
+
+// AsProto returns the underlying descriptor proto. Most usages will be more
+// interested in AsEnumDescriptorProto, which has a concrete return type. This
+// generic version is present to satisfy the Descriptor interface.
+func (ed *EnumDescriptor) AsProto() proto.Message {
+ return ed.proto
+}
+
+// AsEnumDescriptorProto returns the underlying descriptor proto.
+func (ed *EnumDescriptor) AsEnumDescriptorProto() *dpb.EnumDescriptorProto {
+ return ed.proto
+}
+
+// String returns the underlying descriptor proto, in compact text format.
+func (ed *EnumDescriptor) String() string {
+ return ed.proto.String()
+}
+
+// GetValues returns all of the allowed values defined for this enum.
+func (ed *EnumDescriptor) GetValues() []*EnumValueDescriptor {
+ return ed.values
+}
+
+// FindValueByName finds the enum value with the given name. If no such value exists
+// then nil is returned.
+func (ed *EnumDescriptor) FindValueByName(name string) *EnumValueDescriptor {
+ fqn := fmt.Sprintf("%s.%s", ed.fqn, name)
+ if vd, ok := ed.file.symbols[fqn].(*EnumValueDescriptor); ok {
+ return vd
+ } else {
+ return nil
+ }
+}
+
+// FindValueByNumber finds the value with the given numeric value. If no such value
+// exists then nil is returned. If aliases are allowed and multiple values have the
+// given number, the first declared value is returned.
+func (ed *EnumDescriptor) FindValueByNumber(num int32) *EnumValueDescriptor {
+ index := sort.Search(len(ed.valuesByNum), func(i int) bool { return ed.valuesByNum[i].GetNumber() >= num })
+ if index < len(ed.valuesByNum) {
+ vd := ed.valuesByNum[index]
+ if vd.GetNumber() == num {
+ return vd
+ }
+ }
+ return nil
+}
+
+// EnumValueDescriptor describes an allowed value of an enum declared in a proto file.
+type EnumValueDescriptor struct {
+ proto *dpb.EnumValueDescriptorProto
+ parent *EnumDescriptor
+ file *FileDescriptor
+ fqn string
+ sourceInfoPath []int32
+}
+
+func createEnumValueDescriptor(fd *FileDescriptor, parent *EnumDescriptor, enclosing string, evd *dpb.EnumValueDescriptorProto) (*EnumValueDescriptor, string) {
+ valName := merge(enclosing, evd.GetName())
+ return &EnumValueDescriptor{proto: evd, parent: parent, file: fd, fqn: valName}, valName
+}
+
+func (vd *EnumValueDescriptor) resolve(path []int32) {
+ vd.sourceInfoPath = append([]int32(nil), path...) // defensive copy
+}
+
+// GetName returns the name of the enum value.
+func (vd *EnumValueDescriptor) GetName() string {
+ return vd.proto.GetName()
+}
+
+// GetNumber returns the numeric value associated with this enum value.
+func (vd *EnumValueDescriptor) GetNumber() int32 {
+ return vd.proto.GetNumber()
+}
+
+// GetFullyQualifiedName returns the fully qualified name of the enum value.
+// Unlike GetName, this includes fully qualified name of the enclosing enum.
+func (vd *EnumValueDescriptor) GetFullyQualifiedName() string {
+ return vd.fqn
+}
+
+// GetParent returns the descriptor for the enum in which this enum value is
+// defined. Most usages will prefer to use GetEnum, which has a concrete return
+// type. This more generic method is present to satisfy the Descriptor interface.
+func (vd *EnumValueDescriptor) GetParent() Descriptor {
+ return vd.parent
+}
+
+// GetEnum returns the enum in which this enum value is defined.
+func (vd *EnumValueDescriptor) GetEnum() *EnumDescriptor {
+ return vd.parent
+}
+
+// GetFile returns the descriptor for the file in which this enum value is
+// defined.
+func (vd *EnumValueDescriptor) GetFile() *FileDescriptor {
+ return vd.file
+}
+
+// GetOptions returns the enum value's options. Most usages will be more
+// interested in GetEnumValueOptions, which has a concrete return type. This
+// generic version is present to satisfy the Descriptor interface.
+func (vd *EnumValueDescriptor) GetOptions() proto.Message {
+ return vd.proto.GetOptions()
+}
+
+// GetEnumValueOptions returns the enum value's options.
+func (vd *EnumValueDescriptor) GetEnumValueOptions() *dpb.EnumValueOptions {
+ return vd.proto.GetOptions()
+}
+
+// GetSourceInfo returns source info for the enum value, if present in the
+// descriptor. Not all descriptors will contain source info. If non-nil, the
+// returned info contains information about the location in the file where the
+// enum value was defined and also contains comments associated with the enum
+// value definition.
+func (vd *EnumValueDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+ return vd.file.sourceInfo.Get(vd.sourceInfoPath)
+}
+
+// AsProto returns the underlying descriptor proto. Most usages will be more
+// interested in AsEnumValueDescriptorProto, which has a concrete return type.
+// This generic version is present to satisfy the Descriptor interface.
+func (vd *EnumValueDescriptor) AsProto() proto.Message {
+ return vd.proto
+}
+
+// AsEnumValueDescriptorProto returns the underlying descriptor proto.
+func (vd *EnumValueDescriptor) AsEnumValueDescriptorProto() *dpb.EnumValueDescriptorProto {
+ return vd.proto
+}
+
+// String returns the underlying descriptor proto, in compact text format.
+func (vd *EnumValueDescriptor) String() string {
+ return vd.proto.String()
+}
+
+// ServiceDescriptor describes an RPC service declared in a proto file.
+type ServiceDescriptor struct {
+ proto *dpb.ServiceDescriptorProto
+ file *FileDescriptor
+ methods []*MethodDescriptor
+ fqn string
+ sourceInfoPath []int32
+}
+
+func createServiceDescriptor(fd *FileDescriptor, enclosing string, sd *dpb.ServiceDescriptorProto, symbols map[string]Descriptor) (*ServiceDescriptor, string) {
+ serviceName := merge(enclosing, sd.GetName())
+ ret := &ServiceDescriptor{proto: sd, file: fd, fqn: serviceName}
+ for _, m := range sd.GetMethod() {
+ md, n := createMethodDescriptor(fd, ret, serviceName, m)
+ symbols[n] = md
+ ret.methods = append(ret.methods, md)
+ }
+ return ret, serviceName
+}
+
+func (sd *ServiceDescriptor) resolve(path []int32, scopes []scope) error {
+ sd.sourceInfoPath = append([]int32(nil), path...) // defensive copy
+ path = append(path, internal.Service_methodsTag)
+ for i, md := range sd.methods {
+ if err := md.resolve(append(path, int32(i)), scopes); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// GetName returns the simple (unqualified) name of the service.
+func (sd *ServiceDescriptor) GetName() string {
+ return sd.proto.GetName()
+}
+
+// GetFullyQualifiedName returns the fully qualified name of the service. This
+// includes the package name (if there is one).
+func (sd *ServiceDescriptor) GetFullyQualifiedName() string {
+ return sd.fqn
+}
+
+// GetParent returns the descriptor for the file in which this service is
+// defined. Most usages will prefer to use GetFile, which has a concrete return
+// type. This more generic method is present to satisfy the Descriptor interface.
+func (sd *ServiceDescriptor) GetParent() Descriptor {
+ return sd.file
+}
+
+// GetFile returns the descriptor for the file in which this service is defined.
+func (sd *ServiceDescriptor) GetFile() *FileDescriptor {
+ return sd.file
+}
+
+// GetOptions returns the service's options. Most usages will be more interested
+// in GetServiceOptions, which has a concrete return type. This generic version
+// is present to satisfy the Descriptor interface.
+func (sd *ServiceDescriptor) GetOptions() proto.Message {
+ return sd.proto.GetOptions()
+}
+
+// GetServiceOptions returns the service's options.
+func (sd *ServiceDescriptor) GetServiceOptions() *dpb.ServiceOptions {
+ return sd.proto.GetOptions()
+}
+
+// GetSourceInfo returns source info for the service, if present in the
+// descriptor. Not all descriptors will contain source info. If non-nil, the
+// returned info contains information about the location in the file where the
+// service was defined and also contains comments associated with the service
+// definition.
+func (sd *ServiceDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+ return sd.file.sourceInfo.Get(sd.sourceInfoPath)
+}
+
+// AsProto returns the underlying descriptor proto. Most usages will be more
+// interested in AsServiceDescriptorProto, which has a concrete return type.
+// This generic version is present to satisfy the Descriptor interface.
+func (sd *ServiceDescriptor) AsProto() proto.Message {
+ return sd.proto
+}
+
+// AsServiceDescriptorProto returns the underlying descriptor proto.
+func (sd *ServiceDescriptor) AsServiceDescriptorProto() *dpb.ServiceDescriptorProto {
+ return sd.proto
+}
+
+// String returns the underlying descriptor proto, in compact text format.
+func (sd *ServiceDescriptor) String() string {
+ return sd.proto.String()
+}
+
+// GetMethods returns all of the RPC methods for this service.
+func (sd *ServiceDescriptor) GetMethods() []*MethodDescriptor {
+ return sd.methods
+}
+
+// FindMethodByName finds the method with the given name. If no such method exists
+// then nil is returned.
+func (sd *ServiceDescriptor) FindMethodByName(name string) *MethodDescriptor {
+ fqn := fmt.Sprintf("%s.%s", sd.fqn, name)
+ if md, ok := sd.file.symbols[fqn].(*MethodDescriptor); ok {
+ return md
+ } else {
+ return nil
+ }
+}
+
+// MethodDescriptor describes an RPC method declared in a proto file.
+type MethodDescriptor struct {
+ proto *dpb.MethodDescriptorProto
+ parent *ServiceDescriptor
+ file *FileDescriptor
+ inType *MessageDescriptor
+ outType *MessageDescriptor
+ fqn string
+ sourceInfoPath []int32
+}
+
+func createMethodDescriptor(fd *FileDescriptor, parent *ServiceDescriptor, enclosing string, md *dpb.MethodDescriptorProto) (*MethodDescriptor, string) {
+ // request and response types get resolved later
+ methodName := merge(enclosing, md.GetName())
+ return &MethodDescriptor{proto: md, parent: parent, file: fd, fqn: methodName}, methodName
+}
+
+func (md *MethodDescriptor) resolve(path []int32, scopes []scope) error {
+ md.sourceInfoPath = append([]int32(nil), path...) // defensive copy
+ if desc, err := resolve(md.file, md.proto.GetInputType(), scopes); err != nil {
+ return err
+ } else {
+ md.inType = desc.(*MessageDescriptor)
+ }
+ if desc, err := resolve(md.file, md.proto.GetOutputType(), scopes); err != nil {
+ return err
+ } else {
+ md.outType = desc.(*MessageDescriptor)
+ }
+ return nil
+}
+
+// GetName returns the name of the method.
+func (md *MethodDescriptor) GetName() string {
+ return md.proto.GetName()
+}
+
+// GetFullyQualifiedName returns the fully qualified name of the method. Unlike
+// GetName, this includes fully qualified name of the enclosing service.
+func (md *MethodDescriptor) GetFullyQualifiedName() string {
+ return md.fqn
+}
+
+// GetParent returns the descriptor for the service in which this method is
+// defined. Most usages will prefer to use GetService, which has a concrete
+// return type. This more generic method is present to satisfy the Descriptor
+// interface.
+func (md *MethodDescriptor) GetParent() Descriptor {
+ return md.parent
+}
+
+// GetService returns the RPC service in which this method is declared.
+func (md *MethodDescriptor) GetService() *ServiceDescriptor {
+ return md.parent
+}
+
+// GetFile returns the descriptor for the file in which this method is defined.
+func (md *MethodDescriptor) GetFile() *FileDescriptor {
+ return md.file
+}
+
+// GetOptions returns the method's options. Most usages will be more interested
+// in GetMethodOptions, which has a concrete return type. This generic version
+// is present to satisfy the Descriptor interface.
+func (md *MethodDescriptor) GetOptions() proto.Message {
+ return md.proto.GetOptions()
+}
+
+// GetMethodOptions returns the method's options.
+func (md *MethodDescriptor) GetMethodOptions() *dpb.MethodOptions {
+ return md.proto.GetOptions()
+}
+
+// GetSourceInfo returns source info for the method, if present in the
+// descriptor. Not all descriptors will contain source info. If non-nil, the
+// returned info contains information about the location in the file where the
+// method was defined and also contains comments associated with the method
+// definition.
+func (md *MethodDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+ return md.file.sourceInfo.Get(md.sourceInfoPath)
+}
+
+// AsProto returns the underlying descriptor proto. Most usages will be more
+// interested in AsMethodDescriptorProto, which has a concrete return type. This
+// generic version is present to satisfy the Descriptor interface.
+func (md *MethodDescriptor) AsProto() proto.Message {
+ return md.proto
+}
+
+// AsMethodDescriptorProto returns the underlying descriptor proto.
+func (md *MethodDescriptor) AsMethodDescriptorProto() *dpb.MethodDescriptorProto {
+ return md.proto
+}
+
+// String returns the underlying descriptor proto, in compact text format.
+func (md *MethodDescriptor) String() string {
+ return md.proto.String()
+}
+
+// IsServerStreaming returns true if this is a server-streaming method.
+func (md *MethodDescriptor) IsServerStreaming() bool {
+ return md.proto.GetServerStreaming()
+}
+
+// IsClientStreaming returns true if this is a client-streaming method.
+func (md *MethodDescriptor) IsClientStreaming() bool {
+ return md.proto.GetClientStreaming()
+}
+
+// GetInputType returns the input type, or request type, of the RPC method.
+func (md *MethodDescriptor) GetInputType() *MessageDescriptor {
+ return md.inType
+}
+
+// GetOutputType returns the output type, or response type, of the RPC method.
+func (md *MethodDescriptor) GetOutputType() *MessageDescriptor {
+ return md.outType
+}
+
+// OneOfDescriptor describes a one-of field set declared in a protocol buffer message.
+type OneOfDescriptor struct {
+ proto *dpb.OneofDescriptorProto
+ parent *MessageDescriptor
+ file *FileDescriptor
+ choices []*FieldDescriptor
+ fqn string
+ sourceInfoPath []int32
+}
+
+func createOneOfDescriptor(fd *FileDescriptor, parent *MessageDescriptor, index int, enclosing string, od *dpb.OneofDescriptorProto) (*OneOfDescriptor, string) {
+ oneOfName := merge(enclosing, od.GetName())
+ ret := &OneOfDescriptor{proto: od, parent: parent, file: fd, fqn: oneOfName}
+ for _, f := range parent.fields {
+ oi := f.proto.OneofIndex
+ if oi != nil && *oi == int32(index) {
+ f.oneOf = ret
+ ret.choices = append(ret.choices, f)
+ }
+ }
+ return ret, oneOfName
+}
+
+func (od *OneOfDescriptor) resolve(path []int32) {
+ od.sourceInfoPath = append([]int32(nil), path...) // defensive copy
+}
+
+// GetName returns the name of the one-of.
+func (od *OneOfDescriptor) GetName() string {
+ return od.proto.GetName()
+}
+
+// GetFullyQualifiedName returns the fully qualified name of the one-of. Unlike
+// GetName, this includes fully qualified name of the enclosing message.
+func (od *OneOfDescriptor) GetFullyQualifiedName() string {
+ return od.fqn
+}
+
+// GetParent returns the descriptor for the message in which this one-of is
+// defined. Most usages will prefer to use GetOwner, which has a concrete
+// return type. This more generic method is present to satisfy the Descriptor
+// interface.
+func (od *OneOfDescriptor) GetParent() Descriptor {
+ return od.parent
+}
+
+// GetOwner returns the message to which this one-of field set belongs.
+func (od *OneOfDescriptor) GetOwner() *MessageDescriptor {
+ return od.parent
+}
+
+// GetFile returns the descriptor for the file in which this one-fof is defined.
+func (od *OneOfDescriptor) GetFile() *FileDescriptor {
+ return od.file
+}
+
+// GetOptions returns the one-of's options. Most usages will be more interested
+// in GetOneOfOptions, which has a concrete return type. This generic version
+// is present to satisfy the Descriptor interface.
+func (od *OneOfDescriptor) GetOptions() proto.Message {
+ return od.proto.GetOptions()
+}
+
+// GetOneOfOptions returns the one-of's options.
+func (od *OneOfDescriptor) GetOneOfOptions() *dpb.OneofOptions {
+ return od.proto.GetOptions()
+}
+
+// GetSourceInfo returns source info for the one-of, if present in the
+// descriptor. Not all descriptors will contain source info. If non-nil, the
+// returned info contains information about the location in the file where the
+// one-of was defined and also contains comments associated with the one-of
+// definition.
+func (od *OneOfDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
+ return od.file.sourceInfo.Get(od.sourceInfoPath)
+}
+
+// AsProto returns the underlying descriptor proto. Most usages will be more
+// interested in AsOneofDescriptorProto, which has a concrete return type. This
+// generic version is present to satisfy the Descriptor interface.
+func (od *OneOfDescriptor) AsProto() proto.Message {
+ return od.proto
+}
+
+// AsOneofDescriptorProto returns the underlying descriptor proto.
+func (od *OneOfDescriptor) AsOneofDescriptorProto() *dpb.OneofDescriptorProto {
+ return od.proto
+}
+
+// String returns the underlying descriptor proto, in compact text format.
+func (od *OneOfDescriptor) String() string {
+ return od.proto.String()
+}
+
+// GetChoices returns the fields that are part of the one-of field set. At most one of
+// these fields may be set for a given message.
+func (od *OneOfDescriptor) GetChoices() []*FieldDescriptor {
+ return od.choices
+}
+
+// scope represents a lexical scope in a proto file in which messages and enums
+// can be declared.
+type scope func(string) Descriptor
+
+func fileScope(fd *FileDescriptor) scope {
+ // we search symbols in this file, but also symbols in other files that have
+ // the same package as this file or a "parent" package (in protobuf,
+ // packages are a hierarchy like C++ namespaces)
+ prefixes := internal.CreatePrefixList(fd.proto.GetPackage())
+ return func(name string) Descriptor {
+ for _, prefix := range prefixes {
+ n := merge(prefix, name)
+ d := findSymbol(fd, n, false)
+ if d != nil {
+ return d
+ }
+ }
+ return nil
+ }
+}
+
+func messageScope(md *MessageDescriptor) scope {
+ return func(name string) Descriptor {
+ n := merge(md.fqn, name)
+ if d, ok := md.file.symbols[n]; ok {
+ return d
+ }
+ return nil
+ }
+}
+
+func resolve(fd *FileDescriptor, name string, scopes []scope) (Descriptor, error) {
+ if strings.HasPrefix(name, ".") {
+ // already fully-qualified
+ d := findSymbol(fd, name[1:], false)
+ if d != nil {
+ return d, nil
+ }
+ } else {
+ // unqualified, so we look in the enclosing (last) scope first and move
+ // towards outermost (first) scope, trying to resolve the symbol
+ for i := len(scopes) - 1; i >= 0; i-- {
+ d := scopes[i](name)
+ if d != nil {
+ return d, nil
+ }
+ }
+ }
+ return nil, fmt.Errorf("file %q included an unresolvable reference to %q", fd.proto.GetName(), name)
+}
+
+func findSymbol(fd *FileDescriptor, name string, public bool) Descriptor {
+ d := fd.symbols[name]
+ if d != nil {
+ return d
+ }
+
+ // When public = false, we are searching only directly imported symbols. But we
+ // also need to search transitive public imports due to semantics of public imports.
+ var deps []*FileDescriptor
+ if public {
+ deps = fd.publicDeps
+ } else {
+ deps = fd.deps
+ }
+ for _, dep := range deps {
+ d = findSymbol(dep, name, true)
+ if d != nil {
+ return d
+ }
+ }
+
+ return nil
+}
+
+func merge(a, b string) string {
+ if a == "" {
+ return b
+ } else {
+ return a + "." + b
+ }
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/descriptor_no_unsafe.go b/vendor/github.com/jhump/protoreflect/desc/descriptor_no_unsafe.go
new file mode 100644
index 0000000..cd7348e
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/descriptor_no_unsafe.go
@@ -0,0 +1,31 @@
+//+build appengine gopherjs purego
+// NB: other environments where unsafe is unappropriate should use "purego" build tag
+// https://github.com/golang/go/issues/23172
+
+package desc
+
+type jsonNameMap struct{}
+type memoizedDefault struct{}
+
+// FindFieldByJSONName finds the field with the given JSON field name. If no such
+// field exists then nil is returned. Only regular fields are returned, not
+// extensions.
+func (md *MessageDescriptor) FindFieldByJSONName(jsonName string) *FieldDescriptor {
+ // NB: With allowed use of unsafe, we use it to atomically define an index
+ // via atomic.LoadPointer/atomic.StorePointer. Without it, we skip the index
+ // and do an linear scan of fields each time.
+ for _, f := range md.fields {
+ jn := f.proto.GetJsonName()
+ if jn == "" {
+ jn = f.proto.GetName()
+ }
+ if jn == jsonName {
+ return f
+ }
+ }
+ return nil
+}
+
+func (fd *FieldDescriptor) getDefaultValue() interface{} {
+ return fd.determineDefault()
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/descriptor_unsafe.go b/vendor/github.com/jhump/protoreflect/desc/descriptor_unsafe.go
new file mode 100644
index 0000000..19b808d
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/descriptor_unsafe.go
@@ -0,0 +1,60 @@
+//+build !appengine,!gopherjs,!purego
+// NB: other environments where unsafe is unappropriate should use "purego" build tag
+// https://github.com/golang/go/issues/23172
+
+package desc
+
+import (
+ "sync/atomic"
+ "unsafe"
+)
+
+type jsonNameMap map[string]*FieldDescriptor // loaded/stored atomically via atomic+unsafe
+type memoizedDefault *interface{} // loaded/stored atomically via atomic+unsafe
+
+// FindFieldByJSONName finds the field with the given JSON field name. If no such
+// field exists then nil is returned. Only regular fields are returned, not
+// extensions.
+func (md *MessageDescriptor) FindFieldByJSONName(jsonName string) *FieldDescriptor {
+ // NB: We don't want to eagerly index JSON names because many programs won't use it.
+ // So we want to do it lazily, but also make sure the result is thread-safe. So we
+ // atomically load/store the map as if it were a normal pointer. We don't use other
+ // mechanisms -- like sync.Mutex, sync.RWMutex, sync.Once, or atomic.Value -- to
+ // do this lazily because those types cannot be copied, and we'd rather not induce
+ // 'go vet' errors in programs that use descriptors and try to copy them.
+ // If multiple goroutines try to access the index at the same time, before it is
+ // built, they will all end up computing the index redundantly. Future reads of
+ // the index will use whatever was the "last one stored" by those racing goroutines.
+ // Since building the index is deterministic, this is fine: all indices computed
+ // will be the same.
+ addrOfJsonNames := (*unsafe.Pointer)(unsafe.Pointer(&md.jsonNames))
+ jsonNames := atomic.LoadPointer(addrOfJsonNames)
+ var index map[string]*FieldDescriptor
+ if jsonNames == nil {
+ // slow path: compute the index
+ index = map[string]*FieldDescriptor{}
+ for _, f := range md.fields {
+ jn := f.proto.GetJsonName()
+ if jn == "" {
+ jn = f.proto.GetName()
+ }
+ index[jn] = f
+ }
+ atomic.StorePointer(addrOfJsonNames, *(*unsafe.Pointer)(unsafe.Pointer(&index)))
+ } else {
+ *(*unsafe.Pointer)(unsafe.Pointer(&index)) = jsonNames
+ }
+ return index[jsonName]
+}
+
+func (fd *FieldDescriptor) getDefaultValue() interface{} {
+ addrOfDef := (*unsafe.Pointer)(unsafe.Pointer(&fd.def))
+ def := atomic.LoadPointer(addrOfDef)
+ if def != nil {
+ return *(*interface{})(def)
+ }
+ // slow path: compute the default, potentially involves decoding value
+ d := fd.determineDefault()
+ atomic.StorePointer(addrOfDef, (unsafe.Pointer(&d)))
+ return d
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/doc.go b/vendor/github.com/jhump/protoreflect/desc/doc.go
new file mode 100644
index 0000000..1740dce
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/doc.go
@@ -0,0 +1,41 @@
+// Package desc contains "rich descriptors" for protocol buffers. The built-in
+// descriptor types are simple protobuf messages, each one representing a
+// different kind of element in the AST of a .proto source file.
+//
+// Because of this inherent "tree" quality, these build-in descriptors cannot
+// refer to their enclosing file descriptor. Nor can a field descriptor refer to
+// a message or enum descriptor that represents the field's type (for enum and
+// nested message fields). All such links must instead be stringly typed. This
+// limitation makes them much harder to use for doing interesting things with
+// reflection.
+//
+// Without this package, resolving references to types is particularly complex.
+// For example, resolving a field's type, the message type an extension extends,
+// or the request and response types of an RPC method all require searching
+// through symbols defined not only in the file in which these elements are
+// declared but also in its transitive closure of dependencies.
+//
+// "Rich descriptors" avoid the need to deal with the complexities described
+// above. A rich descriptor has all type references resolved and provides
+// methods to access other rich descriptors for all referenced elements. Each
+// rich descriptor has a usefully broad API, but does not try to mimic the full
+// interface of the underlying descriptor proto. Instead, every rich descriptor
+// provides access to that underlying proto, for extracting descriptor
+// properties that are not immediately accessible through rich descriptor's
+// methods.
+//
+// Rich descriptors can be accessed in similar ways as their "poor" cousins
+// (descriptor protos). Instead of using proto.FileDescriptor, use
+// desc.LoadFileDescriptor. Message descriptors and extension field descriptors
+// can also be easily accessed using desc.LoadMessageDescriptor and
+// desc.LoadFieldDescriptorForExtension, respectively.
+//
+// It is also possible create rich descriptors for proto messages that a given
+// Go program doesn't even know about. For example, they could be loaded from a
+// FileDescriptorSet file (which can be generated by protoc) or loaded from a
+// server. This enables interesting things like dynamic clients: where a Go
+// program can be an RPC client of a service it wasn't compiled to know about.
+//
+// Also see the grpcreflect, dynamic, and grpcdynamic packages in this same
+// repo to see just how useful rich descriptors really are.
+package desc
diff --git a/vendor/github.com/jhump/protoreflect/desc/imports.go b/vendor/github.com/jhump/protoreflect/desc/imports.go
new file mode 100644
index 0000000..ab93032
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/imports.go
@@ -0,0 +1,313 @@
+package desc
+
+import (
+ "fmt"
+ "path/filepath"
+ "reflect"
+ "strings"
+ "sync"
+
+ "github.com/golang/protobuf/proto"
+ dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+)
+
+var (
+ globalImportPathConf map[string]string
+ globalImportPathMu sync.RWMutex
+)
+
+// RegisterImportPath registers an alternate import path for a given registered
+// proto file path. For more details on why alternate import paths may need to
+// be configured, see ImportResolver.
+//
+// This method panics if provided invalid input. An empty importPath is invalid.
+// An un-registered registerPath is also invalid. For example, if an attempt is
+// made to register the import path "foo/bar.proto" as "bar.proto", but there is
+// no "bar.proto" registered in the Go protobuf runtime, this method will panic.
+// This method also panics if an attempt is made to register the same import
+// path more than once.
+//
+// This function works globally, applying to all descriptors loaded by this
+// package. If you instead want more granular support for handling alternate
+// import paths -- such as for a single invocation of a function in this
+// package or when the alternate path is only used from one file (so you don't
+// want the alternate path used when loading every other file), use an
+// ImportResolver instead.
+func RegisterImportPath(registerPath, importPath string) {
+ if len(importPath) == 0 {
+ panic("import path cannot be empty")
+ }
+ desc := proto.FileDescriptor(registerPath)
+ if len(desc) == 0 {
+ panic(fmt.Sprintf("path %q is not a registered proto file", registerPath))
+ }
+ globalImportPathMu.Lock()
+ defer globalImportPathMu.Unlock()
+ if reg := globalImportPathConf[importPath]; reg != "" {
+ panic(fmt.Sprintf("import path %q already registered for %s", importPath, reg))
+ }
+ if globalImportPathConf == nil {
+ globalImportPathConf = map[string]string{}
+ }
+ globalImportPathConf[importPath] = registerPath
+}
+
+// ResolveImport resolves the given import path. If it has been registered as an
+// alternate via RegisterImportPath, the registered path is returned. Otherwise,
+// the given import path is returned unchanged.
+func ResolveImport(importPath string) string {
+ importPath = clean(importPath)
+ globalImportPathMu.RLock()
+ defer globalImportPathMu.RUnlock()
+ reg := globalImportPathConf[importPath]
+ if reg == "" {
+ return importPath
+ }
+ return reg
+}
+
+// ImportResolver lets you work-around linking issues that are caused by
+// mismatches between how a particular proto source file is registered in the Go
+// protobuf runtime and how that same file is imported by other files. The file
+// is registered using the same relative path given to protoc when the file is
+// compiled (i.e. when Go code is generated). So if any file tries to import
+// that source file, but using a different relative path, then a link error will
+// occur when this package tries to load a descriptor for the importing file.
+//
+// For example, let's say we have two proto source files: "foo/bar.proto" and
+// "fubar/baz.proto". The latter imports the former using a line like so:
+// import "foo/bar.proto";
+// However, when protoc is invoked, the command-line args looks like so:
+// protoc -Ifoo/ --go_out=foo/ bar.proto
+// protoc -I./ -Ifubar/ --go_out=fubar/ baz.proto
+// Because the path given to protoc is just "bar.proto" and "baz.proto", this is
+// how they are registered in the Go protobuf runtime. So, when loading the
+// descriptor for "fubar/baz.proto", we'll see an import path of "foo/bar.proto"
+// but will find no file registered with that path:
+// fd, err := desc.LoadFileDescriptor("baz.proto")
+// // err will be non-nil, complaining that there is no such file
+// // found named "foo/bar.proto"
+//
+// This can be remedied by registering alternate import paths using an
+// ImportResolver. Continuing with the example above, the code below would fix
+// any link issue:
+// var r desc.ImportResolver
+// r.RegisterImportPath("bar.proto", "foo/bar.proto")
+// fd, err := r.LoadFileDescriptor("baz.proto")
+// // err will be nil; descriptor successfully loaded!
+//
+// If there are files that are *always* imported using a different relative
+// path then how they are registered, consider using the global
+// RegisterImportPath function, so you don't have to use an ImportResolver for
+// every file that imports it.
+type ImportResolver struct {
+ children map[string]*ImportResolver
+ importPaths map[string]string
+
+ // By default, an ImportResolver will fallback to consulting any paths
+ // registered via the top-level RegisterImportPath function. Setting this
+ // field to true will cause the ImportResolver to skip that fallback and
+ // only examine its own locally registered paths.
+ SkipFallbackRules bool
+}
+
+// ResolveImport resolves the given import path in the context of the given
+// source file. If a matching alternate has been registered with this resolver
+// via a call to RegisterImportPath or RegisterImportPathFrom, then the
+// registered path is returned. Otherwise, the given import path is returned
+// unchanged.
+func (r *ImportResolver) ResolveImport(source, importPath string) string {
+ if r != nil {
+ res := r.resolveImport(clean(source), clean(importPath))
+ if res != "" {
+ return res
+ }
+ if r.SkipFallbackRules {
+ return importPath
+ }
+ }
+ return ResolveImport(importPath)
+}
+
+func (r *ImportResolver) resolveImport(source, importPath string) string {
+ if source == "" {
+ return r.importPaths[importPath]
+ }
+ var car, cdr string
+ idx := strings.IndexRune(source, filepath.Separator)
+ if idx < 0 {
+ car, cdr = source, ""
+ } else {
+ car, cdr = source[:idx], source[idx+1:]
+ }
+ ch := r.children[car]
+ if ch != nil {
+ if reg := ch.resolveImport(cdr, importPath); reg != "" {
+ return reg
+ }
+ }
+ return r.importPaths[importPath]
+}
+
+// RegisterImportPath registers an alternate import path for a given registered
+// proto file path with this resolver. Any appearance of the given import path
+// when linking files will instead try to link the given registered path. If the
+// registered path cannot be located, then linking will fallback to the actual
+// imported path.
+//
+// This method will panic if given an empty path or if the same import path is
+// registered more than once.
+//
+// To constrain the contexts where the given import path is to be re-written,
+// use RegisterImportPathFrom instead.
+func (r *ImportResolver) RegisterImportPath(registerPath, importPath string) {
+ r.RegisterImportPathFrom(registerPath, importPath, "")
+}
+
+// RegisterImportPathFrom registers an alternate import path for a given
+// registered proto file path with this resolver, but only for imports in the
+// specified source context.
+//
+// The source context can be the name of a folder or a proto source file. Any
+// appearance of the given import path in that context will instead try to link
+// the given registered path. To be in context, the file that is being linked
+// (i.e. the one whose import statement is being resolved) must be the same
+// relative path of the source context or be a sub-path (i.e. a descendant of
+// the source folder).
+//
+// If the registered path cannot be located, then linking will fallback to the
+// actual imported path.
+//
+// This method will panic if given an empty path. The source context, on the
+// other hand, is allowed to be blank. A blank source matches all files. This
+// method also panics if the same import path is registered in the same source
+// context more than once.
+func (r *ImportResolver) RegisterImportPathFrom(registerPath, importPath, source string) {
+ importPath = clean(importPath)
+ if len(importPath) == 0 {
+ panic("import path cannot be empty")
+ }
+ registerPath = clean(registerPath)
+ if len(registerPath) == 0 {
+ panic("registered path cannot be empty")
+ }
+ r.registerImportPathFrom(registerPath, importPath, clean(source))
+}
+
+func (r *ImportResolver) registerImportPathFrom(registerPath, importPath, source string) {
+ if source == "" {
+ if r.importPaths == nil {
+ r.importPaths = map[string]string{}
+ } else if reg := r.importPaths[importPath]; reg != "" {
+ panic(fmt.Sprintf("already registered import path %q as %q", importPath, registerPath))
+ }
+ r.importPaths[importPath] = registerPath
+ return
+ }
+ var car, cdr string
+ idx := strings.IndexRune(source, filepath.Separator)
+ if idx < 0 {
+ car, cdr = source, ""
+ } else {
+ car, cdr = source[:idx], source[idx+1:]
+ }
+ ch := r.children[car]
+ if ch == nil {
+ if r.children == nil {
+ r.children = map[string]*ImportResolver{}
+ }
+ ch = &ImportResolver{}
+ r.children[car] = ch
+ }
+ ch.registerImportPathFrom(registerPath, importPath, cdr)
+}
+
+// LoadFileDescriptor is the same as the package function of the same name, but
+// any alternate paths configured in this resolver are used when linking the
+// given descriptor proto.
+func (r *ImportResolver) LoadFileDescriptor(filePath string) (*FileDescriptor, error) {
+ return loadFileDescriptor(filePath, r)
+}
+
+// LoadMessageDescriptor is the same as the package function of the same name,
+// but any alternate paths configured in this resolver are used when linking
+// files for the returned descriptor.
+func (r *ImportResolver) LoadMessageDescriptor(msgName string) (*MessageDescriptor, error) {
+ return loadMessageDescriptor(msgName, r)
+}
+
+// LoadMessageDescriptorForMessage is the same as the package function of the
+// same name, but any alternate paths configured in this resolver are used when
+// linking files for the returned descriptor.
+func (r *ImportResolver) LoadMessageDescriptorForMessage(msg proto.Message) (*MessageDescriptor, error) {
+ return loadMessageDescriptorForMessage(msg, r)
+}
+
+// LoadMessageDescriptorForType is the same as the package function of the same
+// name, but any alternate paths configured in this resolver are used when
+// linking files for the returned descriptor.
+func (r *ImportResolver) LoadMessageDescriptorForType(msgType reflect.Type) (*MessageDescriptor, error) {
+ return loadMessageDescriptorForType(msgType, r)
+}
+
+// LoadEnumDescriptorForEnum is the same as the package function of the same
+// name, but any alternate paths configured in this resolver are used when
+// linking files for the returned descriptor.
+func (r *ImportResolver) LoadEnumDescriptorForEnum(enum protoEnum) (*EnumDescriptor, error) {
+ return loadEnumDescriptorForEnum(enum, r)
+}
+
+// LoadEnumDescriptorForType is the same as the package function of the same
+// name, but any alternate paths configured in this resolver are used when
+// linking files for the returned descriptor.
+func (r *ImportResolver) LoadEnumDescriptorForType(enumType reflect.Type) (*EnumDescriptor, error) {
+ return loadEnumDescriptorForType(enumType, r)
+}
+
+// LoadFieldDescriptorForExtension is the same as the package function of the
+// same name, but any alternate paths configured in this resolver are used when
+// linking files for the returned descriptor.
+func (r *ImportResolver) LoadFieldDescriptorForExtension(ext *proto.ExtensionDesc) (*FieldDescriptor, error) {
+ return loadFieldDescriptorForExtension(ext, r)
+}
+
+// CreateFileDescriptor is the same as the package function of the same name,
+// but any alternate paths configured in this resolver are used when linking the
+// given descriptor proto.
+func (r *ImportResolver) CreateFileDescriptor(fdp *dpb.FileDescriptorProto, deps ...*FileDescriptor) (*FileDescriptor, error) {
+ return createFileDescriptor(fdp, deps, r)
+}
+
+// CreateFileDescriptors is the same as the package function of the same name,
+// but any alternate paths configured in this resolver are used when linking the
+// given descriptor protos.
+func (r *ImportResolver) CreateFileDescriptors(fds []*dpb.FileDescriptorProto) (map[string]*FileDescriptor, error) {
+ return createFileDescriptors(fds, r)
+}
+
+// CreateFileDescriptorFromSet is the same as the package function of the same
+// name, but any alternate paths configured in this resolver are used when
+// linking the descriptor protos in the given set.
+func (r *ImportResolver) CreateFileDescriptorFromSet(fds *dpb.FileDescriptorSet) (*FileDescriptor, error) {
+ return createFileDescriptorFromSet(fds, r)
+}
+
+// CreateFileDescriptorsFromSet is the same as the package function of the same
+// name, but any alternate paths configured in this resolver are used when
+// linking the descriptor protos in the given set.
+func (r *ImportResolver) CreateFileDescriptorsFromSet(fds *dpb.FileDescriptorSet) (map[string]*FileDescriptor, error) {
+ return createFileDescriptorsFromSet(fds, r)
+}
+
+const dotPrefix = "." + string(filepath.Separator)
+
+func clean(path string) string {
+ if path == "" {
+ return ""
+ }
+ path = filepath.Clean(path)
+ if path == "." {
+ return ""
+ }
+ return strings.TrimPrefix(path, dotPrefix)
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go b/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go
new file mode 100644
index 0000000..b4150b8
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go
@@ -0,0 +1,107 @@
+package internal
+
+import (
+ dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+)
+
+// SourceInfoMap is a map of paths in a descriptor to the corresponding source
+// code info.
+type SourceInfoMap map[string][]*dpb.SourceCodeInfo_Location
+
+// Get returns the source code info for the given path. If there are
+// multiple locations for the same path, the first one is returned.
+func (m SourceInfoMap) Get(path []int32) *dpb.SourceCodeInfo_Location {
+ v := m[asMapKey(path)]
+ if len(v) > 0 {
+ return v[0]
+ }
+ return nil
+}
+
+// GetAll returns all source code info for the given path.
+func (m SourceInfoMap) GetAll(path []int32) []*dpb.SourceCodeInfo_Location {
+ return m[asMapKey(path)]
+}
+
+// Add stores the given source code info for the given path.
+func (m SourceInfoMap) Add(path []int32, loc *dpb.SourceCodeInfo_Location) {
+ m[asMapKey(path)] = append(m[asMapKey(path)], loc)
+}
+
+// PutIfAbsent stores the given source code info for the given path only if the
+// given path does not exist in the map. This method returns true when the value
+// is stored, false if the path already exists.
+func (m SourceInfoMap) PutIfAbsent(path []int32, loc *dpb.SourceCodeInfo_Location) bool {
+ k := asMapKey(path)
+ if _, ok := m[k]; ok {
+ return false
+ }
+ m[k] = []*dpb.SourceCodeInfo_Location{loc}
+ return true
+}
+
+func asMapKey(slice []int32) string {
+ // NB: arrays should be usable as map keys, but this does not
+ // work due to a bug: https://github.com/golang/go/issues/22605
+ //rv := reflect.ValueOf(slice)
+ //arrayType := reflect.ArrayOf(rv.Len(), rv.Type().Elem())
+ //array := reflect.New(arrayType).Elem()
+ //reflect.Copy(array, rv)
+ //return array.Interface()
+
+ b := make([]byte, len(slice)*4)
+ j := 0
+ for _, s := range slice {
+ b[j] = byte(s)
+ b[j+1] = byte(s >> 8)
+ b[j+2] = byte(s >> 16)
+ b[j+3] = byte(s >> 24)
+ j += 4
+ }
+ return string(b)
+}
+
+// CreateSourceInfoMap constructs a new SourceInfoMap and populates it with the
+// source code info in the given file descriptor proto.
+func CreateSourceInfoMap(fd *dpb.FileDescriptorProto) SourceInfoMap {
+ res := SourceInfoMap{}
+ PopulateSourceInfoMap(fd, res)
+ return res
+}
+
+// PopulateSourceInfoMap populates the given SourceInfoMap with information from
+// the given file descriptor.
+func PopulateSourceInfoMap(fd *dpb.FileDescriptorProto, m SourceInfoMap) {
+ for _, l := range fd.GetSourceCodeInfo().GetLocation() {
+ m.Add(l.Path, l)
+ }
+}
+
+// NB: This wonkiness allows desc.Descriptor impl to implement an interface that
+// is only usable from this package, by embedding a SourceInfoComputeFunc that
+// implements the actual logic (which must live in desc package to avoid a
+// dependency cycle).
+
+// SourceInfoComputer is a single method which will be invoked to recompute
+// source info. This is needed for the protoparse package, which needs to link
+// descriptors without source info in order to interpret options, but then needs
+// to re-compute source info after that interpretation so that final linked
+// descriptors expose the right info.
+type SourceInfoComputer interface {
+ recomputeSourceInfo()
+}
+
+// SourceInfoComputeFunc is the type that a desc.Descriptor will embed. It will
+// be aliased in the desc package to an unexported name so it is not marked as
+// an exported field in reflection and not present in Go docs.
+type SourceInfoComputeFunc func()
+
+func (f SourceInfoComputeFunc) recomputeSourceInfo() {
+ f()
+}
+
+// RecomputeSourceInfo is used to initiate recomputation of source info. This is
+// is used by the protoparse package, after it interprets options.
+func RecomputeSourceInfo(c SourceInfoComputer) {
+ c.recomputeSourceInfo()
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/internal/util.go b/vendor/github.com/jhump/protoreflect/desc/internal/util.go
new file mode 100644
index 0000000..139c9cd
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/internal/util.go
@@ -0,0 +1,270 @@
+package internal
+
+import (
+ "unicode"
+ "unicode/utf8"
+)
+
+const (
+ // MaxTag is the maximum allowed tag number for a field.
+ MaxTag = 536870911 // 2^29 - 1
+
+ // SpecialReservedStart is the first tag in a range that is reserved and not
+ // allowed for use in message definitions.
+ SpecialReservedStart = 19000
+ // SpecialReservedEnd is the last tag in a range that is reserved and not
+ // allowed for use in message definitions.
+ SpecialReservedEnd = 19999
+
+ // NB: It would be nice to use constants from generated code instead of
+ // hard-coding these here. But code-gen does not emit these as constants
+ // anywhere. The only places they appear in generated code are struct tags
+ // on fields of the generated descriptor protos.
+
+ // File_packageTag is the tag number of the package element in a file
+ // descriptor proto.
+ File_packageTag = 2
+ // File_dependencyTag is the tag number of the dependencies element in a
+ // file descriptor proto.
+ File_dependencyTag = 3
+ // File_messagesTag is the tag number of the messages element in a file
+ // descriptor proto.
+ File_messagesTag = 4
+ // File_enumsTag is the tag number of the enums element in a file descriptor
+ // proto.
+ File_enumsTag = 5
+ // File_servicesTag is the tag number of the services element in a file
+ // descriptor proto.
+ File_servicesTag = 6
+ // File_extensionsTag is the tag number of the extensions element in a file
+ // descriptor proto.
+ File_extensionsTag = 7
+ // File_optionsTag is the tag number of the options element in a file
+ // descriptor proto.
+ File_optionsTag = 8
+ // File_syntaxTag is the tag number of the syntax element in a file
+ // descriptor proto.
+ File_syntaxTag = 12
+ // Message_nameTag is the tag number of the name element in a message
+ // descriptor proto.
+ Message_nameTag = 1
+ // Message_fieldsTag is the tag number of the fields element in a message
+ // descriptor proto.
+ Message_fieldsTag = 2
+ // Message_nestedMessagesTag is the tag number of the nested messages
+ // element in a message descriptor proto.
+ Message_nestedMessagesTag = 3
+ // Message_enumsTag is the tag number of the enums element in a message
+ // descriptor proto.
+ Message_enumsTag = 4
+ // Message_extensionRangeTag is the tag number of the extension ranges
+ // element in a message descriptor proto.
+ Message_extensionRangeTag = 5
+ // Message_extensionsTag is the tag number of the extensions element in a
+ // message descriptor proto.
+ Message_extensionsTag = 6
+ // Message_optionsTag is the tag number of the options element in a message
+ // descriptor proto.
+ Message_optionsTag = 7
+ // Message_oneOfsTag is the tag number of the one-ofs element in a message
+ // descriptor proto.
+ Message_oneOfsTag = 8
+ // Message_reservedRangeTag is the tag number of the reserved ranges element
+ // in a message descriptor proto.
+ Message_reservedRangeTag = 9
+ // Message_reservedNameTag is the tag number of the reserved names element
+ // in a message descriptor proto.
+ Message_reservedNameTag = 10
+ // ExtensionRange_startTag is the tag number of the start index in an
+ // extension range proto.
+ ExtensionRange_startTag = 1
+ // ExtensionRange_endTag is the tag number of the end index in an
+ // extension range proto.
+ ExtensionRange_endTag = 2
+ // ExtensionRange_optionsTag is the tag number of the options element in an
+ // extension range proto.
+ ExtensionRange_optionsTag = 3
+ // ReservedRange_startTag is the tag number of the start index in a reserved
+ // range proto.
+ ReservedRange_startTag = 1
+ // ReservedRange_endTag is the tag number of the end index in a reserved
+ // range proto.
+ ReservedRange_endTag = 2
+ // Field_nameTag is the tag number of the name element in a field descriptor
+ // proto.
+ Field_nameTag = 1
+ // Field_extendeeTag is the tag number of the extendee element in a field
+ // descriptor proto.
+ Field_extendeeTag = 2
+ // Field_numberTag is the tag number of the number element in a field
+ // descriptor proto.
+ Field_numberTag = 3
+ // Field_labelTag is the tag number of the label element in a field
+ // descriptor proto.
+ Field_labelTag = 4
+ // Field_typeTag is the tag number of the type element in a field descriptor
+ // proto.
+ Field_typeTag = 5
+ // Field_typeNameTag is the tag number of the type name element in a field
+ // descriptor proto.
+ Field_typeNameTag = 6
+ // Field_defaultTag is the tag number of the default value element in a
+ // field descriptor proto.
+ Field_defaultTag = 7
+ // Field_optionsTag is the tag number of the options element in a field
+ // descriptor proto.
+ Field_optionsTag = 8
+ // Field_jsonNameTag is the tag number of the JSON name element in a field
+ // descriptor proto.
+ Field_jsonNameTag = 10
+ // OneOf_nameTag is the tag number of the name element in a one-of
+ // descriptor proto.
+ OneOf_nameTag = 1
+ // OneOf_optionsTag is the tag number of the options element in a one-of
+ // descriptor proto.
+ OneOf_optionsTag = 2
+ // Enum_nameTag is the tag number of the name element in an enum descriptor
+ // proto.
+ Enum_nameTag = 1
+ // Enum_valuesTag is the tag number of the values element in an enum
+ // descriptor proto.
+ Enum_valuesTag = 2
+ // Enum_optionsTag is the tag number of the options element in an enum
+ // descriptor proto.
+ Enum_optionsTag = 3
+ // Enum_reservedRangeTag is the tag number of the reserved ranges element in
+ // an enum descriptor proto.
+ Enum_reservedRangeTag = 4
+ // Enum_reservedNameTag is the tag number of the reserved names element in
+ // an enum descriptor proto.
+ Enum_reservedNameTag = 5
+ // EnumVal_nameTag is the tag number of the name element in an enum value
+ // descriptor proto.
+ EnumVal_nameTag = 1
+ // EnumVal_numberTag is the tag number of the number element in an enum
+ // value descriptor proto.
+ EnumVal_numberTag = 2
+ // EnumVal_optionsTag is the tag number of the options element in an enum
+ // value descriptor proto.
+ EnumVal_optionsTag = 3
+ // Service_nameTag is the tag number of the name element in a service
+ // descriptor proto.
+ Service_nameTag = 1
+ // Service_methodsTag is the tag number of the methods element in a service
+ // descriptor proto.
+ Service_methodsTag = 2
+ // Service_optionsTag is the tag number of the options element in a service
+ // descriptor proto.
+ Service_optionsTag = 3
+ // Method_nameTag is the tag number of the name element in a method
+ // descriptor proto.
+ Method_nameTag = 1
+ // Method_inputTag is the tag number of the input type element in a method
+ // descriptor proto.
+ Method_inputTag = 2
+ // Method_outputTag is the tag number of the output type element in a method
+ // descriptor proto.
+ Method_outputTag = 3
+ // Method_optionsTag is the tag number of the options element in a method
+ // descriptor proto.
+ Method_optionsTag = 4
+ // Method_inputStreamTag is the tag number of the input stream flag in a
+ // method descriptor proto.
+ Method_inputStreamTag = 5
+ // Method_outputStreamTag is the tag number of the output stream flag in a
+ // method descriptor proto.
+ Method_outputStreamTag = 6
+
+ // UninterpretedOptionsTag is the tag number of the uninterpreted options
+ // element. All *Options messages use the same tag for the field that stores
+ // uninterpreted options.
+ UninterpretedOptionsTag = 999
+
+ // Uninterpreted_nameTag is the tag number of the name element in an
+ // uninterpreted options proto.
+ Uninterpreted_nameTag = 2
+ // Uninterpreted_identTag is the tag number of the identifier value in an
+ // uninterpreted options proto.
+ Uninterpreted_identTag = 3
+ // Uninterpreted_posIntTag is the tag number of the positive int value in an
+ // uninterpreted options proto.
+ Uninterpreted_posIntTag = 4
+ // Uninterpreted_negIntTag is the tag number of the negative int value in an
+ // uninterpreted options proto.
+ Uninterpreted_negIntTag = 5
+ // Uninterpreted_doubleTag is the tag number of the double value in an
+ // uninterpreted options proto.
+ Uninterpreted_doubleTag = 6
+ // Uninterpreted_stringTag is the tag number of the string value in an
+ // uninterpreted options proto.
+ Uninterpreted_stringTag = 7
+ // Uninterpreted_aggregateTag is the tag number of the aggregate value in an
+ // uninterpreted options proto.
+ Uninterpreted_aggregateTag = 8
+ // UninterpretedName_nameTag is the tag number of the name element in an
+ // uninterpreted option name proto.
+ UninterpretedName_nameTag = 1
+)
+
+// JsonName returns the default JSON name for a field with the given name.
+func JsonName(name string) string {
+ var js []rune
+ nextUpper := false
+ for i, r := range name {
+ if r == '_' {
+ nextUpper = true
+ continue
+ }
+ if i == 0 {
+ js = append(js, r)
+ } else if nextUpper {
+ nextUpper = false
+ js = append(js, unicode.ToUpper(r))
+ } else {
+ js = append(js, r)
+ }
+ }
+ return string(js)
+}
+
+// InitCap returns the given field name, but with the first letter capitalized.
+func InitCap(name string) string {
+ r, sz := utf8.DecodeRuneInString(name)
+ return string(unicode.ToUpper(r)) + name[sz:]
+}
+
+// CreatePrefixList returns a list of package prefixes to search when resolving
+// a symbol name. If the given package is blank, it returns only the empty
+// string. If the given package contains only one token, e.g. "foo", it returns
+// that token and the empty string, e.g. ["foo", ""]. Otherwise, it returns
+// successively shorter prefixes of the package and then the empty string. For
+// example, for a package named "foo.bar.baz" it will return the following list:
+// ["foo.bar.baz", "foo.bar", "foo", ""]
+func CreatePrefixList(pkg string) []string {
+ if pkg == "" {
+ return []string{""}
+ }
+
+ numDots := 0
+ // one pass to pre-allocate the returned slice
+ for i := 0; i < len(pkg); i++ {
+ if pkg[i] == '.' {
+ numDots++
+ }
+ }
+ if numDots == 0 {
+ return []string{pkg, ""}
+ }
+
+ prefixes := make([]string, numDots+2)
+ // second pass to fill in returned slice
+ for i := 0; i < len(pkg); i++ {
+ if pkg[i] == '.' {
+ prefixes[numDots] = pkg[:i]
+ numDots--
+ }
+ }
+ prefixes[0] = pkg
+
+ return prefixes
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/load.go b/vendor/github.com/jhump/protoreflect/desc/load.go
new file mode 100644
index 0000000..4a05830
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/load.go
@@ -0,0 +1,341 @@
+package desc
+
+import (
+ "fmt"
+ "reflect"
+ "sync"
+
+ "github.com/golang/protobuf/proto"
+ dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+ "github.com/jhump/protoreflect/internal"
+)
+
+var (
+ cacheMu sync.RWMutex
+ filesCache = map[string]*FileDescriptor{}
+ messagesCache = map[string]*MessageDescriptor{}
+ enumCache = map[reflect.Type]*EnumDescriptor{}
+)
+
+// LoadFileDescriptor creates a file descriptor using the bytes returned by
+// proto.FileDescriptor. Descriptors are cached so that they do not need to be
+// re-processed if the same file is fetched again later.
+func LoadFileDescriptor(file string) (*FileDescriptor, error) {
+ return loadFileDescriptor(file, nil)
+}
+
+func loadFileDescriptor(file string, r *ImportResolver) (*FileDescriptor, error) {
+ f := getFileFromCache(file)
+ if f != nil {
+ return f, nil
+ }
+ cacheMu.Lock()
+ defer cacheMu.Unlock()
+ return loadFileDescriptorLocked(file, r)
+}
+
+func loadFileDescriptorLocked(file string, r *ImportResolver) (*FileDescriptor, error) {
+ f := filesCache[file]
+ if f != nil {
+ return f, nil
+ }
+ fd, err := internal.LoadFileDescriptor(file)
+ if err != nil {
+ return nil, err
+ }
+
+ f, err = toFileDescriptorLocked(fd, r)
+ if err != nil {
+ return nil, err
+ }
+ putCacheLocked(file, f)
+ return f, nil
+}
+
+func toFileDescriptorLocked(fd *dpb.FileDescriptorProto, r *ImportResolver) (*FileDescriptor, error) {
+ deps := make([]*FileDescriptor, len(fd.GetDependency()))
+ for i, dep := range fd.GetDependency() {
+ resolvedDep := r.ResolveImport(fd.GetName(), dep)
+ var err error
+ deps[i], err = loadFileDescriptorLocked(resolvedDep, r)
+ if _, ok := err.(internal.ErrNoSuchFile); ok && resolvedDep != dep {
+ // try original path
+ deps[i], err = loadFileDescriptorLocked(dep, r)
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+ return CreateFileDescriptor(fd, deps...)
+}
+
+func getFileFromCache(file string) *FileDescriptor {
+ cacheMu.RLock()
+ defer cacheMu.RUnlock()
+ return filesCache[file]
+}
+
+func putCacheLocked(filename string, fd *FileDescriptor) {
+ filesCache[filename] = fd
+ putMessageCacheLocked(fd.messages)
+}
+
+func putMessageCacheLocked(mds []*MessageDescriptor) {
+ for _, md := range mds {
+ messagesCache[md.fqn] = md
+ putMessageCacheLocked(md.nested)
+ }
+}
+
+// interface implemented by generated messages, which all have a Descriptor() method in
+// addition to the methods of proto.Message
+type protoMessage interface {
+ proto.Message
+ Descriptor() ([]byte, []int)
+}
+
+// LoadMessageDescriptor loads descriptor using the encoded descriptor proto returned by
+// Message.Descriptor() for the given message type. If the given type is not recognized,
+// then a nil descriptor is returned.
+func LoadMessageDescriptor(message string) (*MessageDescriptor, error) {
+ return loadMessageDescriptor(message, nil)
+}
+
+func loadMessageDescriptor(message string, r *ImportResolver) (*MessageDescriptor, error) {
+ m := getMessageFromCache(message)
+ if m != nil {
+ return m, nil
+ }
+
+ pt := proto.MessageType(message)
+ if pt == nil {
+ return nil, nil
+ }
+ msg, err := messageFromType(pt)
+ if err != nil {
+ return nil, err
+ }
+
+ cacheMu.Lock()
+ defer cacheMu.Unlock()
+ return loadMessageDescriptorForTypeLocked(message, msg, r)
+}
+
+// LoadMessageDescriptorForType loads descriptor using the encoded descriptor proto returned
+// by message.Descriptor() for the given message type. If the given type is not recognized,
+// then a nil descriptor is returned.
+func LoadMessageDescriptorForType(messageType reflect.Type) (*MessageDescriptor, error) {
+ return loadMessageDescriptorForType(messageType, nil)
+}
+
+func loadMessageDescriptorForType(messageType reflect.Type, r *ImportResolver) (*MessageDescriptor, error) {
+ m, err := messageFromType(messageType)
+ if err != nil {
+ return nil, err
+ }
+ return loadMessageDescriptorForMessage(m, r)
+}
+
+// LoadMessageDescriptorForMessage loads descriptor using the encoded descriptor proto
+// returned by message.Descriptor(). If the given type is not recognized, then a nil
+// descriptor is returned.
+func LoadMessageDescriptorForMessage(message proto.Message) (*MessageDescriptor, error) {
+ return loadMessageDescriptorForMessage(message, nil)
+}
+
+func loadMessageDescriptorForMessage(message proto.Message, r *ImportResolver) (*MessageDescriptor, error) {
+ // efficiently handle dynamic messages
+ type descriptorable interface {
+ GetMessageDescriptor() *MessageDescriptor
+ }
+ if d, ok := message.(descriptorable); ok {
+ return d.GetMessageDescriptor(), nil
+ }
+
+ name := proto.MessageName(message)
+ if name == "" {
+ return nil, nil
+ }
+ m := getMessageFromCache(name)
+ if m != nil {
+ return m, nil
+ }
+
+ cacheMu.Lock()
+ defer cacheMu.Unlock()
+ return loadMessageDescriptorForTypeLocked(name, message.(protoMessage), nil)
+}
+
+func messageFromType(mt reflect.Type) (protoMessage, error) {
+ if mt.Kind() != reflect.Ptr {
+ mt = reflect.PtrTo(mt)
+ }
+ m, ok := reflect.Zero(mt).Interface().(protoMessage)
+ if !ok {
+ return nil, fmt.Errorf("failed to create message from type: %v", mt)
+ }
+ return m, nil
+}
+
+func loadMessageDescriptorForTypeLocked(name string, message protoMessage, r *ImportResolver) (*MessageDescriptor, error) {
+ m := messagesCache[name]
+ if m != nil {
+ return m, nil
+ }
+
+ fdb, _ := message.Descriptor()
+ fd, err := internal.DecodeFileDescriptor(name, fdb)
+ if err != nil {
+ return nil, err
+ }
+
+ f, err := toFileDescriptorLocked(fd, r)
+ if err != nil {
+ return nil, err
+ }
+ putCacheLocked(fd.GetName(), f)
+ return f.FindSymbol(name).(*MessageDescriptor), nil
+}
+
+func getMessageFromCache(message string) *MessageDescriptor {
+ cacheMu.RLock()
+ defer cacheMu.RUnlock()
+ return messagesCache[message]
+}
+
+// interface implemented by all generated enums
+type protoEnum interface {
+ EnumDescriptor() ([]byte, []int)
+}
+
+// NB: There is no LoadEnumDescriptor that takes a fully-qualified enum name because
+// it is not useful since protoc-gen-go does not expose the name anywhere in generated
+// code or register it in a way that is it accessible for reflection code. This also
+// means we have to cache enum descriptors differently -- we can only cache them as
+// they are requested, as opposed to caching all enum types whenever a file descriptor
+// is cached. This is because we need to know the generated type of the enums, and we
+// don't know that at the time of caching file descriptors.
+
+// LoadEnumDescriptorForType loads descriptor using the encoded descriptor proto returned
+// by enum.EnumDescriptor() for the given enum type.
+func LoadEnumDescriptorForType(enumType reflect.Type) (*EnumDescriptor, error) {
+ return loadEnumDescriptorForType(enumType, nil)
+}
+
+func loadEnumDescriptorForType(enumType reflect.Type, r *ImportResolver) (*EnumDescriptor, error) {
+ // we cache descriptors using non-pointer type
+ if enumType.Kind() == reflect.Ptr {
+ enumType = enumType.Elem()
+ }
+ e := getEnumFromCache(enumType)
+ if e != nil {
+ return e, nil
+ }
+ enum, err := enumFromType(enumType)
+ if err != nil {
+ return nil, err
+ }
+
+ cacheMu.Lock()
+ defer cacheMu.Unlock()
+ return loadEnumDescriptorForTypeLocked(enumType, enum, r)
+}
+
+// LoadEnumDescriptorForEnum loads descriptor using the encoded descriptor proto
+// returned by enum.EnumDescriptor().
+func LoadEnumDescriptorForEnum(enum protoEnum) (*EnumDescriptor, error) {
+ return loadEnumDescriptorForEnum(enum, nil)
+}
+
+func loadEnumDescriptorForEnum(enum protoEnum, r *ImportResolver) (*EnumDescriptor, error) {
+ et := reflect.TypeOf(enum)
+ // we cache descriptors using non-pointer type
+ if et.Kind() == reflect.Ptr {
+ et = et.Elem()
+ enum = reflect.Zero(et).Interface().(protoEnum)
+ }
+ e := getEnumFromCache(et)
+ if e != nil {
+ return e, nil
+ }
+
+ cacheMu.Lock()
+ defer cacheMu.Unlock()
+ return loadEnumDescriptorForTypeLocked(et, enum, r)
+}
+
+func enumFromType(et reflect.Type) (protoEnum, error) {
+ if et.Kind() != reflect.Int32 {
+ et = reflect.PtrTo(et)
+ }
+ e, ok := reflect.Zero(et).Interface().(protoEnum)
+ if !ok {
+ return nil, fmt.Errorf("failed to create enum from type: %v", et)
+ }
+ return e, nil
+}
+
+func loadEnumDescriptorForTypeLocked(et reflect.Type, enum protoEnum, r *ImportResolver) (*EnumDescriptor, error) {
+ e := enumCache[et]
+ if e != nil {
+ return e, nil
+ }
+
+ fdb, path := enum.EnumDescriptor()
+ name := fmt.Sprintf("%v", et)
+ fd, err := internal.DecodeFileDescriptor(name, fdb)
+ if err != nil {
+ return nil, err
+ }
+ // see if we already have cached "rich" descriptor
+ f, ok := filesCache[fd.GetName()]
+ if !ok {
+ f, err = toFileDescriptorLocked(fd, r)
+ if err != nil {
+ return nil, err
+ }
+ putCacheLocked(fd.GetName(), f)
+ }
+
+ ed := findEnum(f, path)
+ enumCache[et] = ed
+ return ed, nil
+}
+
+func getEnumFromCache(et reflect.Type) *EnumDescriptor {
+ cacheMu.RLock()
+ defer cacheMu.RUnlock()
+ return enumCache[et]
+}
+
+func findEnum(fd *FileDescriptor, path []int) *EnumDescriptor {
+ if len(path) == 1 {
+ return fd.GetEnumTypes()[path[0]]
+ }
+ md := fd.GetMessageTypes()[path[0]]
+ for _, i := range path[1 : len(path)-1] {
+ md = md.GetNestedMessageTypes()[i]
+ }
+ return md.GetNestedEnumTypes()[path[len(path)-1]]
+}
+
+// LoadFieldDescriptorForExtension loads the field descriptor that corresponds to the given
+// extension description.
+func LoadFieldDescriptorForExtension(ext *proto.ExtensionDesc) (*FieldDescriptor, error) {
+ return loadFieldDescriptorForExtension(ext, nil)
+}
+
+func loadFieldDescriptorForExtension(ext *proto.ExtensionDesc, r *ImportResolver) (*FieldDescriptor, error) {
+ file, err := loadFileDescriptor(ext.Filename, r)
+ if err != nil {
+ return nil, err
+ }
+ field, ok := file.FindSymbol(ext.Name).(*FieldDescriptor)
+ // make sure descriptor agrees with attributes of the ExtensionDesc
+ if !ok || !field.IsExtension() || field.GetOwner().GetFullyQualifiedName() != proto.MessageName(ext.ExtendedType) ||
+ field.GetNumber() != ext.Field {
+ return nil, fmt.Errorf("file descriptor contained unexpected object with name %s", ext.Name)
+ }
+ return field, nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/binary.go b/vendor/github.com/jhump/protoreflect/dynamic/binary.go
new file mode 100644
index 0000000..91fd672
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/binary.go
@@ -0,0 +1,185 @@
+package dynamic
+
+// Binary serialization and de-serialization for dynamic messages
+
+import (
+ "fmt"
+ "github.com/golang/protobuf/proto"
+ "github.com/jhump/protoreflect/codec"
+ "io"
+)
+
+// defaultDeterminism, if true, will mean that calls to Marshal will produce
+// deterministic output. This is used to make the output of proto.Marshal(...)
+// deterministic (since there is no way to have that convey determinism intent).
+// **This is only used from tests.**
+var defaultDeterminism = false
+
+// Marshal serializes this message to bytes, returning an error if the operation
+// fails. The resulting bytes are in the standard protocol buffer binary format.
+func (m *Message) Marshal() ([]byte, error) {
+ var b codec.Buffer
+ b.SetDeterministic(defaultDeterminism)
+ if err := m.marshal(&b); err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
+
+// MarshalAppend behaves exactly the same as Marshal, except instead of allocating a
+// new byte slice to marshal into, it uses the provided byte slice. The backing array
+// for the returned byte slice *may* be the same as the one that was passed in, but
+// it's not guaranteed as a new backing array will automatically be allocated if
+// more bytes need to be written than the provided buffer has capacity for.
+func (m *Message) MarshalAppend(b []byte) ([]byte, error) {
+ codedBuf := codec.NewBuffer(b)
+ codedBuf.SetDeterministic(defaultDeterminism)
+ if err := m.marshal(codedBuf); err != nil {
+ return nil, err
+ }
+ return codedBuf.Bytes(), nil
+}
+
+// MarshalDeterministic serializes this message to bytes in a deterministic way,
+// returning an error if the operation fails. This differs from Marshal in that
+// map keys will be sorted before serializing to bytes. The protobuf spec does
+// not define ordering for map entries, so Marshal will use standard Go map
+// iteration order (which will be random). But for cases where determinism is
+// more important than performance, use this method instead.
+func (m *Message) MarshalDeterministic() ([]byte, error) {
+ var b codec.Buffer
+ b.SetDeterministic(true)
+ if err := m.marshal(&b); err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
+
+// MarshalAppendDeterministic behaves exactly the same as MarshalDeterministic,
+// except instead of allocating a new byte slice to marshal into, it uses the
+// provided byte slice. The backing array for the returned byte slice *may* be
+// the same as the one that was passed in, but it's not guaranteed as a new
+// backing array will automatically be allocated if more bytes need to be written
+// than the provided buffer has capacity for.
+func (m *Message) MarshalAppendDeterministic(b []byte) ([]byte, error) {
+ codedBuf := codec.NewBuffer(b)
+ codedBuf.SetDeterministic(true)
+ if err := m.marshal(codedBuf); err != nil {
+ return nil, err
+ }
+ return codedBuf.Bytes(), nil
+}
+
+func (m *Message) marshal(b *codec.Buffer) error {
+ if err := m.marshalKnownFields(b); err != nil {
+ return err
+ }
+ return m.marshalUnknownFields(b)
+}
+
+func (m *Message) marshalKnownFields(b *codec.Buffer) error {
+ for _, tag := range m.knownFieldTags() {
+ itag := int32(tag)
+ val := m.values[itag]
+ fd := m.FindFieldDescriptor(itag)
+ if fd == nil {
+ panic(fmt.Sprintf("Couldn't find field for tag %d", itag))
+ }
+ if err := b.EncodeFieldValue(fd, val); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (m *Message) marshalUnknownFields(b *codec.Buffer) error {
+ for _, tag := range m.unknownFieldTags() {
+ itag := int32(tag)
+ sl := m.unknownFields[itag]
+ for _, u := range sl {
+ if err := b.EncodeTagAndWireType(itag, u.Encoding); err != nil {
+ return err
+ }
+ switch u.Encoding {
+ case proto.WireBytes:
+ if err := b.EncodeRawBytes(u.Contents); err != nil {
+ return err
+ }
+ case proto.WireStartGroup:
+ _, _ = b.Write(u.Contents)
+ if err := b.EncodeTagAndWireType(itag, proto.WireEndGroup); err != nil {
+ return err
+ }
+ case proto.WireFixed32:
+ if err := b.EncodeFixed32(u.Value); err != nil {
+ return err
+ }
+ case proto.WireFixed64:
+ if err := b.EncodeFixed64(u.Value); err != nil {
+ return err
+ }
+ case proto.WireVarint:
+ if err := b.EncodeVarint(u.Value); err != nil {
+ return err
+ }
+ default:
+ return codec.ErrBadWireType
+ }
+ }
+ }
+ return nil
+}
+
+// Unmarshal de-serializes the message that is present in the given bytes into
+// this message. It first resets the current message. It returns an error if the
+// given bytes do not contain a valid encoding of this message type.
+func (m *Message) Unmarshal(b []byte) error {
+ m.Reset()
+ if err := m.UnmarshalMerge(b); err != nil {
+ return err
+ }
+ return m.Validate()
+}
+
+// UnmarshalMerge de-serializes the message that is present in the given bytes
+// into this message. Unlike Unmarshal, it does not first reset the message,
+// instead merging the data in the given bytes into the existing data in this
+// message.
+func (m *Message) UnmarshalMerge(b []byte) error {
+ return m.unmarshal(codec.NewBuffer(b), false)
+}
+
+func (m *Message) unmarshal(buf *codec.Buffer, isGroup bool) error {
+ for !buf.EOF() {
+ fd, val, err := buf.DecodeFieldValue(m.FindFieldDescriptor, m.mf)
+ if err != nil {
+ if err == codec.ErrWireTypeEndGroup {
+ if isGroup {
+ // finished parsing group
+ return nil
+ }
+ return codec.ErrBadWireType
+ }
+ return err
+ }
+
+ if fd == nil {
+ if m.unknownFields == nil {
+ m.unknownFields = map[int32][]UnknownField{}
+ }
+ uv := val.(codec.UnknownField)
+ u := UnknownField{
+ Encoding: uv.Encoding,
+ Value: uv.Value,
+ Contents: uv.Contents,
+ }
+ m.unknownFields[uv.Tag] = append(m.unknownFields[uv.Tag], u)
+ } else if err := mergeField(m, fd, val); err != nil {
+ return err
+ }
+ }
+ if isGroup {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/doc.go b/vendor/github.com/jhump/protoreflect/dynamic/doc.go
new file mode 100644
index 0000000..c329fcd
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/doc.go
@@ -0,0 +1,163 @@
+// Package dynamic provides an implementation for a dynamic protobuf message.
+//
+// The dynamic message is essentially a message descriptor along with a map of
+// tag numbers to values. It has a broad API for interacting with the message,
+// including inspection and modification. Generally, most operations have two
+// forms: a regular method that panics on bad input or error and a "Try" form
+// of the method that will instead return an error.
+//
+// A dynamic message can optionally be constructed with a MessageFactory. The
+// MessageFactory has various registries that may be used by the dynamic message,
+// such as during de-serialization. The message factory is "inherited" by any
+// other dynamic messages created, such as nested messages that are created
+// during de-serialization. Similarly, any dynamic message created using
+// MessageFactory.NewMessage will be associated with that factory, which in turn
+// will be used to create other messages or parse extension fields during
+// de-serialization.
+//
+//
+// Field Types
+//
+// The types of values expected by setters and returned by getters are the
+// same as protoc generates for scalar fields. For repeated fields, there are
+// methods for getting and setting values at a particular index or for adding
+// an element. Similarly, for map fields, there are methods for getting and
+// setting values for a particular key.
+//
+// If you use GetField for a repeated field, it will return a copy of all
+// elements as a slice []interface{}. Similarly, using GetField for a map field
+// will return a copy of all mappings as a map[interface{}]interface{}. You can
+// also use SetField to supply an entire slice or map for repeated or map fields.
+// The slice need not be []interface{} but can actually be typed according to
+// the field's expected type. For example, a repeated uint64 field can be set
+// using a slice of type []uint64.
+//
+// Descriptors for map fields describe them as repeated fields with a nested
+// message type. The nested message type is a special generated type that
+// represents a single mapping: key and value pair. The dynamic message has some
+// special affordances for this representation. For example, you can use
+// SetField to set a map field using a slice of these entry messages. Internally,
+// the slice of entries will be converted to an actual map. Similarly, you can
+// use AddRepeatedField with an entry message to add (or overwrite) a mapping.
+// However, you cannot use GetRepeatedField or SetRepeatedField to modify maps,
+// since those take numeric index arguments which are not relevant to maps
+// (since maps in Go have no defined ordering).
+//
+// When setting field values in dynamic messages, the type-checking is lenient
+// in that it accepts any named type with the right kind. So a string field can
+// be assigned to any type that is defined as a string. Enum fields require
+// int32 values (or any type that is defined as an int32).
+//
+// Unlike normal use of numeric values in Go, values will be automatically
+// widened when assigned. So, for example, an int64 field can be set using an
+// int32 value since it can be safely widened without truncation or loss of
+// precision. Similar goes for uint32 values being converted to uint64 and
+// float32 being converted to float64. Narrowing conversions are not done,
+// however. Also, unsigned values will never be automatically converted to
+// signed (and vice versa), and floating point values will never be
+// automatically converted to integral values (and vice versa). Since the bit
+// width of int and uint fields is allowed to be platform dependent, but will
+// always be less than or equal to 64, they can only be used as values for
+// int64 and uint64 fields, respectively. They cannot be used to set int32 or
+// uint32 fields, which includes enums fields.
+//
+// Fields whose type is a nested message can have values set to either other
+// dynamic messages or generated messages (e.g. pointers to structs generated by
+// protoc). Getting a value for such a field will return the actual type it is
+// set to (e.g. either a dynamic message or a generated message). If the value
+// is not set and the message uses proto2 syntax, the default message returned
+// will be whatever is returned by the dynamic message's MessageFactory (if the
+// dynamic message was not created with a factory, it will use the logic of the
+// zero value factory). In most typical cases, it will return a dynamic message,
+// but if the factory is configured with a KnownTypeRegistry, or if the field's
+// type is a well-known type, it will return a zero value generated message.
+//
+//
+// Unrecognized Fields
+//
+// Unrecognized fields are preserved by the dynamic message when unmarshaling
+// from the standard binary format. If the message's MessageFactory was
+// configured with an ExtensionRegistry, it will be used to identify and parse
+// extension fields for the message.
+//
+// Unrecognized fields can dynamically become recognized fields if the
+// application attempts to retrieve an unrecognized field's value using a
+// FieldDescriptor. In this case, the given FieldDescriptor is used to parse the
+// unknown field and move the parsed value into the message's set of known
+// fields. This behavior is most suited to the use of extensions, where an
+// ExtensionRegistry is not setup with all known extensions ahead of time. But
+// it can even happen for non-extension fields! Here's an example scenario where
+// a non-extension field can initially be unknown and become known:
+//
+// 1. A dynamic message is created with a descriptor, A, and then
+// de-serialized from a stream of bytes. The stream includes an
+// unrecognized tag T. The message will include tag T in its unrecognized
+// field set.
+// 2. Another call site retrieves a newer descriptor, A', which includes a
+// newly added field with tag T.
+// 3. That other call site then uses a FieldDescriptor to access the value of
+// the new field. This will cause the dynamic message to parse the bytes
+// for the unknown tag T and store them as a known field.
+// 4. Subsequent operations for tag T, including setting the field using only
+// tag number or de-serializing a stream that includes tag T, will operate
+// as if that tag were part of the original descriptor, A.
+//
+//
+// Compatibility
+//
+// In addition to implementing the proto.Message interface, the included
+// Message type also provides an XXX_MessageName() method, so it can work with
+// proto.MessageName. And it provides a Descriptor() method that behaves just
+// like the method of the same signature in messages generated by protoc.
+// Because of this, it is actually compatible with proto.Message in many (though
+// not all) contexts. In particular, it is compatible with proto.Marshal and
+// proto.Unmarshal for serializing and de-serializing messages.
+//
+// The dynamic message supports binary and text marshaling, using protobuf's
+// well-defined binary format and the same text format that protoc-generated
+// types use. It also supports JSON serialization/de-serialization by
+// implementing the json.Marshaler and json.Unmarshaler interfaces. And dynamic
+// messages can safely be used with the jsonpb package for JSON serialization
+// and de-serialization.
+//
+// In addition to implementing the proto.Message interface and numerous related
+// methods, it also provides inter-op with generated messages via conversion.
+// The ConvertTo, ConvertFrom, MergeInto, and MergeFrom methods copy message
+// contents from a dynamic message to a generated message and vice versa.
+//
+// When copying from a generated message into a dynamic message, if the
+// generated message contains fields unknown to the dynamic message (e.g. not
+// present in the descriptor used to create the dynamic message), these fields
+// become known to the dynamic message (as per behavior described above in
+// "Unrecognized Fields"). If the generated message has unrecognized fields of
+// its own, including unrecognized extensions, they are preserved in the dynamic
+// message. It is possible that the dynamic message knows about fields that the
+// generated message did not, like if it has a different version of the
+// descriptor or its MessageFactory has an ExtensionRegistry that knows about
+// different extensions than were linked into the program. In this case, these
+// unrecognized fields in the generated message will be known fields in the
+// dynamic message.
+//
+// Similarly, when copying from a dynamic message into a generated message, if
+// the dynamic message has unrecognized fields they can be preserved in the
+// generated message (currently only for syntax proto2 since proto3 generated
+// messages do not preserve unrecognized fields). If the generated message knows
+// about fields that the dynamic message does not, these unrecognized fields may
+// become known fields in the generated message.
+//
+//
+// Registries
+//
+// This package also contains a couple of registries, for managing known types
+// and descriptors.
+//
+// The KnownTypeRegistry allows de-serialization of a dynamic message to use
+// generated message types, instead of dynamic messages, for some kinds of
+// nested message fields. This is particularly useful for working with proto
+// messages that have special encodings as JSON (e.g. the well-known types),
+// since the dynamic message does not try to handle these special cases in its
+// JSON marshaling facilities.
+//
+// The ExtensionRegistry allows for recognizing and parsing extensions fields
+// (for proto2 messages).
+package dynamic
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/dynamic_message.go b/vendor/github.com/jhump/protoreflect/dynamic/dynamic_message.go
new file mode 100644
index 0000000..3f19d6b
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/dynamic_message.go
@@ -0,0 +1,2688 @@
+package dynamic
+
+import (
+ "bytes"
+ "compress/gzip"
+ "errors"
+ "fmt"
+ "reflect"
+ "sort"
+ "strings"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+ "github.com/jhump/protoreflect/codec"
+ "github.com/jhump/protoreflect/desc"
+)
+
+// ErrUnknownTagNumber is an error that is returned when an operation refers
+// to an unknown tag number.
+var ErrUnknownTagNumber = errors.New("unknown tag number")
+
+// UnknownTagNumberError is the same as ErrUnknownTagNumber.
+// Deprecated: use ErrUnknownTagNumber
+var UnknownTagNumberError = ErrUnknownTagNumber
+
+// ErrUnknownFieldName is an error that is returned when an operation refers
+// to an unknown field name.
+var ErrUnknownFieldName = errors.New("unknown field name")
+
+// UnknownFieldNameError is the same as ErrUnknownFieldName.
+// Deprecated: use ErrUnknownFieldName
+var UnknownFieldNameError = ErrUnknownFieldName
+
+// ErrFieldIsNotMap is an error that is returned when map-related operations
+// are attempted with fields that are not maps.
+var ErrFieldIsNotMap = errors.New("field is not a map type")
+
+// FieldIsNotMapError is the same as ErrFieldIsNotMap.
+// Deprecated: use ErrFieldIsNotMap
+var FieldIsNotMapError = ErrFieldIsNotMap
+
+// ErrFieldIsNotRepeated is an error that is returned when repeated field
+// operations are attempted with fields that are not repeated.
+var ErrFieldIsNotRepeated = errors.New("field is not repeated")
+
+// FieldIsNotRepeatedError is the same as ErrFieldIsNotRepeated.
+// Deprecated: use ErrFieldIsNotRepeated
+var FieldIsNotRepeatedError = ErrFieldIsNotRepeated
+
+// ErrIndexOutOfRange is an error that is returned when an invalid index is
+// provided when access a single element of a repeated field.
+var ErrIndexOutOfRange = errors.New("index is out of range")
+
+// IndexOutOfRangeError is the same as ErrIndexOutOfRange.
+// Deprecated: use ErrIndexOutOfRange
+var IndexOutOfRangeError = ErrIndexOutOfRange
+
+// ErrNumericOverflow is an error returned by operations that encounter a
+// numeric value that is too large, for example de-serializing a value into an
+// int32 field when the value is larger that can fit into a 32-bit value.
+var ErrNumericOverflow = errors.New("numeric value is out of range")
+
+// NumericOverflowError is the same as ErrNumericOverflow.
+// Deprecated: use ErrNumericOverflow
+var NumericOverflowError = ErrNumericOverflow
+
+var typeOfProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
+var typeOfDynamicMessage = reflect.TypeOf((*Message)(nil))
+var typeOfBytes = reflect.TypeOf(([]byte)(nil))
+
+// Message is a dynamic protobuf message. Instead of a generated struct,
+// like most protobuf messages, this is a map of field number to values and
+// a message descriptor, which is used to validate the field values and
+// also to de-serialize messages (from the standard binary format, as well
+// as from the text format and from JSON).
+type Message struct {
+ md *desc.MessageDescriptor
+ er *ExtensionRegistry
+ mf *MessageFactory
+ extraFields map[int32]*desc.FieldDescriptor
+ values map[int32]interface{}
+ unknownFields map[int32][]UnknownField
+}
+
+// UnknownField represents a field that was parsed from the binary wire
+// format for a message, but was not a recognized field number. Enough
+// information is preserved so that re-serializing the message won't lose
+// any of the unrecognized data.
+type UnknownField struct {
+ // Encoding indicates how the unknown field was encoded on the wire. If it
+ // is proto.WireBytes or proto.WireGroupStart then Contents will be set to
+ // the raw bytes. If it is proto.WireTypeFixed32 then the data is in the least
+ // significant 32 bits of Value. Otherwise, the data is in all 64 bits of
+ // Value.
+ Encoding int8
+ Contents []byte
+ Value uint64
+}
+
+// NewMessage creates a new dynamic message for the type represented by the given
+// message descriptor. During de-serialization, a default MessageFactory is used to
+// instantiate any nested message fields and no extension fields will be parsed. To
+// use a custom MessageFactory or ExtensionRegistry, use MessageFactory.NewMessage.
+func NewMessage(md *desc.MessageDescriptor) *Message {
+ return NewMessageWithMessageFactory(md, nil)
+}
+
+// NewMessageWithExtensionRegistry creates a new dynamic message for the type
+// represented by the given message descriptor. During de-serialization, the given
+// ExtensionRegistry is used to parse extension fields and nested messages will be
+// instantiated using dynamic.NewMessageFactoryWithExtensionRegistry(er).
+func NewMessageWithExtensionRegistry(md *desc.MessageDescriptor, er *ExtensionRegistry) *Message {
+ mf := NewMessageFactoryWithExtensionRegistry(er)
+ return NewMessageWithMessageFactory(md, mf)
+}
+
+// NewMessageWithMessageFactory creates a new dynamic message for the type
+// represented by the given message descriptor. During de-serialization, the given
+// MessageFactory is used to instantiate nested messages.
+func NewMessageWithMessageFactory(md *desc.MessageDescriptor, mf *MessageFactory) *Message {
+ var er *ExtensionRegistry
+ if mf != nil {
+ er = mf.er
+ }
+ return &Message{
+ md: md,
+ mf: mf,
+ er: er,
+ }
+}
+
+// AsDynamicMessage converts the given message to a dynamic message. If the
+// given message is dynamic, it is returned. Otherwise, a dynamic message is
+// created using NewMessage.
+func AsDynamicMessage(msg proto.Message) (*Message, error) {
+ return AsDynamicMessageWithMessageFactory(msg, nil)
+}
+
+// AsDynamicMessageWithExtensionRegistry converts the given message to a dynamic
+// message. If the given message is dynamic, it is returned. Otherwise, a
+// dynamic message is created using NewMessageWithExtensionRegistry.
+func AsDynamicMessageWithExtensionRegistry(msg proto.Message, er *ExtensionRegistry) (*Message, error) {
+ mf := NewMessageFactoryWithExtensionRegistry(er)
+ return AsDynamicMessageWithMessageFactory(msg, mf)
+}
+
+// AsDynamicMessageWithMessageFactory converts the given message to a dynamic
+// message. If the given message is dynamic, it is returned. Otherwise, a
+// dynamic message is created using NewMessageWithMessageFactory.
+func AsDynamicMessageWithMessageFactory(msg proto.Message, mf *MessageFactory) (*Message, error) {
+ if dm, ok := msg.(*Message); ok {
+ return dm, nil
+ }
+ md, err := desc.LoadMessageDescriptorForMessage(msg)
+ if err != nil {
+ return nil, err
+ }
+ dm := NewMessageWithMessageFactory(md, mf)
+ err = dm.mergeFrom(msg)
+ if err != nil {
+ return nil, err
+ }
+ return dm, nil
+}
+
+// GetMessageDescriptor returns a descriptor for this message's type.
+func (m *Message) GetMessageDescriptor() *desc.MessageDescriptor {
+ return m.md
+}
+
+// GetKnownFields returns a slice of descriptors for all known fields. The
+// fields will not be in any defined order.
+func (m *Message) GetKnownFields() []*desc.FieldDescriptor {
+ if len(m.extraFields) == 0 {
+ return m.md.GetFields()
+ }
+ flds := make([]*desc.FieldDescriptor, len(m.md.GetFields()), len(m.md.GetFields())+len(m.extraFields))
+ copy(flds, m.md.GetFields())
+ for _, fld := range m.extraFields {
+ if !fld.IsExtension() {
+ flds = append(flds, fld)
+ }
+ }
+ return flds
+}
+
+// GetKnownExtensions returns a slice of descriptors for all extensions known by
+// the message's extension registry. The fields will not be in any defined order.
+func (m *Message) GetKnownExtensions() []*desc.FieldDescriptor {
+ if !m.md.IsExtendable() {
+ return nil
+ }
+ exts := m.er.AllExtensionsForType(m.md.GetFullyQualifiedName())
+ for _, fld := range m.extraFields {
+ if fld.IsExtension() {
+ exts = append(exts, fld)
+ }
+ }
+ return exts
+}
+
+// GetUnknownFields returns a slice of tag numbers for all unknown fields that
+// this message contains. The tags will not be in any defined order.
+func (m *Message) GetUnknownFields() []int32 {
+ flds := make([]int32, 0, len(m.unknownFields))
+ for tag := range m.unknownFields {
+ flds = append(flds, tag)
+ }
+ return flds
+}
+
+// Descriptor returns the serialized form of the file descriptor in which the
+// message was defined and a path to the message type therein. This mimics the
+// method of the same name on message types generated by protoc.
+func (m *Message) Descriptor() ([]byte, []int) {
+ // get encoded file descriptor
+ b, err := proto.Marshal(m.md.GetFile().AsProto())
+ if err != nil {
+ panic(fmt.Sprintf("failed to get encoded descriptor for %s: %v", m.md.GetFile().GetName(), err))
+ }
+ var zippedBytes bytes.Buffer
+ w := gzip.NewWriter(&zippedBytes)
+ if _, err := w.Write(b); err != nil {
+ panic(fmt.Sprintf("failed to get encoded descriptor for %s: %v", m.md.GetFile().GetName(), err))
+ }
+ if err := w.Close(); err != nil {
+ panic(fmt.Sprintf("failed to get an encoded descriptor for %s: %v", m.md.GetFile().GetName(), err))
+ }
+
+ // and path to message
+ path := []int{}
+ var d desc.Descriptor
+ name := m.md.GetFullyQualifiedName()
+ for d = m.md.GetParent(); d != nil; name, d = d.GetFullyQualifiedName(), d.GetParent() {
+ found := false
+ switch d := d.(type) {
+ case (*desc.FileDescriptor):
+ for i, md := range d.GetMessageTypes() {
+ if md.GetFullyQualifiedName() == name {
+ found = true
+ path = append(path, i)
+ }
+ }
+ case (*desc.MessageDescriptor):
+ for i, md := range d.GetNestedMessageTypes() {
+ if md.GetFullyQualifiedName() == name {
+ found = true
+ path = append(path, i)
+ }
+ }
+ }
+ if !found {
+ panic(fmt.Sprintf("failed to compute descriptor path for %s", m.md.GetFullyQualifiedName()))
+ }
+ }
+ // reverse the path
+ i := 0
+ j := len(path) - 1
+ for i < j {
+ path[i], path[j] = path[j], path[i]
+ i++
+ j--
+ }
+
+ return zippedBytes.Bytes(), path
+}
+
+// XXX_MessageName returns the fully qualified name of this message's type. This
+// allows dynamic messages to be used with proto.MessageName.
+func (m *Message) XXX_MessageName() string {
+ return m.md.GetFullyQualifiedName()
+}
+
+// FindFieldDescriptor returns a field descriptor for the given tag number. This
+// searches known fields in the descriptor, known fields discovered during calls
+// to GetField or SetField, and extension fields known by the message's extension
+// registry. It returns nil if the tag is unknown.
+func (m *Message) FindFieldDescriptor(tagNumber int32) *desc.FieldDescriptor {
+ fd := m.md.FindFieldByNumber(tagNumber)
+ if fd != nil {
+ return fd
+ }
+ fd = m.er.FindExtension(m.md.GetFullyQualifiedName(), tagNumber)
+ if fd != nil {
+ return fd
+ }
+ return m.extraFields[tagNumber]
+}
+
+// FindFieldDescriptorByName returns a field descriptor for the given field
+// name. This searches known fields in the descriptor, known fields discovered
+// during calls to GetField or SetField, and extension fields known by the
+// message's extension registry. It returns nil if the name is unknown. If the
+// given name refers to an extension, it should be fully qualified and may be
+// optionally enclosed in parentheses or brackets.
+func (m *Message) FindFieldDescriptorByName(name string) *desc.FieldDescriptor {
+ if name == "" {
+ return nil
+ }
+ fd := m.md.FindFieldByName(name)
+ if fd != nil {
+ return fd
+ }
+ mustBeExt := false
+ if name[0] == '(' {
+ if name[len(name)-1] != ')' {
+ // malformed name
+ return nil
+ }
+ mustBeExt = true
+ name = name[1 : len(name)-1]
+ } else if name[0] == '[' {
+ if name[len(name)-1] != ']' {
+ // malformed name
+ return nil
+ }
+ mustBeExt = true
+ name = name[1 : len(name)-1]
+ }
+ fd = m.er.FindExtensionByName(m.md.GetFullyQualifiedName(), name)
+ if fd != nil {
+ return fd
+ }
+ for _, fd := range m.extraFields {
+ if fd.IsExtension() && name == fd.GetFullyQualifiedName() {
+ return fd
+ } else if !mustBeExt && !fd.IsExtension() && name == fd.GetName() {
+ return fd
+ }
+ }
+
+ return nil
+}
+
+// FindFieldDescriptorByJSONName returns a field descriptor for the given JSON
+// name. This searches known fields in the descriptor, known fields discovered
+// during calls to GetField or SetField, and extension fields known by the
+// message's extension registry. If no field matches the given JSON name, it
+// will fall back to searching field names (e.g. FindFieldDescriptorByName). If
+// this also yields no match, nil is returned.
+func (m *Message) FindFieldDescriptorByJSONName(name string) *desc.FieldDescriptor {
+ if name == "" {
+ return nil
+ }
+ fd := m.md.FindFieldByJSONName(name)
+ if fd != nil {
+ return fd
+ }
+ mustBeExt := false
+ if name[0] == '(' {
+ if name[len(name)-1] != ')' {
+ // malformed name
+ return nil
+ }
+ mustBeExt = true
+ name = name[1 : len(name)-1]
+ } else if name[0] == '[' {
+ if name[len(name)-1] != ']' {
+ // malformed name
+ return nil
+ }
+ mustBeExt = true
+ name = name[1 : len(name)-1]
+ }
+ fd = m.er.FindExtensionByJSONName(m.md.GetFullyQualifiedName(), name)
+ if fd != nil {
+ return fd
+ }
+ for _, fd := range m.extraFields {
+ if fd.IsExtension() && name == fd.GetFullyQualifiedJSONName() {
+ return fd
+ } else if !mustBeExt && !fd.IsExtension() && name == fd.GetJSONName() {
+ return fd
+ }
+ }
+
+ // try non-JSON names
+ return m.FindFieldDescriptorByName(name)
+}
+
+func (m *Message) checkField(fd *desc.FieldDescriptor) error {
+ return checkField(fd, m.md)
+}
+
+func checkField(fd *desc.FieldDescriptor, md *desc.MessageDescriptor) error {
+ if fd.GetOwner().GetFullyQualifiedName() != md.GetFullyQualifiedName() {
+ return fmt.Errorf("given field, %s, is for wrong message type: %s; expecting %s", fd.GetName(), fd.GetOwner().GetFullyQualifiedName(), md.GetFullyQualifiedName())
+ }
+ if fd.IsExtension() && !md.IsExtension(fd.GetNumber()) {
+ return fmt.Errorf("given field, %s, is an extension but is not in message extension range: %v", fd.GetFullyQualifiedName(), md.GetExtensionRanges())
+ }
+ return nil
+}
+
+// GetField returns the value for the given field descriptor. It panics if an
+// error is encountered. See TryGetField.
+func (m *Message) GetField(fd *desc.FieldDescriptor) interface{} {
+ if v, err := m.TryGetField(fd); err != nil {
+ panic(err.Error())
+ } else {
+ return v
+ }
+}
+
+// TryGetField returns the value for the given field descriptor. An error is
+// returned if the given field descriptor does not belong to the right message
+// type.
+//
+// The Go type of the returned value, for scalar fields, is the same as protoc
+// would generate for the field (in a non-dynamic message). The table below
+// lists the scalar types and the corresponding Go types.
+// +-------------------------+-----------+
+// | Declared Type | Go Type |
+// +-------------------------+-----------+
+// | int32, sint32, sfixed32 | int32 |
+// | int64, sint64, sfixed64 | int64 |
+// | uint32, fixed32 | uint32 |
+// | uint64, fixed64 | uint64 |
+// | float | float32 |
+// | double | double32 |
+// | bool | bool |
+// | string | string |
+// | bytes | []byte |
+// +-------------------------+-----------+
+//
+// Values for enum fields will always be int32 values. You can use the enum
+// descriptor associated with the field to lookup value names with those values.
+// Values for message type fields may be an instance of the generated type *or*
+// may be another *dynamic.Message that represents the type.
+//
+// If the given field is a map field, the returned type will be
+// map[interface{}]interface{}. The actual concrete types of keys and values is
+// as described above. If the given field is a (non-map) repeated field, the
+// returned type is always []interface{}; the type of the actual elements is as
+// described above.
+//
+// If this message has no value for the given field, its default value is
+// returned. If the message is defined in a file with "proto3" syntax, the
+// default is always the zero value for the field. The default value for map and
+// repeated fields is a nil map or slice (respectively). For field's whose types
+// is a message, the default value is an empty message for "proto2" syntax or a
+// nil message for "proto3" syntax. Note that the in the latter case, a non-nil
+// interface with a nil pointer is returned, not a nil interface. Also note that
+// whether the returned value is an empty message or nil depends on if *this*
+// message was defined as "proto3" syntax, not the message type referred to by
+// the field's type.
+//
+// If the given field descriptor is not known (e.g. not present in the message
+// descriptor) but corresponds to an unknown field, the unknown value will be
+// parsed and become known. The parsed value will be returned, or an error will
+// be returned if the unknown value cannot be parsed according to the field
+// descriptor's type information.
+func (m *Message) TryGetField(fd *desc.FieldDescriptor) (interface{}, error) {
+ if err := m.checkField(fd); err != nil {
+ return nil, err
+ }
+ return m.getField(fd)
+}
+
+// GetFieldByName returns the value for the field with the given name. It panics
+// if an error is encountered. See TryGetFieldByName.
+func (m *Message) GetFieldByName(name string) interface{} {
+ if v, err := m.TryGetFieldByName(name); err != nil {
+ panic(err.Error())
+ } else {
+ return v
+ }
+}
+
+// TryGetFieldByName returns the value for the field with the given name. An
+// error is returned if the given name is unknown. If the given name refers to
+// an extension field, it should be fully qualified and optionally enclosed in
+// parenthesis or brackets.
+//
+// If this message has no value for the given field, its default value is
+// returned. (See TryGetField for more info on types and default field values.)
+func (m *Message) TryGetFieldByName(name string) (interface{}, error) {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return nil, UnknownFieldNameError
+ }
+ return m.getField(fd)
+}
+
+// GetFieldByNumber returns the value for the field with the given tag number.
+// It panics if an error is encountered. See TryGetFieldByNumber.
+func (m *Message) GetFieldByNumber(tagNumber int) interface{} {
+ if v, err := m.TryGetFieldByNumber(tagNumber); err != nil {
+ panic(err.Error())
+ } else {
+ return v
+ }
+}
+
+// TryGetFieldByNumber returns the value for the field with the given tag
+// number. An error is returned if the given tag is unknown.
+//
+// If this message has no value for the given field, its default value is
+// returned. (See TryGetField for more info on types and default field values.)
+func (m *Message) TryGetFieldByNumber(tagNumber int) (interface{}, error) {
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return nil, UnknownTagNumberError
+ }
+ return m.getField(fd)
+}
+
+func (m *Message) getField(fd *desc.FieldDescriptor) (interface{}, error) {
+ return m.doGetField(fd, false)
+}
+
+func (m *Message) doGetField(fd *desc.FieldDescriptor, nilIfAbsent bool) (interface{}, error) {
+ res := m.values[fd.GetNumber()]
+ if res == nil {
+ var err error
+ if res, err = m.parseUnknownField(fd); err != nil {
+ return nil, err
+ }
+ if res == nil {
+ if nilIfAbsent {
+ return nil, nil
+ } else {
+ def := fd.GetDefaultValue()
+ if def != nil {
+ return def, nil
+ }
+ // GetDefaultValue only returns nil for message types
+ md := fd.GetMessageType()
+ if md.IsProto3() {
+ // try to return a proper nil pointer
+ msgType := proto.MessageType(md.GetFullyQualifiedName())
+ if msgType != nil && msgType.Implements(typeOfProtoMessage) {
+ return reflect.Zero(msgType).Interface().(proto.Message), nil
+ }
+ // fallback to nil dynamic message pointer
+ return (*Message)(nil), nil
+ } else {
+ // for proto2, return default instance of message
+ return m.mf.NewMessage(md), nil
+ }
+ }
+ }
+ }
+ rt := reflect.TypeOf(res)
+ if rt.Kind() == reflect.Map {
+ // make defensive copies to prevent caller from storing illegal keys and values
+ m := res.(map[interface{}]interface{})
+ res := map[interface{}]interface{}{}
+ for k, v := range m {
+ res[k] = v
+ }
+ return res, nil
+ } else if rt.Kind() == reflect.Slice && rt != typeOfBytes {
+ // make defensive copies to prevent caller from storing illegal elements
+ sl := res.([]interface{})
+ res := make([]interface{}, len(sl))
+ copy(res, sl)
+ return res, nil
+ }
+ return res, nil
+}
+
+// HasField returns true if this message has a value for the given field. If the
+// given field is not valid (e.g. belongs to a different message type), false is
+// returned. If this message is defined in a file with "proto3" syntax, this
+// will return false even if a field was explicitly assigned its zero value (the
+// zero values for a field are intentionally indistinguishable from absent).
+func (m *Message) HasField(fd *desc.FieldDescriptor) bool {
+ if err := m.checkField(fd); err != nil {
+ return false
+ }
+ return m.HasFieldNumber(int(fd.GetNumber()))
+}
+
+// HasFieldName returns true if this message has a value for a field with the
+// given name. If the given name is unknown, this returns false.
+func (m *Message) HasFieldName(name string) bool {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return false
+ }
+ return m.HasFieldNumber(int(fd.GetNumber()))
+}
+
+// HasFieldNumber returns true if this message has a value for a field with the
+// given tag number. If the given tag is unknown, this returns false.
+func (m *Message) HasFieldNumber(tagNumber int) bool {
+ if _, ok := m.values[int32(tagNumber)]; ok {
+ return true
+ }
+ _, ok := m.unknownFields[int32(tagNumber)]
+ return ok
+}
+
+// SetField sets the value for the given field descriptor to the given value. It
+// panics if an error is encountered. See TrySetField.
+func (m *Message) SetField(fd *desc.FieldDescriptor, val interface{}) {
+ if err := m.TrySetField(fd, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TrySetField sets the value for the given field descriptor to the given value.
+// An error is returned if the given field descriptor does not belong to the
+// right message type or if the given value is not a correct/compatible type for
+// the given field.
+//
+// The Go type expected for a field is the same as TryGetField would return for
+// the field. So message values can be supplied as either the correct generated
+// message type or as a *dynamic.Message.
+//
+// Since it is cumbersome to work with dynamic messages, some concessions are
+// made to simplify usage regarding types:
+//
+// 1. If a numeric type is provided that can be converted *without loss or
+// overflow*, it is accepted. This allows for setting int64 fields using int
+// or int32 values. Similarly for uint64 with uint and uint32 values and for
+// float64 fields with float32 values.
+// 2. The value can be a named type, as long as its underlying type is correct.
+// 3. Map and repeated fields can be set using any kind of concrete map or
+// slice type, as long as the values within are all of the correct type. So
+// a field defined as a 'map<string, int32>` can be set using a
+// map[string]int32, a map[string]interface{}, or even a
+// map[interface{}]interface{}.
+// 4. Finally, dynamic code that chooses to not treat maps as a special-case
+// find that they can set map fields using a slice where each element is a
+// message that matches the implicit map-entry field message type.
+//
+// If the given field descriptor is not known (e.g. not present in the message
+// descriptor) it will become known. Subsequent operations using tag numbers or
+// names will be able to resolve the newly-known type. If the message has a
+// value for the unknown value, it is cleared, replaced by the given known
+// value.
+func (m *Message) TrySetField(fd *desc.FieldDescriptor, val interface{}) error {
+ if err := m.checkField(fd); err != nil {
+ return err
+ }
+ return m.setField(fd, val)
+}
+
+// SetFieldByName sets the value for the field with the given name to the given
+// value. It panics if an error is encountered. See TrySetFieldByName.
+func (m *Message) SetFieldByName(name string, val interface{}) {
+ if err := m.TrySetFieldByName(name, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TrySetFieldByName sets the value for the field with the given name to the
+// given value. An error is returned if the given name is unknown or if the
+// given value has an incorrect type. If the given name refers to an extension
+// field, it should be fully qualified and optionally enclosed in parenthesis or
+// brackets.
+//
+// (See TrySetField for more info on types.)
+func (m *Message) TrySetFieldByName(name string, val interface{}) error {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return UnknownFieldNameError
+ }
+ return m.setField(fd, val)
+}
+
+// SetFieldByNumber sets the value for the field with the given tag number to
+// the given value. It panics if an error is encountered. See
+// TrySetFieldByNumber.
+func (m *Message) SetFieldByNumber(tagNumber int, val interface{}) {
+ if err := m.TrySetFieldByNumber(tagNumber, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TrySetFieldByNumber sets the value for the field with the given tag number to
+// the given value. An error is returned if the given tag is unknown or if the
+// given value has an incorrect type.
+//
+// (See TrySetField for more info on types.)
+func (m *Message) TrySetFieldByNumber(tagNumber int, val interface{}) error {
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return UnknownTagNumberError
+ }
+ return m.setField(fd, val)
+}
+
+func (m *Message) setField(fd *desc.FieldDescriptor, val interface{}) error {
+ var err error
+ if val, err = validFieldValue(fd, val); err != nil {
+ return err
+ }
+ m.internalSetField(fd, val)
+ return nil
+}
+
+func (m *Message) internalSetField(fd *desc.FieldDescriptor, val interface{}) {
+ if fd.IsRepeated() {
+ // Unset fields and zero-length fields are indistinguishable, in both
+ // proto2 and proto3 syntax
+ if reflect.ValueOf(val).Len() == 0 {
+ if m.values != nil {
+ delete(m.values, fd.GetNumber())
+ }
+ return
+ }
+ } else if m.md.IsProto3() && fd.GetOneOf() == nil {
+ // proto3 considers fields that are set to their zero value as unset
+ // (we already handled repeated fields above)
+ var equal bool
+ if b, ok := val.([]byte); ok {
+ // can't compare slices, so we have to special-case []byte values
+ equal = ok && bytes.Equal(b, fd.GetDefaultValue().([]byte))
+ } else {
+ defVal := fd.GetDefaultValue()
+ equal = defVal == val
+ if !equal && defVal == nil {
+ // above just checks if value is the nil interface,
+ // but we should also test if the given value is a
+ // nil pointer
+ rv := reflect.ValueOf(val)
+ if rv.Kind() == reflect.Ptr && rv.IsNil() {
+ equal = true
+ }
+ }
+ }
+ if equal {
+ if m.values != nil {
+ delete(m.values, fd.GetNumber())
+ }
+ return
+ }
+ }
+ if m.values == nil {
+ m.values = map[int32]interface{}{}
+ }
+ m.values[fd.GetNumber()] = val
+ // if this field is part of a one-of, make sure all other one-of choices are cleared
+ od := fd.GetOneOf()
+ if od != nil {
+ for _, other := range od.GetChoices() {
+ if other.GetNumber() != fd.GetNumber() {
+ delete(m.values, other.GetNumber())
+ }
+ }
+ }
+ // also clear any unknown fields
+ if m.unknownFields != nil {
+ delete(m.unknownFields, fd.GetNumber())
+ }
+ // and add this field if it was previously unknown
+ if existing := m.FindFieldDescriptor(fd.GetNumber()); existing == nil {
+ m.addField(fd)
+ }
+}
+
+func (m *Message) addField(fd *desc.FieldDescriptor) {
+ if m.extraFields == nil {
+ m.extraFields = map[int32]*desc.FieldDescriptor{}
+ }
+ m.extraFields[fd.GetNumber()] = fd
+}
+
+// ClearField removes any value for the given field. It panics if an error is
+// encountered. See TryClearField.
+func (m *Message) ClearField(fd *desc.FieldDescriptor) {
+ if err := m.TryClearField(fd); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryClearField removes any value for the given field. An error is returned if
+// the given field descriptor does not belong to the right message type.
+func (m *Message) TryClearField(fd *desc.FieldDescriptor) error {
+ if err := m.checkField(fd); err != nil {
+ return err
+ }
+ m.clearField(fd)
+ return nil
+}
+
+// ClearFieldByName removes any value for the field with the given name. It
+// panics if an error is encountered. See TryClearFieldByName.
+func (m *Message) ClearFieldByName(name string) {
+ if err := m.TryClearFieldByName(name); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryClearFieldByName removes any value for the field with the given name. An
+// error is returned if the given name is unknown. If the given name refers to
+// an extension field, it should be fully qualified and optionally enclosed in
+// parenthesis or brackets.
+func (m *Message) TryClearFieldByName(name string) error {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return UnknownFieldNameError
+ }
+ m.clearField(fd)
+ return nil
+}
+
+// ClearFieldByNumber removes any value for the field with the given tag number.
+// It panics if an error is encountered. See TryClearFieldByNumber.
+func (m *Message) ClearFieldByNumber(tagNumber int) {
+ if err := m.TryClearFieldByNumber(tagNumber); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryClearFieldByNumber removes any value for the field with the given tag
+// number. An error is returned if the given tag is unknown.
+func (m *Message) TryClearFieldByNumber(tagNumber int) error {
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return UnknownTagNumberError
+ }
+ m.clearField(fd)
+ return nil
+}
+
+func (m *Message) clearField(fd *desc.FieldDescriptor) {
+ // clear value
+ if m.values != nil {
+ delete(m.values, fd.GetNumber())
+ }
+ // also clear any unknown fields
+ if m.unknownFields != nil {
+ delete(m.unknownFields, fd.GetNumber())
+ }
+ // and add this field if it was previously unknown
+ if existing := m.FindFieldDescriptor(fd.GetNumber()); existing == nil {
+ m.addField(fd)
+ }
+}
+
+// GetOneOfField returns which of the given one-of's fields is set and the
+// corresponding value. It panics if an error is encountered. See
+// TryGetOneOfField.
+func (m *Message) GetOneOfField(od *desc.OneOfDescriptor) (*desc.FieldDescriptor, interface{}) {
+ if fd, val, err := m.TryGetOneOfField(od); err != nil {
+ panic(err.Error())
+ } else {
+ return fd, val
+ }
+}
+
+// TryGetOneOfField returns which of the given one-of's fields is set and the
+// corresponding value. An error is returned if the given one-of belongs to the
+// wrong message type. If the given one-of has no field set, this method will
+// return nil, nil.
+//
+// The type of the value, if one is set, is the same as would be returned by
+// TryGetField using the returned field descriptor.
+//
+// Like with TryGetField, if the given one-of contains any fields that are not
+// known (e.g. not present in this message's descriptor), they will become known
+// and any unknown value will be parsed (and become a known value on success).
+func (m *Message) TryGetOneOfField(od *desc.OneOfDescriptor) (*desc.FieldDescriptor, interface{}, error) {
+ if od.GetOwner().GetFullyQualifiedName() != m.md.GetFullyQualifiedName() {
+ return nil, nil, fmt.Errorf("given one-of, %s, is for wrong message type: %s; expecting %s", od.GetName(), od.GetOwner().GetFullyQualifiedName(), m.md.GetFullyQualifiedName())
+ }
+ for _, fd := range od.GetChoices() {
+ val, err := m.doGetField(fd, true)
+ if err != nil {
+ return nil, nil, err
+ }
+ if val != nil {
+ return fd, val, nil
+ }
+ }
+ return nil, nil, nil
+}
+
+// ClearOneOfField removes any value for any of the given one-of's fields. It
+// panics if an error is encountered. See TryClearOneOfField.
+func (m *Message) ClearOneOfField(od *desc.OneOfDescriptor) {
+ if err := m.TryClearOneOfField(od); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryClearOneOfField removes any value for any of the given one-of's fields. An
+// error is returned if the given one-of descriptor does not belong to the right
+// message type.
+func (m *Message) TryClearOneOfField(od *desc.OneOfDescriptor) error {
+ if od.GetOwner().GetFullyQualifiedName() != m.md.GetFullyQualifiedName() {
+ return fmt.Errorf("given one-of, %s, is for wrong message type: %s; expecting %s", od.GetName(), od.GetOwner().GetFullyQualifiedName(), m.md.GetFullyQualifiedName())
+ }
+ for _, fd := range od.GetChoices() {
+ m.clearField(fd)
+ }
+ return nil
+}
+
+// GetMapField returns the value for the given map field descriptor and given
+// key. It panics if an error is encountered. See TryGetMapField.
+func (m *Message) GetMapField(fd *desc.FieldDescriptor, key interface{}) interface{} {
+ if v, err := m.TryGetMapField(fd, key); err != nil {
+ panic(err.Error())
+ } else {
+ return v
+ }
+}
+
+// TryGetMapField returns the value for the given map field descriptor and given
+// key. An error is returned if the given field descriptor does not belong to
+// the right message type or if it is not a map field.
+//
+// If the map field does not contain the requested key, this method returns
+// nil, nil. The Go type of the value returned mirrors the type that protoc
+// would generate for the field. (See TryGetField for more details on types).
+//
+// If the given field descriptor is not known (e.g. not present in the message
+// descriptor) but corresponds to an unknown field, the unknown value will be
+// parsed and become known. The parsed value will be searched for the requested
+// key and any value returned. An error will be returned if the unknown value
+// cannot be parsed according to the field descriptor's type information.
+func (m *Message) TryGetMapField(fd *desc.FieldDescriptor, key interface{}) (interface{}, error) {
+ if err := m.checkField(fd); err != nil {
+ return nil, err
+ }
+ return m.getMapField(fd, key)
+}
+
+// GetMapFieldByName returns the value for the map field with the given name and
+// given key. It panics if an error is encountered. See TryGetMapFieldByName.
+func (m *Message) GetMapFieldByName(name string, key interface{}) interface{} {
+ if v, err := m.TryGetMapFieldByName(name, key); err != nil {
+ panic(err.Error())
+ } else {
+ return v
+ }
+}
+
+// TryGetMapFieldByName returns the value for the map field with the given name
+// and given key. An error is returned if the given name is unknown or if it
+// names a field that is not a map field.
+//
+// If this message has no value for the given field or the value has no value
+// for the requested key, then this method returns nil, nil.
+//
+// (See TryGetField for more info on types.)
+func (m *Message) TryGetMapFieldByName(name string, key interface{}) (interface{}, error) {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return nil, UnknownFieldNameError
+ }
+ return m.getMapField(fd, key)
+}
+
+// GetMapFieldByNumber returns the value for the map field with the given tag
+// number and given key. It panics if an error is encountered. See
+// TryGetMapFieldByNumber.
+func (m *Message) GetMapFieldByNumber(tagNumber int, key interface{}) interface{} {
+ if v, err := m.TryGetMapFieldByNumber(tagNumber, key); err != nil {
+ panic(err.Error())
+ } else {
+ return v
+ }
+}
+
+// TryGetMapFieldByNumber returns the value for the map field with the given tag
+// number and given key. An error is returned if the given tag is unknown or if
+// it indicates a field that is not a map field.
+//
+// If this message has no value for the given field or the value has no value
+// for the requested key, then this method returns nil, nil.
+//
+// (See TryGetField for more info on types.)
+func (m *Message) TryGetMapFieldByNumber(tagNumber int, key interface{}) (interface{}, error) {
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return nil, UnknownTagNumberError
+ }
+ return m.getMapField(fd, key)
+}
+
+func (m *Message) getMapField(fd *desc.FieldDescriptor, key interface{}) (interface{}, error) {
+ if !fd.IsMap() {
+ return nil, FieldIsNotMapError
+ }
+ kfd := fd.GetMessageType().GetFields()[0]
+ ki, err := validElementFieldValue(kfd, key)
+ if err != nil {
+ return nil, err
+ }
+ mp := m.values[fd.GetNumber()]
+ if mp == nil {
+ if mp, err = m.parseUnknownField(fd); err != nil {
+ return nil, err
+ } else if mp == nil {
+ return nil, nil
+ }
+ }
+ return mp.(map[interface{}]interface{})[ki], nil
+}
+
+// ForEachMapFieldEntry executes the given function for each entry in the map
+// value for the given field descriptor. It stops iteration if the function
+// returns false. It panics if an error is encountered. See
+// TryForEachMapFieldEntry.
+func (m *Message) ForEachMapFieldEntry(fd *desc.FieldDescriptor, fn func(key, val interface{}) bool) {
+ if err := m.TryForEachMapFieldEntry(fd, fn); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryForEachMapFieldEntry executes the given function for each entry in the map
+// value for the given field descriptor. An error is returned if the given field
+// descriptor does not belong to the right message type or if it is not a map
+// field.
+//
+// Iteration ends either when all entries have been examined or when the given
+// function returns false. So the function is expected to return true for normal
+// iteration and false to break out. If this message has no value for the given
+// field, it returns without invoking the given function.
+//
+// The Go type of the key and value supplied to the function mirrors the type
+// that protoc would generate for the field. (See TryGetField for more details
+// on types).
+//
+// If the given field descriptor is not known (e.g. not present in the message
+// descriptor) but corresponds to an unknown field, the unknown value will be
+// parsed and become known. The parsed value will be searched for the requested
+// key and any value returned. An error will be returned if the unknown value
+// cannot be parsed according to the field descriptor's type information.
+func (m *Message) TryForEachMapFieldEntry(fd *desc.FieldDescriptor, fn func(key, val interface{}) bool) error {
+ if err := m.checkField(fd); err != nil {
+ return err
+ }
+ return m.forEachMapFieldEntry(fd, fn)
+}
+
+// ForEachMapFieldEntryByName executes the given function for each entry in the
+// map value for the field with the given name. It stops iteration if the
+// function returns false. It panics if an error is encountered. See
+// TryForEachMapFieldEntryByName.
+func (m *Message) ForEachMapFieldEntryByName(name string, fn func(key, val interface{}) bool) {
+ if err := m.TryForEachMapFieldEntryByName(name, fn); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryForEachMapFieldEntryByName executes the given function for each entry in
+// the map value for the field with the given name. It stops iteration if the
+// function returns false. An error is returned if the given name is unknown or
+// if it names a field that is not a map field.
+//
+// If this message has no value for the given field, it returns without ever
+// invoking the given function.
+//
+// (See TryGetField for more info on types supplied to the function.)
+func (m *Message) TryForEachMapFieldEntryByName(name string, fn func(key, val interface{}) bool) error {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return UnknownFieldNameError
+ }
+ return m.forEachMapFieldEntry(fd, fn)
+}
+
+// ForEachMapFieldEntryByNumber executes the given function for each entry in
+// the map value for the field with the given tag number. It stops iteration if
+// the function returns false. It panics if an error is encountered. See
+// TryForEachMapFieldEntryByNumber.
+func (m *Message) ForEachMapFieldEntryByNumber(tagNumber int, fn func(key, val interface{}) bool) {
+ if err := m.TryForEachMapFieldEntryByNumber(tagNumber, fn); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryForEachMapFieldEntryByNumber executes the given function for each entry in
+// the map value for the field with the given tag number. It stops iteration if
+// the function returns false. An error is returned if the given tag is unknown
+// or if it indicates a field that is not a map field.
+//
+// If this message has no value for the given field, it returns without ever
+// invoking the given function.
+//
+// (See TryGetField for more info on types supplied to the function.)
+func (m *Message) TryForEachMapFieldEntryByNumber(tagNumber int, fn func(key, val interface{}) bool) error {
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return UnknownTagNumberError
+ }
+ return m.forEachMapFieldEntry(fd, fn)
+}
+
+func (m *Message) forEachMapFieldEntry(fd *desc.FieldDescriptor, fn func(key, val interface{}) bool) error {
+ if !fd.IsMap() {
+ return FieldIsNotMapError
+ }
+ mp := m.values[fd.GetNumber()]
+ if mp == nil {
+ if mp, err := m.parseUnknownField(fd); err != nil {
+ return err
+ } else if mp == nil {
+ return nil
+ }
+ }
+ for k, v := range mp.(map[interface{}]interface{}) {
+ if !fn(k, v) {
+ break
+ }
+ }
+ return nil
+}
+
+// PutMapField sets the value for the given map field descriptor and given key
+// to the given value. It panics if an error is encountered. See TryPutMapField.
+func (m *Message) PutMapField(fd *desc.FieldDescriptor, key interface{}, val interface{}) {
+ if err := m.TryPutMapField(fd, key, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryPutMapField sets the value for the given map field descriptor and given
+// key to the given value. An error is returned if the given field descriptor
+// does not belong to the right message type, if the given field is not a map
+// field, or if the given value is not a correct/compatible type for the given
+// field.
+//
+// The Go type expected for a field is the same as required by TrySetField for
+// a field with the same type as the map's value type.
+//
+// If the given field descriptor is not known (e.g. not present in the message
+// descriptor) it will become known. Subsequent operations using tag numbers or
+// names will be able to resolve the newly-known type. If the message has a
+// value for the unknown value, it is cleared, replaced by the given known
+// value.
+func (m *Message) TryPutMapField(fd *desc.FieldDescriptor, key interface{}, val interface{}) error {
+ if err := m.checkField(fd); err != nil {
+ return err
+ }
+ return m.putMapField(fd, key, val)
+}
+
+// PutMapFieldByName sets the value for the map field with the given name and
+// given key to the given value. It panics if an error is encountered. See
+// TryPutMapFieldByName.
+func (m *Message) PutMapFieldByName(name string, key interface{}, val interface{}) {
+ if err := m.TryPutMapFieldByName(name, key, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryPutMapFieldByName sets the value for the map field with the given name and
+// the given key to the given value. An error is returned if the given name is
+// unknown, if it names a field that is not a map, or if the given value has an
+// incorrect type.
+//
+// (See TrySetField for more info on types.)
+func (m *Message) TryPutMapFieldByName(name string, key interface{}, val interface{}) error {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return UnknownFieldNameError
+ }
+ return m.putMapField(fd, key, val)
+}
+
+// PutMapFieldByNumber sets the value for the map field with the given tag
+// number and given key to the given value. It panics if an error is
+// encountered. See TryPutMapFieldByNumber.
+func (m *Message) PutMapFieldByNumber(tagNumber int, key interface{}, val interface{}) {
+ if err := m.TryPutMapFieldByNumber(tagNumber, key, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryPutMapFieldByNumber sets the value for the map field with the given tag
+// number and the given key to the given value. An error is returned if the
+// given tag is unknown, if it indicates a field that is not a map, or if the
+// given value has an incorrect type.
+//
+// (See TrySetField for more info on types.)
+func (m *Message) TryPutMapFieldByNumber(tagNumber int, key interface{}, val interface{}) error {
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return UnknownTagNumberError
+ }
+ return m.putMapField(fd, key, val)
+}
+
+func (m *Message) putMapField(fd *desc.FieldDescriptor, key interface{}, val interface{}) error {
+ if !fd.IsMap() {
+ return FieldIsNotMapError
+ }
+ kfd := fd.GetMessageType().GetFields()[0]
+ ki, err := validElementFieldValue(kfd, key)
+ if err != nil {
+ return err
+ }
+ vfd := fd.GetMessageType().GetFields()[1]
+ vi, err := validElementFieldValue(vfd, val)
+ if err != nil {
+ return err
+ }
+ mp := m.values[fd.GetNumber()]
+ if mp == nil {
+ if mp, err = m.parseUnknownField(fd); err != nil {
+ return err
+ } else if mp == nil {
+ m.internalSetField(fd, map[interface{}]interface{}{ki: vi})
+ return nil
+ }
+ }
+ mp.(map[interface{}]interface{})[ki] = vi
+ return nil
+}
+
+// RemoveMapField changes the value for the given field descriptor by removing
+// any value associated with the given key. It panics if an error is
+// encountered. See TryRemoveMapField.
+func (m *Message) RemoveMapField(fd *desc.FieldDescriptor, key interface{}) {
+ if err := m.TryRemoveMapField(fd, key); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryRemoveMapField changes the value for the given field descriptor by
+// removing any value associated with the given key. An error is returned if the
+// given field descriptor does not belong to the right message type or if the
+// given field is not a map field.
+//
+// If the given field descriptor is not known (e.g. not present in the message
+// descriptor) it will become known. Subsequent operations using tag numbers or
+// names will be able to resolve the newly-known type. If the message has a
+// value for the unknown value, it is parsed and any value for the given key
+// removed.
+func (m *Message) TryRemoveMapField(fd *desc.FieldDescriptor, key interface{}) error {
+ if err := m.checkField(fd); err != nil {
+ return err
+ }
+ return m.removeMapField(fd, key)
+}
+
+// RemoveMapFieldByName changes the value for the field with the given name by
+// removing any value associated with the given key. It panics if an error is
+// encountered. See TryRemoveMapFieldByName.
+func (m *Message) RemoveMapFieldByName(name string, key interface{}) {
+ if err := m.TryRemoveMapFieldByName(name, key); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryRemoveMapFieldByName changes the value for the field with the given name
+// by removing any value associated with the given key. An error is returned if
+// the given name is unknown or if it names a field that is not a map.
+func (m *Message) TryRemoveMapFieldByName(name string, key interface{}) error {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return UnknownFieldNameError
+ }
+ return m.removeMapField(fd, key)
+}
+
+// RemoveMapFieldByNumber changes the value for the field with the given tag
+// number by removing any value associated with the given key. It panics if an
+// error is encountered. See TryRemoveMapFieldByNumber.
+func (m *Message) RemoveMapFieldByNumber(tagNumber int, key interface{}) {
+ if err := m.TryRemoveMapFieldByNumber(tagNumber, key); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryRemoveMapFieldByNumber changes the value for the field with the given tag
+// number by removing any value associated with the given key. An error is
+// returned if the given tag is unknown or if it indicates a field that is not
+// a map.
+func (m *Message) TryRemoveMapFieldByNumber(tagNumber int, key interface{}) error {
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return UnknownTagNumberError
+ }
+ return m.removeMapField(fd, key)
+}
+
+func (m *Message) removeMapField(fd *desc.FieldDescriptor, key interface{}) error {
+ if !fd.IsMap() {
+ return FieldIsNotMapError
+ }
+ kfd := fd.GetMessageType().GetFields()[0]
+ ki, err := validElementFieldValue(kfd, key)
+ if err != nil {
+ return err
+ }
+ mp := m.values[fd.GetNumber()]
+ if mp == nil {
+ if mp, err = m.parseUnknownField(fd); err != nil {
+ return err
+ } else if mp == nil {
+ return nil
+ }
+ }
+ res := mp.(map[interface{}]interface{})
+ delete(res, ki)
+ if len(res) == 0 {
+ delete(m.values, fd.GetNumber())
+ }
+ return nil
+}
+
+// FieldLength returns the number of elements in this message for the given
+// field descriptor. It panics if an error is encountered. See TryFieldLength.
+func (m *Message) FieldLength(fd *desc.FieldDescriptor) int {
+ l, err := m.TryFieldLength(fd)
+ if err != nil {
+ panic(err.Error())
+ }
+ return l
+}
+
+// TryFieldLength returns the number of elements in this message for the given
+// field descriptor. An error is returned if the given field descriptor does not
+// belong to the right message type or if it is neither a map field nor a
+// repeated field.
+func (m *Message) TryFieldLength(fd *desc.FieldDescriptor) (int, error) {
+ if err := m.checkField(fd); err != nil {
+ return 0, err
+ }
+ return m.fieldLength(fd)
+}
+
+// FieldLengthByName returns the number of elements in this message for the
+// field with the given name. It panics if an error is encountered. See
+// TryFieldLengthByName.
+func (m *Message) FieldLengthByName(name string) int {
+ l, err := m.TryFieldLengthByName(name)
+ if err != nil {
+ panic(err.Error())
+ }
+ return l
+}
+
+// TryFieldLengthByName returns the number of elements in this message for the
+// field with the given name. An error is returned if the given name is unknown
+// or if the named field is neither a map field nor a repeated field.
+func (m *Message) TryFieldLengthByName(name string) (int, error) {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return 0, UnknownFieldNameError
+ }
+ return m.fieldLength(fd)
+}
+
+// FieldLengthByNumber returns the number of elements in this message for the
+// field with the given tag number. It panics if an error is encountered. See
+// TryFieldLengthByNumber.
+func (m *Message) FieldLengthByNumber(tagNumber int32) int {
+ l, err := m.TryFieldLengthByNumber(tagNumber)
+ if err != nil {
+ panic(err.Error())
+ }
+ return l
+}
+
+// TryFieldLengthByNumber returns the number of elements in this message for the
+// field with the given tag number. An error is returned if the given tag is
+// unknown or if the named field is neither a map field nor a repeated field.
+func (m *Message) TryFieldLengthByNumber(tagNumber int32) (int, error) {
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return 0, UnknownTagNumberError
+ }
+ return m.fieldLength(fd)
+}
+
+func (m *Message) fieldLength(fd *desc.FieldDescriptor) (int, error) {
+ if !fd.IsRepeated() {
+ return 0, FieldIsNotRepeatedError
+ }
+ val := m.values[fd.GetNumber()]
+ if val == nil {
+ var err error
+ if val, err = m.parseUnknownField(fd); err != nil {
+ return 0, err
+ } else if val == nil {
+ return 0, nil
+ }
+ }
+ if sl, ok := val.([]interface{}); ok {
+ return len(sl), nil
+ } else if mp, ok := val.(map[interface{}]interface{}); ok {
+ return len(mp), nil
+ }
+ return 0, nil
+}
+
+// GetRepeatedField returns the value for the given repeated field descriptor at
+// the given index. It panics if an error is encountered. See
+// TryGetRepeatedField.
+func (m *Message) GetRepeatedField(fd *desc.FieldDescriptor, index int) interface{} {
+ if v, err := m.TryGetRepeatedField(fd, index); err != nil {
+ panic(err.Error())
+ } else {
+ return v
+ }
+}
+
+// TryGetRepeatedField returns the value for the given repeated field descriptor
+// at the given index. An error is returned if the given field descriptor does
+// not belong to the right message type, if it is not a repeated field, or if
+// the given index is out of range (less than zero or greater than or equal to
+// the length of the repeated field). Also, even though map fields technically
+// are repeated fields, if the given field is a map field an error will result:
+// map representation does not lend itself to random access by index.
+//
+// The Go type of the value returned mirrors the type that protoc would generate
+// for the field's element type. (See TryGetField for more details on types).
+//
+// If the given field descriptor is not known (e.g. not present in the message
+// descriptor) but corresponds to an unknown field, the unknown value will be
+// parsed and become known. The value at the given index in the parsed value
+// will be returned. An error will be returned if the unknown value cannot be
+// parsed according to the field descriptor's type information.
+func (m *Message) TryGetRepeatedField(fd *desc.FieldDescriptor, index int) (interface{}, error) {
+ if index < 0 {
+ return nil, IndexOutOfRangeError
+ }
+ if err := m.checkField(fd); err != nil {
+ return nil, err
+ }
+ return m.getRepeatedField(fd, index)
+}
+
+// GetRepeatedFieldByName returns the value for the repeated field with the
+// given name at the given index. It panics if an error is encountered. See
+// TryGetRepeatedFieldByName.
+func (m *Message) GetRepeatedFieldByName(name string, index int) interface{} {
+ if v, err := m.TryGetRepeatedFieldByName(name, index); err != nil {
+ panic(err.Error())
+ } else {
+ return v
+ }
+}
+
+// TryGetRepeatedFieldByName returns the value for the repeated field with the
+// given name at the given index. An error is returned if the given name is
+// unknown, if it names a field that is not a repeated field (or is a map
+// field), or if the given index is out of range (less than zero or greater
+// than or equal to the length of the repeated field).
+//
+// (See TryGetField for more info on types.)
+func (m *Message) TryGetRepeatedFieldByName(name string, index int) (interface{}, error) {
+ if index < 0 {
+ return nil, IndexOutOfRangeError
+ }
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return nil, UnknownFieldNameError
+ }
+ return m.getRepeatedField(fd, index)
+}
+
+// GetRepeatedFieldByNumber returns the value for the repeated field with the
+// given tag number at the given index. It panics if an error is encountered.
+// See TryGetRepeatedFieldByNumber.
+func (m *Message) GetRepeatedFieldByNumber(tagNumber int, index int) interface{} {
+ if v, err := m.TryGetRepeatedFieldByNumber(tagNumber, index); err != nil {
+ panic(err.Error())
+ } else {
+ return v
+ }
+}
+
+// TryGetRepeatedFieldByNumber returns the value for the repeated field with the
+// given tag number at the given index. An error is returned if the given tag is
+// unknown, if it indicates a field that is not a repeated field (or is a map
+// field), or if the given index is out of range (less than zero or greater than
+// or equal to the length of the repeated field).
+//
+// (See TryGetField for more info on types.)
+func (m *Message) TryGetRepeatedFieldByNumber(tagNumber int, index int) (interface{}, error) {
+ if index < 0 {
+ return nil, IndexOutOfRangeError
+ }
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return nil, UnknownTagNumberError
+ }
+ return m.getRepeatedField(fd, index)
+}
+
+func (m *Message) getRepeatedField(fd *desc.FieldDescriptor, index int) (interface{}, error) {
+ if fd.IsMap() || !fd.IsRepeated() {
+ return nil, FieldIsNotRepeatedError
+ }
+ sl := m.values[fd.GetNumber()]
+ if sl == nil {
+ var err error
+ if sl, err = m.parseUnknownField(fd); err != nil {
+ return nil, err
+ } else if sl == nil {
+ return nil, IndexOutOfRangeError
+ }
+ }
+ res := sl.([]interface{})
+ if index >= len(res) {
+ return nil, IndexOutOfRangeError
+ }
+ return res[index], nil
+}
+
+// AddRepeatedField appends the given value to the given repeated field. It
+// panics if an error is encountered. See TryAddRepeatedField.
+func (m *Message) AddRepeatedField(fd *desc.FieldDescriptor, val interface{}) {
+ if err := m.TryAddRepeatedField(fd, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryAddRepeatedField appends the given value to the given repeated field. An
+// error is returned if the given field descriptor does not belong to the right
+// message type, if the given field is not repeated, or if the given value is
+// not a correct/compatible type for the given field. If the given field is a
+// map field, the call will succeed if the given value is an instance of the
+// map's entry message type.
+//
+// The Go type expected for a field is the same as required by TrySetField for
+// a non-repeated field of the same type.
+//
+// If the given field descriptor is not known (e.g. not present in the message
+// descriptor) it will become known. Subsequent operations using tag numbers or
+// names will be able to resolve the newly-known type. If the message has a
+// value for the unknown value, it is parsed and the given value is appended to
+// it.
+func (m *Message) TryAddRepeatedField(fd *desc.FieldDescriptor, val interface{}) error {
+ if err := m.checkField(fd); err != nil {
+ return err
+ }
+ return m.addRepeatedField(fd, val)
+}
+
+// AddRepeatedFieldByName appends the given value to the repeated field with the
+// given name. It panics if an error is encountered. See
+// TryAddRepeatedFieldByName.
+func (m *Message) AddRepeatedFieldByName(name string, val interface{}) {
+ if err := m.TryAddRepeatedFieldByName(name, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryAddRepeatedFieldByName appends the given value to the repeated field with
+// the given name. An error is returned if the given name is unknown, if it
+// names a field that is not repeated, or if the given value has an incorrect
+// type.
+//
+// (See TrySetField for more info on types.)
+func (m *Message) TryAddRepeatedFieldByName(name string, val interface{}) error {
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return UnknownFieldNameError
+ }
+ return m.addRepeatedField(fd, val)
+}
+
+// AddRepeatedFieldByNumber appends the given value to the repeated field with
+// the given tag number. It panics if an error is encountered. See
+// TryAddRepeatedFieldByNumber.
+func (m *Message) AddRepeatedFieldByNumber(tagNumber int, val interface{}) {
+ if err := m.TryAddRepeatedFieldByNumber(tagNumber, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TryAddRepeatedFieldByNumber appends the given value to the repeated field
+// with the given tag number. An error is returned if the given tag is unknown,
+// if it indicates a field that is not repeated, or if the given value has an
+// incorrect type.
+//
+// (See TrySetField for more info on types.)
+func (m *Message) TryAddRepeatedFieldByNumber(tagNumber int, val interface{}) error {
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return UnknownTagNumberError
+ }
+ return m.addRepeatedField(fd, val)
+}
+
+func (m *Message) addRepeatedField(fd *desc.FieldDescriptor, val interface{}) error {
+ if !fd.IsRepeated() {
+ return FieldIsNotRepeatedError
+ }
+ val, err := validElementFieldValue(fd, val)
+ if err != nil {
+ return err
+ }
+
+ if fd.IsMap() {
+ // We're lenient. Just as we allow setting a map field to a slice of entry messages, we also allow
+ // adding entries one at a time (as if the field were a normal repeated field).
+ msg := val.(proto.Message)
+ dm, err := asDynamicMessage(msg, fd.GetMessageType(), m.mf)
+ if err != nil {
+ return err
+ }
+ k, err := dm.TryGetFieldByNumber(1)
+ if err != nil {
+ return err
+ }
+ v, err := dm.TryGetFieldByNumber(2)
+ if err != nil {
+ return err
+ }
+ return m.putMapField(fd, k, v)
+ }
+
+ sl := m.values[fd.GetNumber()]
+ if sl == nil {
+ if sl, err = m.parseUnknownField(fd); err != nil {
+ return err
+ } else if sl == nil {
+ sl = []interface{}{}
+ }
+ }
+ res := sl.([]interface{})
+ res = append(res, val)
+ m.internalSetField(fd, res)
+ return nil
+}
+
+// SetRepeatedField sets the value for the given repeated field descriptor and
+// given index to the given value. It panics if an error is encountered. See
+// SetRepeatedField.
+func (m *Message) SetRepeatedField(fd *desc.FieldDescriptor, index int, val interface{}) {
+ if err := m.TrySetRepeatedField(fd, index, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TrySetRepeatedField sets the value for the given repeated field descriptor
+// and given index to the given value. An error is returned if the given field
+// descriptor does not belong to the right message type, if the given field is
+// not repeated, or if the given value is not a correct/compatible type for the
+// given field. Also, even though map fields technically are repeated fields, if
+// the given field is a map field an error will result: map representation does
+// not lend itself to random access by index.
+//
+// The Go type expected for a field is the same as required by TrySetField for
+// a non-repeated field of the same type.
+//
+// If the given field descriptor is not known (e.g. not present in the message
+// descriptor) it will become known. Subsequent operations using tag numbers or
+// names will be able to resolve the newly-known type. If the message has a
+// value for the unknown value, it is parsed and the element at the given index
+// is replaced with the given value.
+func (m *Message) TrySetRepeatedField(fd *desc.FieldDescriptor, index int, val interface{}) error {
+ if index < 0 {
+ return IndexOutOfRangeError
+ }
+ if err := m.checkField(fd); err != nil {
+ return err
+ }
+ return m.setRepeatedField(fd, index, val)
+}
+
+// SetRepeatedFieldByName sets the value for the repeated field with the given
+// name and given index to the given value. It panics if an error is
+// encountered. See TrySetRepeatedFieldByName.
+func (m *Message) SetRepeatedFieldByName(name string, index int, val interface{}) {
+ if err := m.TrySetRepeatedFieldByName(name, index, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TrySetRepeatedFieldByName sets the value for the repeated field with the
+// given name and the given index to the given value. An error is returned if
+// the given name is unknown, if it names a field that is not repeated (or is a
+// map field), or if the given value has an incorrect type.
+//
+// (See TrySetField for more info on types.)
+func (m *Message) TrySetRepeatedFieldByName(name string, index int, val interface{}) error {
+ if index < 0 {
+ return IndexOutOfRangeError
+ }
+ fd := m.FindFieldDescriptorByName(name)
+ if fd == nil {
+ return UnknownFieldNameError
+ }
+ return m.setRepeatedField(fd, index, val)
+}
+
+// SetRepeatedFieldByNumber sets the value for the repeated field with the given
+// tag number and given index to the given value. It panics if an error is
+// encountered. See TrySetRepeatedFieldByNumber.
+func (m *Message) SetRepeatedFieldByNumber(tagNumber int, index int, val interface{}) {
+ if err := m.TrySetRepeatedFieldByNumber(tagNumber, index, val); err != nil {
+ panic(err.Error())
+ }
+}
+
+// TrySetRepeatedFieldByNumber sets the value for the repeated field with the
+// given tag number and the given index to the given value. An error is returned
+// if the given tag is unknown, if it indicates a field that is not repeated (or
+// is a map field), or if the given value has an incorrect type.
+//
+// (See TrySetField for more info on types.)
+func (m *Message) TrySetRepeatedFieldByNumber(tagNumber int, index int, val interface{}) error {
+ if index < 0 {
+ return IndexOutOfRangeError
+ }
+ fd := m.FindFieldDescriptor(int32(tagNumber))
+ if fd == nil {
+ return UnknownTagNumberError
+ }
+ return m.setRepeatedField(fd, index, val)
+}
+
+func (m *Message) setRepeatedField(fd *desc.FieldDescriptor, index int, val interface{}) error {
+ if fd.IsMap() || !fd.IsRepeated() {
+ return FieldIsNotRepeatedError
+ }
+ val, err := validElementFieldValue(fd, val)
+ if err != nil {
+ return err
+ }
+ sl := m.values[fd.GetNumber()]
+ if sl == nil {
+ if sl, err = m.parseUnknownField(fd); err != nil {
+ return err
+ } else if sl == nil {
+ return IndexOutOfRangeError
+ }
+ }
+ res := sl.([]interface{})
+ if index >= len(res) {
+ return IndexOutOfRangeError
+ }
+ res[index] = val
+ return nil
+}
+
+// GetUnknownField gets the value(s) for the given unknown tag number. If this
+// message has no unknown fields with the given tag, nil is returned.
+func (m *Message) GetUnknownField(tagNumber int32) []UnknownField {
+ if u, ok := m.unknownFields[tagNumber]; ok {
+ return u
+ } else {
+ return nil
+ }
+}
+
+func (m *Message) parseUnknownField(fd *desc.FieldDescriptor) (interface{}, error) {
+ unks, ok := m.unknownFields[fd.GetNumber()]
+ if !ok {
+ return nil, nil
+ }
+ var v interface{}
+ var sl []interface{}
+ var mp map[interface{}]interface{}
+ if fd.IsMap() {
+ mp = map[interface{}]interface{}{}
+ }
+ var err error
+ for _, unk := range unks {
+ var val interface{}
+ if unk.Encoding == proto.WireBytes || unk.Encoding == proto.WireStartGroup {
+ val, err = codec.DecodeLengthDelimitedField(fd, unk.Contents, m.mf)
+ } else {
+ val, err = codec.DecodeScalarField(fd, unk.Value)
+ }
+ if err != nil {
+ return nil, err
+ }
+ if fd.IsMap() {
+ newEntry := val.(*Message)
+ kk, err := newEntry.TryGetFieldByNumber(1)
+ if err != nil {
+ return nil, err
+ }
+ vv, err := newEntry.TryGetFieldByNumber(2)
+ if err != nil {
+ return nil, err
+ }
+ mp[kk] = vv
+ v = mp
+ } else if fd.IsRepeated() {
+ t := reflect.TypeOf(val)
+ if t.Kind() == reflect.Slice && t != typeOfBytes {
+ // append slices if we unmarshalled a packed repeated field
+ newVals := val.([]interface{})
+ sl = append(sl, newVals...)
+ } else {
+ sl = append(sl, val)
+ }
+ v = sl
+ } else {
+ v = val
+ }
+ }
+ m.internalSetField(fd, v)
+ return v, nil
+}
+
+func validFieldValue(fd *desc.FieldDescriptor, val interface{}) (interface{}, error) {
+ return validFieldValueForRv(fd, reflect.ValueOf(val))
+}
+
+func validFieldValueForRv(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
+ if fd.IsMap() && val.Kind() == reflect.Map {
+ return validFieldValueForMapField(fd, val)
+ }
+
+ if fd.IsRepeated() { // this will also catch map fields where given value was not a map
+ if val.Kind() != reflect.Array && val.Kind() != reflect.Slice {
+ if fd.IsMap() {
+ return nil, fmt.Errorf("value for map field must be a map; instead was %v", val.Type())
+ } else {
+ return nil, fmt.Errorf("value for repeated field must be a slice; instead was %v", val.Type())
+ }
+ }
+
+ if fd.IsMap() {
+ // value should be a slice of entry messages that we need convert into a map[interface{}]interface{}
+ m := map[interface{}]interface{}{}
+ for i := 0; i < val.Len(); i++ {
+ e, err := validElementFieldValue(fd, val.Index(i).Interface())
+ if err != nil {
+ return nil, err
+ }
+ msg := e.(proto.Message)
+ dm, err := asDynamicMessage(msg, fd.GetMessageType(), nil)
+ if err != nil {
+ return nil, err
+ }
+ k, err := dm.TryGetFieldByNumber(1)
+ if err != nil {
+ return nil, err
+ }
+ v, err := dm.TryGetFieldByNumber(2)
+ if err != nil {
+ return nil, err
+ }
+ m[k] = v
+ }
+ return m, nil
+ }
+
+ // make a defensive copy while checking contents (also converts to []interface{})
+ s := make([]interface{}, val.Len())
+ for i := 0; i < val.Len(); i++ {
+ ev := val.Index(i)
+ if ev.Kind() == reflect.Interface {
+ // unwrap it
+ ev = reflect.ValueOf(ev.Interface())
+ }
+ e, err := validElementFieldValueForRv(fd, ev)
+ if err != nil {
+ return nil, err
+ }
+ s[i] = e
+ }
+
+ return s, nil
+ }
+
+ return validElementFieldValueForRv(fd, val)
+}
+
+func asDynamicMessage(m proto.Message, md *desc.MessageDescriptor, mf *MessageFactory) (*Message, error) {
+ if dm, ok := m.(*Message); ok {
+ return dm, nil
+ }
+ dm := NewMessageWithMessageFactory(md, mf)
+ if err := dm.mergeFrom(m); err != nil {
+ return nil, err
+ }
+ return dm, nil
+}
+
+func validElementFieldValue(fd *desc.FieldDescriptor, val interface{}) (interface{}, error) {
+ return validElementFieldValueForRv(fd, reflect.ValueOf(val))
+}
+
+func validElementFieldValueForRv(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
+ t := fd.GetType()
+ if !val.IsValid() {
+ return nil, typeError(fd, nil)
+ }
+
+ switch t {
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED32,
+ descriptor.FieldDescriptorProto_TYPE_INT32,
+ descriptor.FieldDescriptorProto_TYPE_SINT32,
+ descriptor.FieldDescriptorProto_TYPE_ENUM:
+ return toInt32(reflect.Indirect(val), fd)
+
+ case descriptor.FieldDescriptorProto_TYPE_SFIXED64,
+ descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_SINT64:
+ return toInt64(reflect.Indirect(val), fd)
+
+ case descriptor.FieldDescriptorProto_TYPE_FIXED32,
+ descriptor.FieldDescriptorProto_TYPE_UINT32:
+ return toUint32(reflect.Indirect(val), fd)
+
+ case descriptor.FieldDescriptorProto_TYPE_FIXED64,
+ descriptor.FieldDescriptorProto_TYPE_UINT64:
+ return toUint64(reflect.Indirect(val), fd)
+
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ return toFloat32(reflect.Indirect(val), fd)
+
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ return toFloat64(reflect.Indirect(val), fd)
+
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ return toBool(reflect.Indirect(val), fd)
+
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ return toBytes(reflect.Indirect(val), fd)
+
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ return toString(reflect.Indirect(val), fd)
+
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE,
+ descriptor.FieldDescriptorProto_TYPE_GROUP:
+ m, err := asMessage(val, fd.GetFullyQualifiedName())
+ // check that message is correct type
+ if err != nil {
+ return nil, err
+ }
+ var msgType string
+ if dm, ok := m.(*Message); ok {
+ msgType = dm.GetMessageDescriptor().GetFullyQualifiedName()
+ } else {
+ msgType = proto.MessageName(m)
+ }
+ if msgType != fd.GetMessageType().GetFullyQualifiedName() {
+ return nil, fmt.Errorf("message field %s requires value of type %s; received %s", fd.GetFullyQualifiedName(), fd.GetMessageType().GetFullyQualifiedName(), msgType)
+ }
+ return m, nil
+
+ default:
+ return nil, fmt.Errorf("unable to handle unrecognized field type: %v", fd.GetType())
+ }
+}
+
+func toInt32(v reflect.Value, fd *desc.FieldDescriptor) (int32, error) {
+ if v.Kind() == reflect.Int32 {
+ return int32(v.Int()), nil
+ }
+ return 0, typeError(fd, v.Type())
+}
+
+func toUint32(v reflect.Value, fd *desc.FieldDescriptor) (uint32, error) {
+ if v.Kind() == reflect.Uint32 {
+ return uint32(v.Uint()), nil
+ }
+ return 0, typeError(fd, v.Type())
+}
+
+func toFloat32(v reflect.Value, fd *desc.FieldDescriptor) (float32, error) {
+ if v.Kind() == reflect.Float32 {
+ return float32(v.Float()), nil
+ }
+ return 0, typeError(fd, v.Type())
+}
+
+func toInt64(v reflect.Value, fd *desc.FieldDescriptor) (int64, error) {
+ if v.Kind() == reflect.Int64 || v.Kind() == reflect.Int || v.Kind() == reflect.Int32 {
+ return v.Int(), nil
+ }
+ return 0, typeError(fd, v.Type())
+}
+
+func toUint64(v reflect.Value, fd *desc.FieldDescriptor) (uint64, error) {
+ if v.Kind() == reflect.Uint64 || v.Kind() == reflect.Uint || v.Kind() == reflect.Uint32 {
+ return v.Uint(), nil
+ }
+ return 0, typeError(fd, v.Type())
+}
+
+func toFloat64(v reflect.Value, fd *desc.FieldDescriptor) (float64, error) {
+ if v.Kind() == reflect.Float64 || v.Kind() == reflect.Float32 {
+ return v.Float(), nil
+ }
+ return 0, typeError(fd, v.Type())
+}
+
+func toBool(v reflect.Value, fd *desc.FieldDescriptor) (bool, error) {
+ if v.Kind() == reflect.Bool {
+ return v.Bool(), nil
+ }
+ return false, typeError(fd, v.Type())
+}
+
+func toBytes(v reflect.Value, fd *desc.FieldDescriptor) ([]byte, error) {
+ if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 {
+ return v.Bytes(), nil
+ }
+ return nil, typeError(fd, v.Type())
+}
+
+func toString(v reflect.Value, fd *desc.FieldDescriptor) (string, error) {
+ if v.Kind() == reflect.String {
+ return v.String(), nil
+ }
+ return "", typeError(fd, v.Type())
+}
+
+func typeError(fd *desc.FieldDescriptor, t reflect.Type) error {
+ return fmt.Errorf(
+ "%s field %s is not compatible with value of type %v",
+ getTypeString(fd), fd.GetFullyQualifiedName(), t)
+}
+
+func getTypeString(fd *desc.FieldDescriptor) string {
+ return strings.ToLower(fd.GetType().String())
+}
+
+func asMessage(v reflect.Value, fieldName string) (proto.Message, error) {
+ t := v.Type()
+ // we need a pointer to a struct that implements proto.Message
+ if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct || !t.Implements(typeOfProtoMessage) {
+ return nil, fmt.Errorf("message field %s requires is not compatible with value of type %v", fieldName, v.Type())
+ }
+ return v.Interface().(proto.Message), nil
+}
+
+// Reset resets this message to an empty message. It removes all values set in
+// the message.
+func (m *Message) Reset() {
+ for k := range m.values {
+ delete(m.values, k)
+ }
+ for k := range m.unknownFields {
+ delete(m.unknownFields, k)
+ }
+}
+
+// String returns this message rendered in compact text format.
+func (m *Message) String() string {
+ b, err := m.MarshalText()
+ if err != nil {
+ panic(fmt.Sprintf("Failed to create string representation of message: %s", err.Error()))
+ }
+ return string(b)
+}
+
+// ProtoMessage is present to satisfy the proto.Message interface.
+func (m *Message) ProtoMessage() {
+}
+
+// ConvertTo converts this dynamic message into the given message. This is
+// shorthand for resetting then merging:
+// target.Reset()
+// m.MergeInto(target)
+func (m *Message) ConvertTo(target proto.Message) error {
+ if err := m.checkType(target); err != nil {
+ return err
+ }
+
+ target.Reset()
+ return m.mergeInto(target)
+}
+
+// ConvertFrom converts the given message into this dynamic message. This is
+// shorthand for resetting then merging:
+// m.Reset()
+// m.MergeFrom(target)
+func (m *Message) ConvertFrom(target proto.Message) error {
+ if err := m.checkType(target); err != nil {
+ return err
+ }
+
+ m.Reset()
+ return m.mergeFrom(target)
+}
+
+// MergeInto merges this dynamic message into the given message. All field
+// values in this message will be set on the given message. For map fields,
+// entries are added to the given message (if the given message has existing
+// values for like keys, they are overwritten). For slice fields, elements are
+// added.
+//
+// If the given message has a different set of known fields, it is possible for
+// some known fields in this message to be represented as unknown fields in the
+// given message after merging, and vice versa.
+func (m *Message) MergeInto(target proto.Message) error {
+ if err := m.checkType(target); err != nil {
+ return err
+ }
+ return m.mergeInto(target)
+}
+
+// MergeFrom merges the given message into this dynamic message. All field
+// values in the given message will be set on this message. For map fields,
+// entries are added to this message (if this message has existing values for
+// like keys, they are overwritten). For slice fields, elements are added.
+//
+// If the given message has a different set of known fields, it is possible for
+// some known fields in that message to be represented as unknown fields in this
+// message after merging, and vice versa.
+func (m *Message) MergeFrom(source proto.Message) error {
+ if err := m.checkType(source); err != nil {
+ return err
+ }
+ return m.mergeFrom(source)
+}
+
+// Merge implements the proto.Merger interface so that dynamic messages are
+// compatible with the proto.Merge function. It delegates to MergeFrom but will
+// panic on error as the proto.Merger interface doesn't allow for returning an
+// error.
+//
+// Unlike nearly all other methods, this method can work if this message's type
+// is not defined (such as instantiating the message without using NewMessage).
+// This is strictly so that dynamic message's are compatible with the
+// proto.Clone function, which instantiates a new message via reflection (thus
+// its message descriptor will not be set) and than calls Merge.
+func (m *Message) Merge(source proto.Message) {
+ if m.md == nil {
+ // To support proto.Clone, initialize the descriptor from the source.
+ if dm, ok := source.(*Message); ok {
+ m.md = dm.md
+ // also make sure the clone uses the same message factory and
+ // extensions and also knows about the same extra fields (if any)
+ m.mf = dm.mf
+ m.er = dm.er
+ m.extraFields = dm.extraFields
+ } else if md, err := desc.LoadMessageDescriptorForMessage(source); err != nil {
+ panic(err.Error())
+ } else {
+ m.md = md
+ }
+ }
+
+ if err := m.MergeFrom(source); err != nil {
+ panic(err.Error())
+ }
+}
+
+func (m *Message) checkType(target proto.Message) error {
+ if dm, ok := target.(*Message); ok {
+ if dm.md.GetFullyQualifiedName() != m.md.GetFullyQualifiedName() {
+ return fmt.Errorf("given message has wrong type: %q; expecting %q", dm.md.GetFullyQualifiedName(), m.md.GetFullyQualifiedName())
+ }
+ return nil
+ }
+
+ msgName := proto.MessageName(target)
+ if msgName != m.md.GetFullyQualifiedName() {
+ return fmt.Errorf("given message has wrong type: %q; expecting %q", msgName, m.md.GetFullyQualifiedName())
+ }
+ return nil
+}
+
+func (m *Message) mergeInto(pm proto.Message) error {
+ if dm, ok := pm.(*Message); ok {
+ return dm.mergeFrom(m)
+ }
+
+ target := reflect.ValueOf(pm)
+ if target.Kind() == reflect.Ptr {
+ target = target.Elem()
+ }
+
+ // track tags for which the dynamic message has data but the given
+ // message doesn't know about it
+ u := target.FieldByName("XXX_unrecognized")
+ var unknownTags map[int32]struct{}
+ if u.IsValid() && u.Type() == typeOfBytes {
+ unknownTags = map[int32]struct{}{}
+ for tag := range m.values {
+ unknownTags[tag] = struct{}{}
+ }
+ }
+
+ // check that we can successfully do the merge
+ structProps := proto.GetProperties(reflect.TypeOf(pm).Elem())
+ for _, prop := range structProps.Prop {
+ if prop.Tag == 0 {
+ continue // one-of or special field (such as XXX_unrecognized, etc.)
+ }
+ tag := int32(prop.Tag)
+ v, ok := m.values[tag]
+ if !ok {
+ continue
+ }
+ if unknownTags != nil {
+ delete(unknownTags, tag)
+ }
+ f := target.FieldByName(prop.Name)
+ ft := f.Type()
+ val := reflect.ValueOf(v)
+ if !canConvert(val, ft) {
+ return fmt.Errorf("cannot convert %v to %v", val.Type(), ft)
+ }
+ }
+ // check one-of fields
+ for _, oop := range structProps.OneofTypes {
+ prop := oop.Prop
+ tag := int32(prop.Tag)
+ v, ok := m.values[tag]
+ if !ok {
+ continue
+ }
+ if unknownTags != nil {
+ delete(unknownTags, tag)
+ }
+ stf, ok := oop.Type.Elem().FieldByName(prop.Name)
+ if !ok {
+ return fmt.Errorf("one-of field indicates struct field name %s, but type %v has no such field", prop.Name, oop.Type.Elem())
+ }
+ ft := stf.Type
+ val := reflect.ValueOf(v)
+ if !canConvert(val, ft) {
+ return fmt.Errorf("cannot convert %v to %v", val.Type(), ft)
+ }
+ }
+ // and check extensions, too
+ for tag, ext := range proto.RegisteredExtensions(pm) {
+ v, ok := m.values[tag]
+ if !ok {
+ continue
+ }
+ if unknownTags != nil {
+ delete(unknownTags, tag)
+ }
+ ft := reflect.TypeOf(ext.ExtensionType)
+ val := reflect.ValueOf(v)
+ if !canConvert(val, ft) {
+ return fmt.Errorf("cannot convert %v to %v", val.Type(), ft)
+ }
+ }
+
+ // now actually perform the merge
+ for _, prop := range structProps.Prop {
+ v, ok := m.values[int32(prop.Tag)]
+ if !ok {
+ continue
+ }
+ f := target.FieldByName(prop.Name)
+ if err := mergeVal(reflect.ValueOf(v), f); err != nil {
+ return err
+ }
+ }
+ // merge one-ofs
+ for _, oop := range structProps.OneofTypes {
+ prop := oop.Prop
+ tag := int32(prop.Tag)
+ v, ok := m.values[tag]
+ if !ok {
+ continue
+ }
+ oov := reflect.New(oop.Type.Elem())
+ f := oov.Elem().FieldByName(prop.Name)
+ if err := mergeVal(reflect.ValueOf(v), f); err != nil {
+ return err
+ }
+ target.Field(oop.Field).Set(oov)
+ }
+ // merge extensions, too
+ for tag, ext := range proto.RegisteredExtensions(pm) {
+ v, ok := m.values[tag]
+ if !ok {
+ continue
+ }
+ e := reflect.New(reflect.TypeOf(ext.ExtensionType)).Elem()
+ if err := mergeVal(reflect.ValueOf(v), e); err != nil {
+ return err
+ }
+ if err := proto.SetExtension(pm, ext, e.Interface()); err != nil {
+ // shouldn't happen since we already checked that the extension type was compatible above
+ return err
+ }
+ }
+
+ // if we have fields that the given message doesn't know about, add to its unknown fields
+ if len(unknownTags) > 0 {
+ ub := u.Interface().([]byte)
+ var b codec.Buffer
+ b.SetDeterministic(defaultDeterminism)
+ for tag := range unknownTags {
+ fd := m.FindFieldDescriptor(tag)
+ if err := b.EncodeFieldValue(fd, m.values[tag]); err != nil {
+ return err
+ }
+ }
+ ub = append(ub, b.Bytes()...)
+ u.Set(reflect.ValueOf(ub))
+ }
+
+ // finally, convey unknown fields into the given message by letting it unmarshal them
+ // (this will append to its unknown fields if not known; if somehow the given message recognizes
+ // a field even though the dynamic message did not, it will get correctly unmarshalled)
+ if unknownTags != nil && len(m.unknownFields) > 0 {
+ var b codec.Buffer
+ _ = m.marshalUnknownFields(&b)
+ _ = proto.UnmarshalMerge(b.Bytes(), pm)
+ }
+
+ return nil
+}
+
+func canConvert(src reflect.Value, target reflect.Type) bool {
+ if src.Kind() == reflect.Interface {
+ src = reflect.ValueOf(src.Interface())
+ }
+ srcType := src.Type()
+ // we allow convertible types instead of requiring exact types so that calling
+ // code can, for example, assign an enum constant to an enum field. In that case,
+ // one type is the enum type (a sub-type of int32) and the other may be the int32
+ // type. So we automatically do the conversion in that case.
+ if srcType.ConvertibleTo(target) {
+ return true
+ } else if target.Kind() == reflect.Ptr && srcType.ConvertibleTo(target.Elem()) {
+ return true
+ } else if target.Kind() == reflect.Slice {
+ if srcType.Kind() != reflect.Slice {
+ return false
+ }
+ et := target.Elem()
+ for i := 0; i < src.Len(); i++ {
+ if !canConvert(src.Index(i), et) {
+ return false
+ }
+ }
+ return true
+ } else if target.Kind() == reflect.Map {
+ if srcType.Kind() != reflect.Map {
+ return false
+ }
+ return canConvertMap(src, target)
+ } else if srcType == typeOfDynamicMessage && target.Implements(typeOfProtoMessage) {
+ z := reflect.Zero(target).Interface()
+ msgType := proto.MessageName(z.(proto.Message))
+ return msgType == src.Interface().(*Message).GetMessageDescriptor().GetFullyQualifiedName()
+ } else {
+ return false
+ }
+}
+
+func mergeVal(src, target reflect.Value) error {
+ if src.Kind() == reflect.Interface && !src.IsNil() {
+ src = src.Elem()
+ }
+ srcType := src.Type()
+ targetType := target.Type()
+ if srcType.ConvertibleTo(targetType) {
+ if targetType.Implements(typeOfProtoMessage) && !target.IsNil() {
+ Merge(target.Interface().(proto.Message), src.Convert(targetType).Interface().(proto.Message))
+ } else {
+ target.Set(src.Convert(targetType))
+ }
+ } else if targetType.Kind() == reflect.Ptr && srcType.ConvertibleTo(targetType.Elem()) {
+ if !src.CanAddr() {
+ target.Set(reflect.New(targetType.Elem()))
+ target.Elem().Set(src.Convert(targetType.Elem()))
+ } else {
+ target.Set(src.Addr().Convert(targetType))
+ }
+ } else if targetType.Kind() == reflect.Slice {
+ l := target.Len()
+ newL := l + src.Len()
+ if target.Cap() < newL {
+ // expand capacity of the slice and copy
+ newSl := reflect.MakeSlice(targetType, newL, newL)
+ for i := 0; i < target.Len(); i++ {
+ newSl.Index(i).Set(target.Index(i))
+ }
+ target.Set(newSl)
+ } else {
+ target.SetLen(newL)
+ }
+ for i := 0; i < src.Len(); i++ {
+ dest := target.Index(l + i)
+ if dest.Kind() == reflect.Ptr {
+ dest.Set(reflect.New(dest.Type().Elem()))
+ }
+ if err := mergeVal(src.Index(i), dest); err != nil {
+ return err
+ }
+ }
+ } else if targetType.Kind() == reflect.Map {
+ return mergeMapVal(src, target, targetType)
+ } else if srcType == typeOfDynamicMessage && targetType.Implements(typeOfProtoMessage) {
+ dm := src.Interface().(*Message)
+ if target.IsNil() {
+ target.Set(reflect.New(targetType.Elem()))
+ }
+ m := target.Interface().(proto.Message)
+ if err := dm.mergeInto(m); err != nil {
+ return err
+ }
+ } else {
+ return fmt.Errorf("cannot convert %v to %v", srcType, targetType)
+ }
+ return nil
+}
+
+func (m *Message) mergeFrom(pm proto.Message) error {
+ if dm, ok := pm.(*Message); ok {
+ // if given message is also a dynamic message, we merge differently
+ for tag, v := range dm.values {
+ fd := m.FindFieldDescriptor(tag)
+ if fd == nil {
+ fd = dm.FindFieldDescriptor(tag)
+ }
+ if err := mergeField(m, fd, v); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ pmrv := reflect.ValueOf(pm)
+ if pmrv.IsNil() {
+ // nil is an empty message, so nothing to do
+ return nil
+ }
+
+ // check that we can successfully do the merge
+ src := pmrv.Elem()
+ values := map[*desc.FieldDescriptor]interface{}{}
+ props := proto.GetProperties(reflect.TypeOf(pm).Elem())
+ if props == nil {
+ return fmt.Errorf("could not determine message properties to merge for %v", reflect.TypeOf(pm).Elem())
+ }
+
+ // regular fields
+ for _, prop := range props.Prop {
+ if prop.Tag == 0 {
+ continue // one-of or special field (such as XXX_unrecognized, etc.)
+ }
+ fd := m.FindFieldDescriptor(int32(prop.Tag))
+ if fd == nil {
+ // Our descriptor has different fields than this message object. So
+ // try to reflect on the message object's fields.
+ md, err := desc.LoadMessageDescriptorForMessage(pm)
+ if err != nil {
+ return err
+ }
+ fd = md.FindFieldByNumber(int32(prop.Tag))
+ if fd == nil {
+ return fmt.Errorf("message descriptor %q did not contain field for tag %d (%q)", md.GetFullyQualifiedName(), prop.Tag, prop.Name)
+ }
+ }
+ rv := src.FieldByName(prop.Name)
+ if (rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Slice) && rv.IsNil() {
+ continue
+ }
+ if v, err := validFieldValueForRv(fd, rv); err != nil {
+ return err
+ } else {
+ values[fd] = v
+ }
+ }
+
+ // one-of fields
+ for _, oop := range props.OneofTypes {
+ oov := src.Field(oop.Field).Elem()
+ if !oov.IsValid() || oov.Type() != oop.Type {
+ // this field is unset (in other words, one-of message field is not currently set to this option)
+ continue
+ }
+ prop := oop.Prop
+ rv := oov.Elem().FieldByName(prop.Name)
+ fd := m.FindFieldDescriptor(int32(prop.Tag))
+ if fd == nil {
+ // Our descriptor has different fields than this message object. So
+ // try to reflect on the message object's fields.
+ md, err := desc.LoadMessageDescriptorForMessage(pm)
+ if err != nil {
+ return err
+ }
+ fd = md.FindFieldByNumber(int32(prop.Tag))
+ if fd == nil {
+ return fmt.Errorf("message descriptor %q did not contain field for tag %d (%q in one-of %q)", md.GetFullyQualifiedName(), prop.Tag, prop.Name, src.Type().Field(oop.Field).Name)
+ }
+ }
+ if v, err := validFieldValueForRv(fd, rv); err != nil {
+ return err
+ } else {
+ values[fd] = v
+ }
+ }
+
+ // extension fields
+ rexts, _ := proto.ExtensionDescs(pm)
+ var unknownExtensions []byte
+ for _, ed := range rexts {
+ v, _ := proto.GetExtension(pm, ed)
+ if v == nil {
+ continue
+ }
+ if ed.ExtensionType == nil {
+ extBytes, _ := v.([]byte)
+ if len(extBytes) > 0 {
+ unknownExtensions = append(unknownExtensions, extBytes...)
+ }
+ continue
+ }
+ fd := m.er.FindExtension(m.md.GetFullyQualifiedName(), ed.Field)
+ if fd == nil {
+ var err error
+ if fd, err = desc.LoadFieldDescriptorForExtension(ed); err != nil {
+ return err
+ }
+ }
+ if v, err := validFieldValue(fd, v); err != nil {
+ return err
+ } else {
+ values[fd] = v
+ }
+ }
+
+ // now actually perform the merge
+ for fd, v := range values {
+ mergeField(m, fd, v)
+ }
+
+ u := src.FieldByName("XXX_unrecognized")
+ if u.IsValid() && u.Type() == typeOfBytes {
+ // ignore any error returned: pulling in unknown fields is best-effort
+ _ = m.UnmarshalMerge(u.Interface().([]byte))
+ }
+
+ // lastly, also extract any unknown extensions the message may have (unknown extensions
+ // are stored with other extensions, not in the XXX_unrecognized field, so we have to do
+ // more than just the step above...)
+ if len(unknownExtensions) > 0 {
+ // pulling in unknown fields is best-effort, so we just ignore errors
+ _ = m.UnmarshalMerge(unknownExtensions)
+ }
+ return nil
+}
+
+// Validate checks that all required fields are present. It returns an error if any are absent.
+func (m *Message) Validate() error {
+ missingFields := m.findMissingFields()
+ if len(missingFields) == 0 {
+ return nil
+ }
+ return fmt.Errorf("some required fields missing: %v", strings.Join(missingFields, ", "))
+}
+
+func (m *Message) findMissingFields() []string {
+ if m.md.IsProto3() {
+ // proto3 does not allow required fields
+ return nil
+ }
+ var missingFields []string
+ for _, fd := range m.md.GetFields() {
+ if fd.IsRequired() {
+ if _, ok := m.values[fd.GetNumber()]; !ok {
+ missingFields = append(missingFields, fd.GetName())
+ }
+ }
+ }
+ return missingFields
+}
+
+// ValidateRecursive checks that all required fields are present and also
+// recursively validates all fields who are also messages. It returns an error
+// if any required fields, in this message or nested within, are absent.
+func (m *Message) ValidateRecursive() error {
+ return m.validateRecursive("")
+}
+
+func (m *Message) validateRecursive(prefix string) error {
+ if missingFields := m.findMissingFields(); len(missingFields) > 0 {
+ for i := range missingFields {
+ missingFields[i] = fmt.Sprintf("%s%s", prefix, missingFields[i])
+ }
+ return fmt.Errorf("some required fields missing: %v", strings.Join(missingFields, ", "))
+ }
+
+ for tag, fld := range m.values {
+ fd := m.FindFieldDescriptor(tag)
+ var chprefix string
+ var md *desc.MessageDescriptor
+ checkMsg := func(pm proto.Message) error {
+ var dm *Message
+ if d, ok := pm.(*Message); ok {
+ dm = d
+ } else {
+ dm = m.mf.NewDynamicMessage(md)
+ if err := dm.ConvertFrom(pm); err != nil {
+ return nil
+ }
+ }
+ if err := dm.validateRecursive(chprefix); err != nil {
+ return err
+ }
+ return nil
+ }
+ isMap := fd.IsMap()
+ if isMap && fd.GetMapValueType().GetMessageType() != nil {
+ md = fd.GetMapValueType().GetMessageType()
+ mp := fld.(map[interface{}]interface{})
+ for k, v := range mp {
+ chprefix = fmt.Sprintf("%s%s[%v].", prefix, getName(fd), k)
+ if err := checkMsg(v.(proto.Message)); err != nil {
+ return err
+ }
+ }
+ } else if !isMap && fd.GetMessageType() != nil {
+ md = fd.GetMessageType()
+ if fd.IsRepeated() {
+ sl := fld.([]interface{})
+ for i, v := range sl {
+ chprefix = fmt.Sprintf("%s%s[%d].", prefix, getName(fd), i)
+ if err := checkMsg(v.(proto.Message)); err != nil {
+ return err
+ }
+ }
+ } else {
+ chprefix = fmt.Sprintf("%s%s.", prefix, getName(fd))
+ if err := checkMsg(fld.(proto.Message)); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+func getName(fd *desc.FieldDescriptor) string {
+ if fd.IsExtension() {
+ return fmt.Sprintf("(%s)", fd.GetFullyQualifiedName())
+ } else {
+ return fd.GetName()
+ }
+}
+
+// knownFieldTags return tags of present and recognized fields, in sorted order.
+func (m *Message) knownFieldTags() []int {
+ if len(m.values) == 0 {
+ return []int(nil)
+ }
+
+ keys := make([]int, len(m.values))
+ i := 0
+ for k := range m.values {
+ keys[i] = int(k)
+ i++
+ }
+
+ sort.Ints(keys)
+ return keys
+}
+
+// allKnownFieldTags return tags of present and recognized fields, including
+// those that are unset, in sorted order. This only includes extensions that are
+// present. Known but not-present extensions are not included in the returned
+// set of tags.
+func (m *Message) allKnownFieldTags() []int {
+ fds := m.md.GetFields()
+ keys := make([]int, 0, len(fds)+len(m.extraFields))
+
+ for k := range m.values {
+ keys = append(keys, int(k))
+ }
+
+ // also include known fields that are not present
+ for _, fd := range fds {
+ if _, ok := m.values[fd.GetNumber()]; !ok {
+ keys = append(keys, int(fd.GetNumber()))
+ }
+ }
+ for _, fd := range m.extraFields {
+ if !fd.IsExtension() { // skip extensions that are not present
+ if _, ok := m.values[fd.GetNumber()]; !ok {
+ keys = append(keys, int(fd.GetNumber()))
+ }
+ }
+ }
+
+ sort.Ints(keys)
+ return keys
+}
+
+// unknownFieldTags return tags of present but unrecognized fields, in sorted order.
+func (m *Message) unknownFieldTags() []int {
+ if len(m.unknownFields) == 0 {
+ return []int(nil)
+ }
+ keys := make([]int, len(m.unknownFields))
+ i := 0
+ for k := range m.unknownFields {
+ keys[i] = int(k)
+ i++
+ }
+ sort.Ints(keys)
+ return keys
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/equal.go b/vendor/github.com/jhump/protoreflect/dynamic/equal.go
new file mode 100644
index 0000000..5fbcc24
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/equal.go
@@ -0,0 +1,152 @@
+package dynamic
+
+import (
+ "bytes"
+ "reflect"
+
+ "github.com/golang/protobuf/proto"
+
+ "github.com/jhump/protoreflect/desc"
+)
+
+// Equal returns true if the given two dynamic messages are equal. Two messages are equal when they
+// have the same message type and same fields set to equal values. For proto3 messages, fields set
+// to their zero value are considered unset.
+func Equal(a, b *Message) bool {
+ if a.md.GetFullyQualifiedName() != b.md.GetFullyQualifiedName() {
+ return false
+ }
+ if len(a.values) != len(b.values) {
+ return false
+ }
+ if len(a.unknownFields) != len(b.unknownFields) {
+ return false
+ }
+ for tag, aval := range a.values {
+ bval, ok := b.values[tag]
+ if !ok {
+ return false
+ }
+ if !fieldsEqual(aval, bval) {
+ return false
+ }
+ }
+ for tag, au := range a.unknownFields {
+ bu, ok := b.unknownFields[tag]
+ if !ok {
+ return false
+ }
+ if len(au) != len(bu) {
+ return false
+ }
+ for i, aval := range au {
+ bval := bu[i]
+ if aval.Encoding != bval.Encoding {
+ return false
+ }
+ if aval.Encoding == proto.WireBytes || aval.Encoding == proto.WireStartGroup {
+ if !bytes.Equal(aval.Contents, bval.Contents) {
+ return false
+ }
+ } else if aval.Value != bval.Value {
+ return false
+ }
+ }
+ }
+ // all checks pass!
+ return true
+}
+
+func fieldsEqual(aval, bval interface{}) bool {
+ arv := reflect.ValueOf(aval)
+ brv := reflect.ValueOf(bval)
+ if arv.Type() != brv.Type() {
+ // it is possible that one is a dynamic message and one is not
+ apm, ok := aval.(proto.Message)
+ if !ok {
+ return false
+ }
+ bpm, ok := bval.(proto.Message)
+ if !ok {
+ return false
+ }
+ return MessagesEqual(apm, bpm)
+
+ } else {
+ switch arv.Kind() {
+ case reflect.Ptr:
+ apm, ok := aval.(proto.Message)
+ if !ok {
+ // Don't know how to compare pointer values that aren't messages!
+ // Maybe this should panic?
+ return false
+ }
+ bpm := bval.(proto.Message) // we know it will succeed because we know a and b have same type
+ return MessagesEqual(apm, bpm)
+
+ case reflect.Map:
+ return mapsEqual(arv, brv)
+
+ case reflect.Slice:
+ if arv.Type() == typeOfBytes {
+ return bytes.Equal(aval.([]byte), bval.([]byte))
+ } else {
+ return slicesEqual(arv, brv)
+ }
+
+ default:
+ return aval == bval
+ }
+ }
+}
+
+func slicesEqual(a, b reflect.Value) bool {
+ if a.Len() != b.Len() {
+ return false
+ }
+ for i := 0; i < a.Len(); i++ {
+ ai := a.Index(i)
+ bi := b.Index(i)
+ if !fieldsEqual(ai.Interface(), bi.Interface()) {
+ return false
+ }
+ }
+ return true
+}
+
+// MessagesEqual returns true if the given two messages are equal. Use this instead of proto.Equal
+// when one or both of the messages might be a dynamic message.
+func MessagesEqual(a, b proto.Message) bool {
+ da, aok := a.(*Message)
+ db, bok := b.(*Message)
+ // Both dynamic messages
+ if aok && bok {
+ return Equal(da, db)
+ }
+ // Neither dynamic messages
+ if !aok && !bok {
+ return proto.Equal(a, b)
+ }
+ // Mixed
+ if aok {
+ md, err := desc.LoadMessageDescriptorForMessage(b)
+ if err != nil {
+ return false
+ }
+ db = NewMessageWithMessageFactory(md, da.mf)
+ if db.ConvertFrom(b) != nil {
+ return false
+ }
+ return Equal(da, db)
+ } else {
+ md, err := desc.LoadMessageDescriptorForMessage(a)
+ if err != nil {
+ return false
+ }
+ da = NewMessageWithMessageFactory(md, db.mf)
+ if da.ConvertFrom(a) != nil {
+ return false
+ }
+ return Equal(da, db)
+ }
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/extension.go b/vendor/github.com/jhump/protoreflect/dynamic/extension.go
new file mode 100644
index 0000000..1d38161
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/extension.go
@@ -0,0 +1,46 @@
+package dynamic
+
+import (
+ "fmt"
+
+ "github.com/golang/protobuf/proto"
+
+ "github.com/jhump/protoreflect/codec"
+ "github.com/jhump/protoreflect/desc"
+)
+
+// SetExtension sets the given extension value. If the given message is not a
+// dynamic message, the given extension may not be recognized (or may differ
+// from the compiled and linked in version of the extension. So in that case,
+// this function will serialize the given value to bytes and then use
+// proto.SetRawExtension to set the value.
+func SetExtension(msg proto.Message, extd *desc.FieldDescriptor, val interface{}) error {
+ if !extd.IsExtension() {
+ return fmt.Errorf("given field %s is not an extension", extd.GetFullyQualifiedName())
+ }
+
+ if dm, ok := msg.(*Message); ok {
+ return dm.TrySetField(extd, val)
+ }
+
+ md, err := desc.LoadMessageDescriptorForMessage(msg)
+ if err != nil {
+ return err
+ }
+ if err := checkField(extd, md); err != nil {
+ return err
+ }
+
+ val, err = validFieldValue(extd, val)
+ if err != nil {
+ return err
+ }
+
+ var b codec.Buffer
+ b.SetDeterministic(defaultDeterminism)
+ if err := b.EncodeFieldValue(extd, val); err != nil {
+ return err
+ }
+ proto.SetRawExtension(msg, extd.GetNumber(), b.Bytes())
+ return nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/extension_registry.go b/vendor/github.com/jhump/protoreflect/dynamic/extension_registry.go
new file mode 100644
index 0000000..6876827
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/extension_registry.go
@@ -0,0 +1,241 @@
+package dynamic
+
+import (
+ "fmt"
+ "reflect"
+ "sync"
+
+ "github.com/golang/protobuf/proto"
+
+ "github.com/jhump/protoreflect/desc"
+)
+
+// ExtensionRegistry is a registry of known extension fields. This is used to parse
+// extension fields encountered when de-serializing a dynamic message.
+type ExtensionRegistry struct {
+ includeDefault bool
+ mu sync.RWMutex
+ exts map[string]map[int32]*desc.FieldDescriptor
+}
+
+// NewExtensionRegistryWithDefaults is a registry that includes all "default" extensions,
+// which are those that are statically linked into the current program (e.g. registered by
+// protoc-generated code via proto.RegisterExtension). Extensions explicitly added to the
+// registry will override any default extensions that are for the same extendee and have the
+// same tag number and/or name.
+func NewExtensionRegistryWithDefaults() *ExtensionRegistry {
+ return &ExtensionRegistry{includeDefault: true}
+}
+
+// AddExtensionDesc adds the given extensions to the registry.
+func (r *ExtensionRegistry) AddExtensionDesc(exts ...*proto.ExtensionDesc) error {
+ flds := make([]*desc.FieldDescriptor, len(exts))
+ for i, ext := range exts {
+ fd, err := desc.LoadFieldDescriptorForExtension(ext)
+ if err != nil {
+ return err
+ }
+ flds[i] = fd
+ }
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.exts == nil {
+ r.exts = map[string]map[int32]*desc.FieldDescriptor{}
+ }
+ for _, fd := range flds {
+ r.putExtensionLocked(fd)
+ }
+ return nil
+}
+
+// AddExtension adds the given extensions to the registry. The given extensions
+// will overwrite any previously added extensions that are for the same extendee
+// message and same extension tag number.
+func (r *ExtensionRegistry) AddExtension(exts ...*desc.FieldDescriptor) error {
+ for _, ext := range exts {
+ if !ext.IsExtension() {
+ return fmt.Errorf("given field is not an extension: %s", ext.GetFullyQualifiedName())
+ }
+ }
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.exts == nil {
+ r.exts = map[string]map[int32]*desc.FieldDescriptor{}
+ }
+ for _, ext := range exts {
+ r.putExtensionLocked(ext)
+ }
+ return nil
+}
+
+// AddExtensionsFromFile adds to the registry all extension fields defined in the given file descriptor.
+func (r *ExtensionRegistry) AddExtensionsFromFile(fd *desc.FileDescriptor) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ r.addExtensionsFromFileLocked(fd, false, nil)
+}
+
+// AddExtensionsFromFileRecursively adds to the registry all extension fields defined in the give file
+// descriptor and also recursively adds all extensions defined in that file's dependencies. This adds
+// extensions from the entire transitive closure for the given file.
+func (r *ExtensionRegistry) AddExtensionsFromFileRecursively(fd *desc.FileDescriptor) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ already := map[*desc.FileDescriptor]struct{}{}
+ r.addExtensionsFromFileLocked(fd, true, already)
+}
+
+func (r *ExtensionRegistry) addExtensionsFromFileLocked(fd *desc.FileDescriptor, recursive bool, alreadySeen map[*desc.FileDescriptor]struct{}) {
+ if _, ok := alreadySeen[fd]; ok {
+ return
+ }
+
+ if r.exts == nil {
+ r.exts = map[string]map[int32]*desc.FieldDescriptor{}
+ }
+ for _, ext := range fd.GetExtensions() {
+ r.putExtensionLocked(ext)
+ }
+ for _, msg := range fd.GetMessageTypes() {
+ r.addExtensionsFromMessageLocked(msg)
+ }
+
+ if recursive {
+ alreadySeen[fd] = struct{}{}
+ for _, dep := range fd.GetDependencies() {
+ r.addExtensionsFromFileLocked(dep, recursive, alreadySeen)
+ }
+ }
+}
+
+func (r *ExtensionRegistry) addExtensionsFromMessageLocked(md *desc.MessageDescriptor) {
+ for _, ext := range md.GetNestedExtensions() {
+ r.putExtensionLocked(ext)
+ }
+ for _, msg := range md.GetNestedMessageTypes() {
+ r.addExtensionsFromMessageLocked(msg)
+ }
+}
+
+func (r *ExtensionRegistry) putExtensionLocked(fd *desc.FieldDescriptor) {
+ msgName := fd.GetOwner().GetFullyQualifiedName()
+ m := r.exts[msgName]
+ if m == nil {
+ m = map[int32]*desc.FieldDescriptor{}
+ r.exts[msgName] = m
+ }
+ m[fd.GetNumber()] = fd
+}
+
+// FindExtension queries for the extension field with the given extendee name (must be a fully-qualified
+// message name) and tag number. If no extension is known, nil is returned.
+func (r *ExtensionRegistry) FindExtension(messageName string, tagNumber int32) *desc.FieldDescriptor {
+ if r == nil {
+ return nil
+ }
+ r.mu.RLock()
+ defer r.mu.RUnlock()
+ fd := r.exts[messageName][tagNumber]
+ if fd == nil && r.includeDefault {
+ ext := getDefaultExtensions(messageName)[tagNumber]
+ if ext != nil {
+ fd, _ = desc.LoadFieldDescriptorForExtension(ext)
+ }
+ }
+ return fd
+}
+
+// FindExtensionByName queries for the extension field with the given extendee name (must be a fully-qualified
+// message name) and field name (must also be a fully-qualified extension name). If no extension is known, nil
+// is returned.
+func (r *ExtensionRegistry) FindExtensionByName(messageName string, fieldName string) *desc.FieldDescriptor {
+ if r == nil {
+ return nil
+ }
+ r.mu.RLock()
+ defer r.mu.RUnlock()
+ for _, fd := range r.exts[messageName] {
+ if fd.GetFullyQualifiedName() == fieldName {
+ return fd
+ }
+ }
+ if r.includeDefault {
+ for _, ext := range getDefaultExtensions(messageName) {
+ fd, _ := desc.LoadFieldDescriptorForExtension(ext)
+ if fd.GetFullyQualifiedName() == fieldName {
+ return fd
+ }
+ }
+ }
+ return nil
+}
+
+// FindExtensionByJSONName queries for the extension field with the given extendee name (must be a fully-qualified
+// message name) and JSON field name (must also be a fully-qualified name). If no extension is known, nil is returned.
+// The fully-qualified JSON name is the same as the extension's normal fully-qualified name except that the last
+// component uses the field's JSON name (if present).
+func (r *ExtensionRegistry) FindExtensionByJSONName(messageName string, fieldName string) *desc.FieldDescriptor {
+ if r == nil {
+ return nil
+ }
+ r.mu.RLock()
+ defer r.mu.RUnlock()
+ for _, fd := range r.exts[messageName] {
+ if fd.GetFullyQualifiedJSONName() == fieldName {
+ return fd
+ }
+ }
+ if r.includeDefault {
+ for _, ext := range getDefaultExtensions(messageName) {
+ fd, _ := desc.LoadFieldDescriptorForExtension(ext)
+ if fd.GetFullyQualifiedJSONName() == fieldName {
+ return fd
+ }
+ }
+ }
+ return nil
+}
+
+func getDefaultExtensions(messageName string) map[int32]*proto.ExtensionDesc {
+ t := proto.MessageType(messageName)
+ if t != nil {
+ msg := reflect.Zero(t).Interface().(proto.Message)
+ return proto.RegisteredExtensions(msg)
+ }
+ return nil
+}
+
+// AllExtensionsForType returns all known extension fields for the given extendee name (must be a
+// fully-qualified message name).
+func (r *ExtensionRegistry) AllExtensionsForType(messageName string) []*desc.FieldDescriptor {
+ if r == nil {
+ return []*desc.FieldDescriptor(nil)
+ }
+ r.mu.RLock()
+ defer r.mu.RUnlock()
+ flds := r.exts[messageName]
+ var ret []*desc.FieldDescriptor
+ if r.includeDefault {
+ exts := getDefaultExtensions(messageName)
+ if len(exts) > 0 || len(flds) > 0 {
+ ret = make([]*desc.FieldDescriptor, 0, len(exts)+len(flds))
+ }
+ for tag, ext := range exts {
+ if _, ok := flds[tag]; ok {
+ // skip default extension and use the one explicitly registered instead
+ continue
+ }
+ fd, _ := desc.LoadFieldDescriptorForExtension(ext)
+ if fd != nil {
+ ret = append(ret, fd)
+ }
+ }
+ } else if len(flds) > 0 {
+ ret = make([]*desc.FieldDescriptor, 0, len(flds))
+ }
+
+ for _, ext := range flds {
+ ret = append(ret, ext)
+ }
+ return ret
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/indent.go b/vendor/github.com/jhump/protoreflect/dynamic/indent.go
new file mode 100644
index 0000000..bd7fcaa
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/indent.go
@@ -0,0 +1,76 @@
+package dynamic
+
+import "bytes"
+
+type indentBuffer struct {
+ bytes.Buffer
+ indent string
+ indentCount int
+ comma bool
+}
+
+func (b *indentBuffer) start() error {
+ if b.indentCount >= 0 {
+ b.indentCount++
+ return b.newLine(false)
+ }
+ return nil
+}
+
+func (b *indentBuffer) sep() error {
+ if b.indentCount >= 0 {
+ _, err := b.WriteString(": ")
+ return err
+ } else {
+ return b.WriteByte(':')
+ }
+}
+
+func (b *indentBuffer) end() error {
+ if b.indentCount >= 0 {
+ b.indentCount--
+ return b.newLine(false)
+ }
+ return nil
+}
+
+func (b *indentBuffer) maybeNext(first *bool) error {
+ if *first {
+ *first = false
+ return nil
+ } else {
+ return b.next()
+ }
+}
+
+func (b *indentBuffer) next() error {
+ if b.indentCount >= 0 {
+ return b.newLine(b.comma)
+ } else if b.comma {
+ return b.WriteByte(',')
+ } else {
+ return b.WriteByte(' ')
+ }
+}
+
+func (b *indentBuffer) newLine(comma bool) error {
+ if comma {
+ err := b.WriteByte(',')
+ if err != nil {
+ return err
+ }
+ }
+
+ err := b.WriteByte('\n')
+ if err != nil {
+ return err
+ }
+
+ for i := 0; i < b.indentCount; i++ {
+ _, err := b.WriteString(b.indent)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/json.go b/vendor/github.com/jhump/protoreflect/dynamic/json.go
new file mode 100644
index 0000000..7dfae09
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/json.go
@@ -0,0 +1,1238 @@
+package dynamic
+
+// JSON marshalling and unmarshalling for dynamic messages
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/golang/protobuf/jsonpb"
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/protoc-gen-go/descriptor"
+ // link in the well-known-types that have a special JSON format
+ _ "github.com/golang/protobuf/ptypes/any"
+ _ "github.com/golang/protobuf/ptypes/duration"
+ _ "github.com/golang/protobuf/ptypes/empty"
+ _ "github.com/golang/protobuf/ptypes/struct"
+ _ "github.com/golang/protobuf/ptypes/timestamp"
+ _ "github.com/golang/protobuf/ptypes/wrappers"
+
+ "github.com/jhump/protoreflect/desc"
+)
+
+var wellKnownTypeNames = map[string]struct{}{
+ "google.protobuf.Any": {},
+ "google.protobuf.Empty": {},
+ "google.protobuf.Duration": {},
+ "google.protobuf.Timestamp": {},
+ // struct.proto
+ "google.protobuf.Struct": {},
+ "google.protobuf.Value": {},
+ "google.protobuf.ListValue": {},
+ // wrappers.proto
+ "google.protobuf.DoubleValue": {},
+ "google.protobuf.FloatValue": {},
+ "google.protobuf.Int64Value": {},
+ "google.protobuf.UInt64Value": {},
+ "google.protobuf.Int32Value": {},
+ "google.protobuf.UInt32Value": {},
+ "google.protobuf.BoolValue": {},
+ "google.protobuf.StringValue": {},
+ "google.protobuf.BytesValue": {},
+}
+
+// MarshalJSON serializes this message to bytes in JSON format, returning an
+// error if the operation fails. The resulting bytes will be a valid UTF8
+// string.
+//
+// This method uses a compact form: no newlines, and spaces between fields and
+// between field identifiers and values are elided.
+//
+// This method is convenient shorthand for invoking MarshalJSONPB with a default
+// (zero value) marshaler:
+//
+// m.MarshalJSONPB(&jsonpb.Marshaler{})
+//
+// So enums are serialized using enum value name strings, and values that are
+// not present (including those with default/zero value for messages defined in
+// "proto3" syntax) are omitted.
+func (m *Message) MarshalJSON() ([]byte, error) {
+ return m.MarshalJSONPB(&jsonpb.Marshaler{})
+}
+
+// MarshalJSONIndent serializes this message to bytes in JSON format, returning
+// an error if the operation fails. The resulting bytes will be a valid UTF8
+// string.
+//
+// This method uses a "pretty-printed" form, with each field on its own line and
+// spaces between field identifiers and values. Indentation of two spaces is
+// used.
+//
+// This method is convenient shorthand for invoking MarshalJSONPB with a default
+// (zero value) marshaler:
+//
+// m.MarshalJSONPB(&jsonpb.Marshaler{Indent: " "})
+//
+// So enums are serialized using enum value name strings, and values that are
+// not present (including those with default/zero value for messages defined in
+// "proto3" syntax) are omitted.
+func (m *Message) MarshalJSONIndent() ([]byte, error) {
+ return m.MarshalJSONPB(&jsonpb.Marshaler{Indent: " "})
+}
+
+// MarshalJSONPB serializes this message to bytes in JSON format, returning an
+// error if the operation fails. The resulting bytes will be a valid UTF8
+// string. The given marshaler is used to convey options used during marshaling.
+//
+// If this message contains nested messages that are generated message types (as
+// opposed to dynamic messages), the given marshaler is used to marshal it.
+//
+// When marshaling any nested messages, any jsonpb.AnyResolver configured in the
+// given marshaler is augmented with knowledge of message types known to this
+// message's descriptor (and its enclosing file and set of transitive
+// dependencies).
+func (m *Message) MarshalJSONPB(opts *jsonpb.Marshaler) ([]byte, error) {
+ var b indentBuffer
+ b.indent = opts.Indent
+ if len(opts.Indent) == 0 {
+ b.indentCount = -1
+ }
+ b.comma = true
+ if err := m.marshalJSON(&b, opts); err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
+
+func (m *Message) marshalJSON(b *indentBuffer, opts *jsonpb.Marshaler) error {
+ if r, changed := wrapResolver(opts.AnyResolver, m.mf, m.md.GetFile()); changed {
+ newOpts := *opts
+ newOpts.AnyResolver = r
+ opts = &newOpts
+ }
+
+ if ok, err := marshalWellKnownType(m, b, opts); ok {
+ return err
+ }
+
+ err := b.WriteByte('{')
+ if err != nil {
+ return err
+ }
+ err = b.start()
+ if err != nil {
+ return err
+ }
+
+ var tags []int
+ if opts.EmitDefaults {
+ tags = m.allKnownFieldTags()
+ } else {
+ tags = m.knownFieldTags()
+ }
+
+ first := true
+
+ for _, tag := range tags {
+ itag := int32(tag)
+ fd := m.FindFieldDescriptor(itag)
+
+ v, ok := m.values[itag]
+ if !ok {
+ if fd.GetOneOf() != nil {
+ // don't print defaults for fields in a oneof
+ continue
+ }
+ v = fd.GetDefaultValue()
+ }
+
+ err := b.maybeNext(&first)
+ if err != nil {
+ return err
+ }
+ err = marshalKnownFieldJSON(b, fd, v, opts)
+ if err != nil {
+ return err
+ }
+ }
+
+ err = b.end()
+ if err != nil {
+ return err
+ }
+ err = b.WriteByte('}')
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func marshalWellKnownType(m *Message, b *indentBuffer, opts *jsonpb.Marshaler) (bool, error) {
+ fqn := m.md.GetFullyQualifiedName()
+ if _, ok := wellKnownTypeNames[fqn]; !ok {
+ return false, nil
+ }
+
+ msgType := proto.MessageType(fqn)
+ if msgType == nil {
+ // wtf?
+ panic(fmt.Sprintf("could not find registered message type for %q", fqn))
+ }
+
+ // convert dynamic message to well-known type and let jsonpb marshal it
+ msg := reflect.New(msgType.Elem()).Interface().(proto.Message)
+ if err := m.MergeInto(msg); err != nil {
+ return true, err
+ }
+ return true, opts.Marshal(b, msg)
+}
+
+func marshalKnownFieldJSON(b *indentBuffer, fd *desc.FieldDescriptor, v interface{}, opts *jsonpb.Marshaler) error {
+ var jsonName string
+ if opts.OrigName {
+ jsonName = fd.GetName()
+ } else {
+ jsonName = fd.AsFieldDescriptorProto().GetJsonName()
+ if jsonName == "" {
+ jsonName = fd.GetName()
+ }
+ }
+ if fd.IsExtension() {
+ var scope string
+ switch parent := fd.GetParent().(type) {
+ case *desc.FileDescriptor:
+ scope = parent.GetPackage()
+ default:
+ scope = parent.GetFullyQualifiedName()
+ }
+ if scope == "" {
+ jsonName = fmt.Sprintf("[%s]", jsonName)
+ } else {
+ jsonName = fmt.Sprintf("[%s.%s]", scope, jsonName)
+ }
+ }
+ err := writeJsonString(b, jsonName)
+ if err != nil {
+ return err
+ }
+ err = b.sep()
+ if err != nil {
+ return err
+ }
+
+ if isNil(v) {
+ _, err := b.WriteString("null")
+ return err
+ }
+
+ if fd.IsMap() {
+ err = b.WriteByte('{')
+ if err != nil {
+ return err
+ }
+ err = b.start()
+ if err != nil {
+ return err
+ }
+
+ md := fd.GetMessageType()
+ vfd := md.FindFieldByNumber(2)
+
+ mp := v.(map[interface{}]interface{})
+ keys := make([]interface{}, 0, len(mp))
+ for k := range mp {
+ keys = append(keys, k)
+ }
+ sort.Sort(sortable(keys))
+ first := true
+ for _, mk := range keys {
+ mv := mp[mk]
+ err := b.maybeNext(&first)
+ if err != nil {
+ return err
+ }
+
+ err = marshalKnownFieldMapEntryJSON(b, mk, vfd, mv, opts)
+ if err != nil {
+ return err
+ }
+ }
+
+ err = b.end()
+ if err != nil {
+ return err
+ }
+ return b.WriteByte('}')
+
+ } else if fd.IsRepeated() {
+ err = b.WriteByte('[')
+ if err != nil {
+ return err
+ }
+ err = b.start()
+ if err != nil {
+ return err
+ }
+
+ sl := v.([]interface{})
+ first := true
+ for _, slv := range sl {
+ err := b.maybeNext(&first)
+ if err != nil {
+ return err
+ }
+ err = marshalKnownFieldValueJSON(b, fd, slv, opts)
+ if err != nil {
+ return err
+ }
+ }
+
+ err = b.end()
+ if err != nil {
+ return err
+ }
+ return b.WriteByte(']')
+
+ } else {
+ return marshalKnownFieldValueJSON(b, fd, v, opts)
+ }
+}
+
+// sortable is used to sort map keys. Values will be integers (int32, int64, uint32, and uint64),
+// bools, or strings.
+type sortable []interface{}
+
+func (s sortable) Len() int {
+ return len(s)
+}
+
+func (s sortable) Less(i, j int) bool {
+ vi := s[i]
+ vj := s[j]
+ switch reflect.TypeOf(vi).Kind() {
+ case reflect.Int32:
+ return vi.(int32) < vj.(int32)
+ case reflect.Int64:
+ return vi.(int64) < vj.(int64)
+ case reflect.Uint32:
+ return vi.(uint32) < vj.(uint32)
+ case reflect.Uint64:
+ return vi.(uint64) < vj.(uint64)
+ case reflect.String:
+ return vi.(string) < vj.(string)
+ case reflect.Bool:
+ return !vi.(bool) && vj.(bool)
+ default:
+ panic(fmt.Sprintf("cannot compare keys of type %v", reflect.TypeOf(vi)))
+ }
+}
+
+func (s sortable) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func isNil(v interface{}) bool {
+ if v == nil {
+ return true
+ }
+ rv := reflect.ValueOf(v)
+ return rv.Kind() == reflect.Ptr && rv.IsNil()
+}
+
+func marshalKnownFieldMapEntryJSON(b *indentBuffer, mk interface{}, vfd *desc.FieldDescriptor, mv interface{}, opts *jsonpb.Marshaler) error {
+ rk := reflect.ValueOf(mk)
+ var strkey string
+ switch rk.Kind() {
+ case reflect.Bool:
+ strkey = strconv.FormatBool(rk.Bool())
+ case reflect.Int32, reflect.Int64:
+ strkey = strconv.FormatInt(rk.Int(), 10)
+ case reflect.Uint32, reflect.Uint64:
+ strkey = strconv.FormatUint(rk.Uint(), 10)
+ case reflect.String:
+ strkey = rk.String()
+ default:
+ return fmt.Errorf("invalid map key value: %v (%v)", mk, rk.Type())
+ }
+ err := writeString(b, strkey)
+ if err != nil {
+ return err
+ }
+ err = b.sep()
+ if err != nil {
+ return err
+ }
+ return marshalKnownFieldValueJSON(b, vfd, mv, opts)
+}
+
+func marshalKnownFieldValueJSON(b *indentBuffer, fd *desc.FieldDescriptor, v interface{}, opts *jsonpb.Marshaler) error {
+ rv := reflect.ValueOf(v)
+ switch rv.Kind() {
+ case reflect.Int64:
+ return writeJsonString(b, strconv.FormatInt(rv.Int(), 10))
+ case reflect.Int32:
+ ed := fd.GetEnumType()
+ if !opts.EnumsAsInts && ed != nil {
+ n := int32(rv.Int())
+ vd := ed.FindValueByNumber(n)
+ if vd == nil {
+ _, err := b.WriteString(strconv.FormatInt(rv.Int(), 10))
+ return err
+ } else {
+ return writeJsonString(b, vd.GetName())
+ }
+ } else {
+ _, err := b.WriteString(strconv.FormatInt(rv.Int(), 10))
+ return err
+ }
+ case reflect.Uint64:
+ return writeJsonString(b, strconv.FormatUint(rv.Uint(), 10))
+ case reflect.Uint32:
+ _, err := b.WriteString(strconv.FormatUint(rv.Uint(), 10))
+ return err
+ case reflect.Float32, reflect.Float64:
+ f := rv.Float()
+ var str string
+ if math.IsNaN(f) {
+ str = `"NaN"`
+ } else if math.IsInf(f, 1) {
+ str = `"Infinity"`
+ } else if math.IsInf(f, -1) {
+ str = `"-Infinity"`
+ } else {
+ var bits int
+ if rv.Kind() == reflect.Float32 {
+ bits = 32
+ } else {
+ bits = 64
+ }
+ str = strconv.FormatFloat(rv.Float(), 'g', -1, bits)
+ }
+ _, err := b.WriteString(str)
+ return err
+ case reflect.Bool:
+ _, err := b.WriteString(strconv.FormatBool(rv.Bool()))
+ return err
+ case reflect.Slice:
+ bstr := base64.StdEncoding.EncodeToString(rv.Bytes())
+ return writeJsonString(b, bstr)
+ case reflect.String:
+ return writeJsonString(b, rv.String())
+ default:
+ // must be a message
+ if dm, ok := v.(*Message); ok {
+ return dm.marshalJSON(b, opts)
+ } else {
+ var err error
+ if b.indentCount <= 0 || len(b.indent) == 0 {
+ err = opts.Marshal(b, v.(proto.Message))
+ } else {
+ str, err := opts.MarshalToString(v.(proto.Message))
+ if err != nil {
+ return err
+ }
+ indent := strings.Repeat(b.indent, b.indentCount)
+ pos := 0
+ // add indention prefix to each line
+ for pos < len(str) {
+ start := pos
+ nextPos := strings.Index(str[pos:], "\n")
+ if nextPos == -1 {
+ nextPos = len(str)
+ } else {
+ nextPos = pos + nextPos + 1 // include newline
+ }
+ line := str[start:nextPos]
+ if pos > 0 {
+ _, err = b.WriteString(indent)
+ if err != nil {
+ return err
+ }
+ }
+ _, err = b.WriteString(line)
+ if err != nil {
+ return err
+ }
+ pos = nextPos
+ }
+ }
+ return err
+ }
+ }
+}
+
+func writeJsonString(b *indentBuffer, s string) error {
+ if sbytes, err := json.Marshal(s); err != nil {
+ return err
+ } else {
+ _, err := b.Write(sbytes)
+ return err
+ }
+}
+
+// UnmarshalJSON de-serializes the message that is present, in JSON format, in
+// the given bytes into this message. It first resets the current message. It
+// returns an error if the given bytes do not contain a valid encoding of this
+// message type in JSON format.
+//
+// This method is shorthand for invoking UnmarshalJSONPB with a default (zero
+// value) unmarshaler:
+//
+// m.UnmarshalMergeJSONPB(&jsonpb.Unmarshaler{}, js)
+//
+// So unknown fields will result in an error, and no provided jsonpb.AnyResolver
+// will be used when parsing google.protobuf.Any messages.
+func (m *Message) UnmarshalJSON(js []byte) error {
+ return m.UnmarshalJSONPB(&jsonpb.Unmarshaler{}, js)
+}
+
+// UnmarshalMergeJSON de-serializes the message that is present, in JSON format,
+// in the given bytes into this message. Unlike UnmarshalJSON, it does not first
+// reset the message, instead merging the data in the given bytes into the
+// existing data in this message.
+func (m *Message) UnmarshalMergeJSON(js []byte) error {
+ return m.UnmarshalMergeJSONPB(&jsonpb.Unmarshaler{}, js)
+}
+
+// UnmarshalJSONPB de-serializes the message that is present, in JSON format, in
+// the given bytes into this message. The given unmarshaler conveys options used
+// when parsing the JSON. This function first resets the current message. It
+// returns an error if the given bytes do not contain a valid encoding of this
+// message type in JSON format.
+//
+// The decoding is lenient:
+// 1. The JSON can refer to fields either by their JSON name or by their
+// declared name.
+// 2. The JSON can use either numeric values or string names for enum values.
+//
+// When instantiating nested messages, if this message's associated factory
+// returns a generated message type (as opposed to a dynamic message), the given
+// unmarshaler is used to unmarshal it.
+//
+// When unmarshaling any nested messages, any jsonpb.AnyResolver configured in
+// the given unmarshaler is augmented with knowledge of message types known to
+// this message's descriptor (and its enclosing file and set of transitive
+// dependencies).
+func (m *Message) UnmarshalJSONPB(opts *jsonpb.Unmarshaler, js []byte) error {
+ m.Reset()
+ if err := m.UnmarshalMergeJSONPB(opts, js); err != nil {
+ return err
+ }
+ return m.Validate()
+}
+
+// UnmarshalMergeJSONPB de-serializes the message that is present, in JSON
+// format, in the given bytes into this message. The given unmarshaler conveys
+// options used when parsing the JSON. Unlike UnmarshalJSONPB, it does not first
+// reset the message, instead merging the data in the given bytes into the
+// existing data in this message.
+func (m *Message) UnmarshalMergeJSONPB(opts *jsonpb.Unmarshaler, js []byte) error {
+ r := newJsReader(js)
+ err := m.unmarshalJson(r, opts)
+ if err != nil {
+ return err
+ }
+ if t, err := r.poll(); err != io.EOF {
+ b, _ := ioutil.ReadAll(r.unread())
+ s := fmt.Sprintf("%v%s", t, string(b))
+ return fmt.Errorf("superfluous data found after JSON object: %q", s)
+ }
+ return nil
+}
+
+func unmarshalWellKnownType(m *Message, r *jsReader, opts *jsonpb.Unmarshaler) (bool, error) {
+ fqn := m.md.GetFullyQualifiedName()
+ if _, ok := wellKnownTypeNames[fqn]; !ok {
+ return false, nil
+ }
+
+ msgType := proto.MessageType(fqn)
+ if msgType == nil {
+ // wtf?
+ panic(fmt.Sprintf("could not find registered message type for %q", fqn))
+ }
+
+ // extract json value from r
+ var js json.RawMessage
+ if err := json.NewDecoder(r.unread()).Decode(&js); err != nil {
+ return true, err
+ }
+ if err := r.skip(); err != nil {
+ return true, err
+ }
+
+ // unmarshal into well-known type and then convert to dynamic message
+ msg := reflect.New(msgType.Elem()).Interface().(proto.Message)
+ if err := opts.Unmarshal(bytes.NewReader(js), msg); err != nil {
+ return true, err
+ }
+ return true, m.MergeFrom(msg)
+}
+
+func (m *Message) unmarshalJson(r *jsReader, opts *jsonpb.Unmarshaler) error {
+ if r, changed := wrapResolver(opts.AnyResolver, m.mf, m.md.GetFile()); changed {
+ newOpts := *opts
+ newOpts.AnyResolver = r
+ opts = &newOpts
+ }
+
+ if ok, err := unmarshalWellKnownType(m, r, opts); ok {
+ return err
+ }
+
+ t, err := r.peek()
+ if err != nil {
+ return err
+ }
+ if t == nil {
+ // if json is simply "null" we do nothing
+ r.poll()
+ return nil
+ }
+
+ if err := r.beginObject(); err != nil {
+ return err
+ }
+
+ for r.hasNext() {
+ f, err := r.nextObjectKey()
+ if err != nil {
+ return err
+ }
+ fd := m.FindFieldDescriptorByJSONName(f)
+ if fd == nil {
+ if opts.AllowUnknownFields {
+ r.skip()
+ continue
+ }
+ return fmt.Errorf("message type %s has no known field named %s", m.md.GetFullyQualifiedName(), f)
+ }
+ v, err := unmarshalJsField(fd, r, m.mf, opts)
+ if err != nil {
+ return err
+ }
+ if v != nil {
+ if err := mergeField(m, fd, v); err != nil {
+ return err
+ }
+ } else if fd.GetOneOf() != nil {
+ // preserve explicit null for oneof fields (this is a little odd but
+ // mimics the behavior of jsonpb with oneofs in generated message types)
+ if fd.GetMessageType() != nil {
+ typ := m.mf.GetKnownTypeRegistry().GetKnownType(fd.GetMessageType().GetFullyQualifiedName())
+ if typ != nil {
+ // typed nil
+ if typ.Kind() != reflect.Ptr {
+ typ = reflect.PtrTo(typ)
+ }
+ v = reflect.Zero(typ).Interface()
+ } else {
+ // can't use nil dynamic message, so we just use empty one instead
+ v = m.mf.NewDynamicMessage(fd.GetMessageType())
+ }
+ if err := m.setField(fd, v); err != nil {
+ return err
+ }
+ } else {
+ // not a message... explicit null makes no sense
+ return fmt.Errorf("message type %s cannot set field %s to null: it is not a message type", m.md.GetFullyQualifiedName(), f)
+ }
+ } else {
+ m.clearField(fd)
+ }
+ }
+
+ if err := r.endObject(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func isWellKnownValue(fd *desc.FieldDescriptor) bool {
+ return !fd.IsRepeated() && fd.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE &&
+ fd.GetMessageType().GetFullyQualifiedName() == "google.protobuf.Value"
+}
+
+func isWellKnownListValue(fd *desc.FieldDescriptor) bool {
+ return !fd.IsRepeated() && fd.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE &&
+ fd.GetMessageType().GetFullyQualifiedName() == "google.protobuf.ListValue"
+}
+
+func unmarshalJsField(fd *desc.FieldDescriptor, r *jsReader, mf *MessageFactory, opts *jsonpb.Unmarshaler) (interface{}, error) {
+ t, err := r.peek()
+ if err != nil {
+ return nil, err
+ }
+ if t == nil && !isWellKnownValue(fd) {
+ // if value is null, just return nil
+ // (unless field is google.protobuf.Value, in which case
+ // we fall through to parse it as an instance where its
+ // underlying value is set to a NullValue)
+ r.poll()
+ return nil, nil
+ }
+
+ if t == json.Delim('{') && fd.IsMap() {
+ entryType := fd.GetMessageType()
+ keyType := entryType.FindFieldByNumber(1)
+ valueType := entryType.FindFieldByNumber(2)
+ mp := map[interface{}]interface{}{}
+
+ // TODO: if there are just two map keys "key" and "value" and they have the right type of values,
+ // treat this JSON object as a single map entry message. (In keeping with support of map fields as
+ // if they were normal repeated field of entry messages as well as supporting a transition from
+ // optional to repeated...)
+
+ if err := r.beginObject(); err != nil {
+ return nil, err
+ }
+ for r.hasNext() {
+ kk, err := unmarshalJsFieldElement(keyType, r, mf, opts)
+ if err != nil {
+ return nil, err
+ }
+ vv, err := unmarshalJsFieldElement(valueType, r, mf, opts)
+ if err != nil {
+ return nil, err
+ }
+ mp[kk] = vv
+ }
+ if err := r.endObject(); err != nil {
+ return nil, err
+ }
+
+ return mp, nil
+ } else if t == json.Delim('[') && !isWellKnownListValue(fd) {
+ // We support parsing an array, even if field is not repeated, to mimic support in proto
+ // binary wire format that supports changing an optional field to repeated and vice versa.
+ // If the field is not repeated, we only keep the last value in the array.
+
+ if err := r.beginArray(); err != nil {
+ return nil, err
+ }
+ var sl []interface{}
+ var v interface{}
+ for r.hasNext() {
+ var err error
+ v, err = unmarshalJsFieldElement(fd, r, mf, opts)
+ if err != nil {
+ return nil, err
+ }
+ if fd.IsRepeated() && v != nil {
+ sl = append(sl, v)
+ }
+ }
+ if err := r.endArray(); err != nil {
+ return nil, err
+ }
+ if fd.IsMap() {
+ mp := map[interface{}]interface{}{}
+ for _, m := range sl {
+ msg := m.(*Message)
+ kk, err := msg.TryGetFieldByNumber(1)
+ if err != nil {
+ return nil, err
+ }
+ vv, err := msg.TryGetFieldByNumber(2)
+ if err != nil {
+ return nil, err
+ }
+ mp[kk] = vv
+ }
+ return mp, nil
+ } else if fd.IsRepeated() {
+ return sl, nil
+ } else {
+ return v, nil
+ }
+ } else {
+ // We support parsing a singular value, even if field is repeated, to mimic support in proto
+ // binary wire format that supports changing an optional field to repeated and vice versa.
+ // If the field is repeated, we store value as singleton slice of that one value.
+
+ v, err := unmarshalJsFieldElement(fd, r, mf, opts)
+ if err != nil {
+ return nil, err
+ }
+ if v == nil {
+ return nil, nil
+ }
+ if fd.IsRepeated() {
+ return []interface{}{v}, nil
+ } else {
+ return v, nil
+ }
+ }
+}
+
+func unmarshalJsFieldElement(fd *desc.FieldDescriptor, r *jsReader, mf *MessageFactory, opts *jsonpb.Unmarshaler) (interface{}, error) {
+ t, err := r.peek()
+ if err != nil {
+ return nil, err
+ }
+
+ switch fd.GetType() {
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE,
+ descriptor.FieldDescriptorProto_TYPE_GROUP:
+ m := mf.NewMessage(fd.GetMessageType())
+ if dm, ok := m.(*Message); ok {
+ if err := dm.unmarshalJson(r, opts); err != nil {
+ return nil, err
+ }
+ } else {
+ var msg json.RawMessage
+ if err := json.NewDecoder(r.unread()).Decode(&msg); err != nil {
+ return nil, err
+ }
+ if err := r.skip(); err != nil {
+ return nil, err
+ }
+ if err := opts.Unmarshal(bytes.NewReader([]byte(msg)), m); err != nil {
+ return nil, err
+ }
+ }
+ return m, nil
+
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ if e, err := r.nextNumber(); err != nil {
+ return nil, err
+ } else {
+ // value could be string or number
+ if i, err := e.Int64(); err != nil {
+ // number cannot be parsed, so see if it's an enum value name
+ vd := fd.GetEnumType().FindValueByName(string(e))
+ if vd != nil {
+ return vd.GetNumber(), nil
+ } else {
+ return nil, fmt.Errorf("enum %q does not have value named %q", fd.GetEnumType().GetFullyQualifiedName(), e)
+ }
+ } else if i > math.MaxInt32 || i < math.MinInt32 {
+ return nil, NumericOverflowError
+ } else {
+ return int32(i), err
+ }
+ }
+
+ case descriptor.FieldDescriptorProto_TYPE_INT32,
+ descriptor.FieldDescriptorProto_TYPE_SINT32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ if i, err := r.nextInt(); err != nil {
+ return nil, err
+ } else if i > math.MaxInt32 || i < math.MinInt32 {
+ return nil, NumericOverflowError
+ } else {
+ return int32(i), err
+ }
+
+ case descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_SINT64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ return r.nextInt()
+
+ case descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ if i, err := r.nextUint(); err != nil {
+ return nil, err
+ } else if i > math.MaxUint32 {
+ return nil, NumericOverflowError
+ } else {
+ return uint32(i), err
+ }
+
+ case descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ return r.nextUint()
+
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ if str, ok := t.(string); ok {
+ if str == "true" {
+ r.poll() // consume token
+ return true, err
+ } else if str == "false" {
+ r.poll() // consume token
+ return false, err
+ }
+ }
+ return r.nextBool()
+
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ if f, err := r.nextFloat(); err != nil {
+ return nil, err
+ } else {
+ return float32(f), nil
+ }
+
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ return r.nextFloat()
+
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ return r.nextBytes()
+
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ return r.nextString()
+
+ default:
+ return nil, fmt.Errorf("unknown field type: %v", fd.GetType())
+ }
+}
+
+type jsReader struct {
+ reader *bytes.Reader
+ dec *json.Decoder
+ current json.Token
+ peeked bool
+}
+
+func newJsReader(b []byte) *jsReader {
+ reader := bytes.NewReader(b)
+ dec := json.NewDecoder(reader)
+ dec.UseNumber()
+ return &jsReader{reader: reader, dec: dec}
+}
+
+func (r *jsReader) unread() io.Reader {
+ bufs := make([]io.Reader, 3)
+ var peeked []byte
+ if r.peeked {
+ if _, ok := r.current.(json.Delim); ok {
+ peeked = []byte(fmt.Sprintf("%v", r.current))
+ } else {
+ peeked, _ = json.Marshal(r.current)
+ }
+ }
+ readerCopy := *r.reader
+ decCopy := *r.dec
+
+ bufs[0] = bytes.NewReader(peeked)
+ bufs[1] = decCopy.Buffered()
+ bufs[2] = &readerCopy
+ return &concatReader{bufs: bufs}
+}
+
+func (r *jsReader) hasNext() bool {
+ return r.dec.More()
+}
+
+func (r *jsReader) peek() (json.Token, error) {
+ if r.peeked {
+ return r.current, nil
+ }
+ t, err := r.dec.Token()
+ if err != nil {
+ return nil, err
+ }
+ r.peeked = true
+ r.current = t
+ return t, nil
+}
+
+func (r *jsReader) poll() (json.Token, error) {
+ if r.peeked {
+ ret := r.current
+ r.current = nil
+ r.peeked = false
+ return ret, nil
+ }
+ return r.dec.Token()
+}
+
+func (r *jsReader) beginObject() error {
+ _, err := r.expect(func(t json.Token) bool { return t == json.Delim('{') }, nil, "start of JSON object: '{'")
+ return err
+}
+
+func (r *jsReader) endObject() error {
+ _, err := r.expect(func(t json.Token) bool { return t == json.Delim('}') }, nil, "end of JSON object: '}'")
+ return err
+}
+
+func (r *jsReader) beginArray() error {
+ _, err := r.expect(func(t json.Token) bool { return t == json.Delim('[') }, nil, "start of array: '['")
+ return err
+}
+
+func (r *jsReader) endArray() error {
+ _, err := r.expect(func(t json.Token) bool { return t == json.Delim(']') }, nil, "end of array: ']'")
+ return err
+}
+
+func (r *jsReader) nextObjectKey() (string, error) {
+ return r.nextString()
+}
+
+func (r *jsReader) nextString() (string, error) {
+ t, err := r.expect(func(t json.Token) bool { _, ok := t.(string); return ok }, "", "string")
+ if err != nil {
+ return "", err
+ }
+ return t.(string), nil
+}
+
+func (r *jsReader) nextBytes() ([]byte, error) {
+ str, err := r.nextString()
+ if err != nil {
+ return nil, err
+ }
+ return base64.StdEncoding.DecodeString(str)
+}
+
+func (r *jsReader) nextBool() (bool, error) {
+ t, err := r.expect(func(t json.Token) bool { _, ok := t.(bool); return ok }, false, "boolean")
+ if err != nil {
+ return false, err
+ }
+ return t.(bool), nil
+}
+
+func (r *jsReader) nextInt() (int64, error) {
+ n, err := r.nextNumber()
+ if err != nil {
+ return 0, err
+ }
+ return n.Int64()
+}
+
+func (r *jsReader) nextUint() (uint64, error) {
+ n, err := r.nextNumber()
+ if err != nil {
+ return 0, err
+ }
+ return strconv.ParseUint(string(n), 10, 64)
+}
+
+func (r *jsReader) nextFloat() (float64, error) {
+ n, err := r.nextNumber()
+ if err != nil {
+ return 0, err
+ }
+ return n.Float64()
+}
+
+func (r *jsReader) nextNumber() (json.Number, error) {
+ t, err := r.expect(func(t json.Token) bool { return reflect.TypeOf(t).Kind() == reflect.String }, "0", "number")
+ if err != nil {
+ return "", err
+ }
+ switch t := t.(type) {
+ case json.Number:
+ return t, nil
+ case string:
+ return json.Number(t), nil
+ }
+ return "", fmt.Errorf("expecting a number but got %v", t)
+}
+
+func (r *jsReader) skip() error {
+ t, err := r.poll()
+ if err != nil {
+ return err
+ }
+ if t == json.Delim('[') {
+ if err := r.skipArray(); err != nil {
+ return err
+ }
+ } else if t == json.Delim('{') {
+ if err := r.skipObject(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (r *jsReader) skipArray() error {
+ for r.hasNext() {
+ if err := r.skip(); err != nil {
+ return err
+ }
+ }
+ if err := r.endArray(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (r *jsReader) skipObject() error {
+ for r.hasNext() {
+ // skip object key
+ if err := r.skip(); err != nil {
+ return err
+ }
+ // and value
+ if err := r.skip(); err != nil {
+ return err
+ }
+ }
+ if err := r.endObject(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (r *jsReader) expect(predicate func(json.Token) bool, ifNil interface{}, expected string) (interface{}, error) {
+ t, err := r.poll()
+ if err != nil {
+ return nil, err
+ }
+ if t == nil && ifNil != nil {
+ return ifNil, nil
+ }
+ if !predicate(t) {
+ return t, fmt.Errorf("bad input: expecting %s ; instead got %v", expected, t)
+ }
+ return t, nil
+}
+
+type concatReader struct {
+ bufs []io.Reader
+ curr int
+}
+
+func (r *concatReader) Read(p []byte) (n int, err error) {
+ for {
+ if r.curr >= len(r.bufs) {
+ err = io.EOF
+ return
+ }
+ var c int
+ c, err = r.bufs[r.curr].Read(p)
+ n += c
+ if err != io.EOF {
+ return
+ }
+ r.curr++
+ p = p[c:]
+ }
+}
+
+// AnyResolver returns a jsonpb.AnyResolver that uses the given file descriptors
+// to resolve message names. It uses the given factory, which may be nil, to
+// instantiate messages. The messages that it returns when resolving a type name
+// may often be dynamic messages.
+func AnyResolver(mf *MessageFactory, files ...*desc.FileDescriptor) jsonpb.AnyResolver {
+ return &anyResolver{mf: mf, files: files}
+}
+
+type anyResolver struct {
+ mf *MessageFactory
+ files []*desc.FileDescriptor
+ ignored map[*desc.FileDescriptor]struct{}
+ other jsonpb.AnyResolver
+}
+
+func wrapResolver(r jsonpb.AnyResolver, mf *MessageFactory, f *desc.FileDescriptor) (jsonpb.AnyResolver, bool) {
+ if r, ok := r.(*anyResolver); ok {
+ if _, ok := r.ignored[f]; ok {
+ // if the current resolver is ignoring this file, it's because another
+ // (upstream) resolver is already handling it, so nothing to do
+ return r, false
+ }
+ for _, file := range r.files {
+ if file == f {
+ // no need to wrap!
+ return r, false
+ }
+ }
+ // ignore files that will be checked by the resolver we're wrapping
+ // (we'll just delegate and let it search those files)
+ ignored := map[*desc.FileDescriptor]struct{}{}
+ for i := range r.ignored {
+ ignored[i] = struct{}{}
+ }
+ ignore(r.files, ignored)
+ return &anyResolver{mf: mf, files: []*desc.FileDescriptor{f}, ignored: ignored, other: r}, true
+ }
+ return &anyResolver{mf: mf, files: []*desc.FileDescriptor{f}, other: r}, true
+}
+
+func ignore(files []*desc.FileDescriptor, ignored map[*desc.FileDescriptor]struct{}) {
+ for _, f := range files {
+ if _, ok := ignored[f]; ok {
+ continue
+ }
+ ignored[f] = struct{}{}
+ ignore(f.GetDependencies(), ignored)
+ }
+}
+
+func (r *anyResolver) Resolve(typeUrl string) (proto.Message, error) {
+ mname := typeUrl
+ if slash := strings.LastIndex(mname, "/"); slash >= 0 {
+ mname = mname[slash+1:]
+ }
+
+ // see if the user-specified resolver is able to do the job
+ if r.other != nil {
+ msg, err := r.other.Resolve(typeUrl)
+ if err == nil {
+ return msg, nil
+ }
+ }
+
+ // try to find the message in our known set of files
+ checked := map[*desc.FileDescriptor]struct{}{}
+ for _, f := range r.files {
+ md := r.findMessage(f, mname, checked)
+ if md != nil {
+ return r.mf.NewMessage(md), nil
+ }
+ }
+ // failing that, see if the message factory knows about this type
+ var ktr *KnownTypeRegistry
+ if r.mf != nil {
+ ktr = r.mf.ktr
+ } else {
+ ktr = (*KnownTypeRegistry)(nil)
+ }
+ m := ktr.CreateIfKnown(mname)
+ if m != nil {
+ return m, nil
+ }
+
+ // no other resolver to fallback to? mimic default behavior
+ mt := proto.MessageType(mname)
+ if mt == nil {
+ return nil, fmt.Errorf("unknown message type %q", mname)
+ }
+ return reflect.New(mt.Elem()).Interface().(proto.Message), nil
+}
+
+func (r *anyResolver) findMessage(fd *desc.FileDescriptor, msgName string, checked map[*desc.FileDescriptor]struct{}) *desc.MessageDescriptor {
+ // if this is an ignored descriptor, skip
+ if _, ok := r.ignored[fd]; ok {
+ return nil
+ }
+
+ // bail if we've already checked this file
+ if _, ok := checked[fd]; ok {
+ return nil
+ }
+ checked[fd] = struct{}{}
+
+ // see if this file has the message
+ md := fd.FindMessage(msgName)
+ if md != nil {
+ return md
+ }
+
+ // if not, recursively search the file's imports
+ for _, dep := range fd.GetDependencies() {
+ md = r.findMessage(dep, msgName, checked)
+ if md != nil {
+ return md
+ }
+ }
+ return nil
+}
+
+var _ jsonpb.AnyResolver = (*anyResolver)(nil)
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/maps_1.11.go b/vendor/github.com/jhump/protoreflect/dynamic/maps_1.11.go
new file mode 100644
index 0000000..bb68d7b
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/maps_1.11.go
@@ -0,0 +1,129 @@
+//+build !go1.12
+
+package dynamic
+
+import (
+ "github.com/jhump/protoreflect/desc"
+ "reflect"
+)
+
+// Pre-Go-1.12, we must use reflect.Value.MapKeys to reflectively
+// iterate a map. (We can be more efficient in Go 1.12 and up...)
+
+func mapsEqual(a, b reflect.Value) bool {
+ if a.Len() != b.Len() {
+ return false
+ }
+ if a.Len() == 0 && b.Len() == 0 {
+ // Optimize the case where maps are frequently empty because MapKeys()
+ // function allocates heavily.
+ return true
+ }
+
+ for _, k := range a.MapKeys() {
+ av := a.MapIndex(k)
+ bv := b.MapIndex(k)
+ if !bv.IsValid() {
+ return false
+ }
+ if !fieldsEqual(av.Interface(), bv.Interface()) {
+ return false
+ }
+ }
+ return true
+}
+
+func validFieldValueForMapField(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
+ // make a defensive copy while we check the contents
+ // (also converts to map[interface{}]interface{} if it's some other type)
+ keyField := fd.GetMessageType().GetFields()[0]
+ valField := fd.GetMessageType().GetFields()[1]
+ m := map[interface{}]interface{}{}
+ for _, k := range val.MapKeys() {
+ if k.Kind() == reflect.Interface {
+ // unwrap it
+ k = reflect.ValueOf(k.Interface())
+ }
+ kk, err := validFieldValueForRv(keyField, k)
+ if err != nil {
+ return nil, err
+ }
+ v := val.MapIndex(k)
+ if v.Kind() == reflect.Interface {
+ // unwrap it
+ v = reflect.ValueOf(v.Interface())
+ }
+ vv, err := validFieldValueForRv(valField, v)
+ if err != nil {
+ return nil, err
+ }
+ m[kk] = vv
+ }
+ return m, nil
+}
+
+func canConvertMap(src reflect.Value, target reflect.Type) bool {
+ kt := target.Key()
+ vt := target.Elem()
+ for _, k := range src.MapKeys() {
+ if !canConvert(k, kt) {
+ return false
+ }
+ if !canConvert(src.MapIndex(k), vt) {
+ return false
+ }
+ }
+ return true
+}
+
+func mergeMapVal(src, target reflect.Value, targetType reflect.Type) error {
+ tkt := targetType.Key()
+ tvt := targetType.Elem()
+ for _, k := range src.MapKeys() {
+ v := src.MapIndex(k)
+ skt := k.Type()
+ svt := v.Type()
+ var nk, nv reflect.Value
+ if tkt == skt {
+ nk = k
+ } else if tkt.Kind() == reflect.Ptr && tkt.Elem() == skt {
+ nk = k.Addr()
+ } else {
+ nk = reflect.New(tkt).Elem()
+ if err := mergeVal(k, nk); err != nil {
+ return err
+ }
+ }
+ if tvt == svt {
+ nv = v
+ } else if tvt.Kind() == reflect.Ptr && tvt.Elem() == svt {
+ nv = v.Addr()
+ } else {
+ nv = reflect.New(tvt).Elem()
+ if err := mergeVal(v, nv); err != nil {
+ return err
+ }
+ }
+ if target.IsNil() {
+ target.Set(reflect.MakeMap(targetType))
+ }
+ target.SetMapIndex(nk, nv)
+ }
+ return nil
+}
+
+func mergeMapField(m *Message, fd *desc.FieldDescriptor, rv reflect.Value) error {
+ for _, k := range rv.MapKeys() {
+ if k.Kind() == reflect.Interface && !k.IsNil() {
+ k = k.Elem()
+ }
+ v := rv.MapIndex(k)
+ if v.Kind() == reflect.Interface && !v.IsNil() {
+ v = v.Elem()
+ }
+ if err := m.putMapField(fd, k.Interface(), v.Interface()); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/maps_1.12.go b/vendor/github.com/jhump/protoreflect/dynamic/maps_1.12.go
new file mode 100644
index 0000000..f5ffd67
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/maps_1.12.go
@@ -0,0 +1,137 @@
+//+build go1.12
+
+package dynamic
+
+import (
+ "github.com/jhump/protoreflect/desc"
+ "reflect"
+)
+
+// With Go 1.12 and above, we can use reflect.Value.MapRange to iterate
+// over maps more efficiently than using reflect.Value.MapKeys.
+
+func mapsEqual(a, b reflect.Value) bool {
+ if a.Len() != b.Len() {
+ return false
+ }
+ if a.Len() == 0 && b.Len() == 0 {
+ // Optimize the case where maps are frequently empty
+ return true
+ }
+
+ iter := a.MapRange()
+ for iter.Next() {
+ k := iter.Key()
+ av := iter.Value()
+ bv := b.MapIndex(k)
+ if !bv.IsValid() {
+ return false
+ }
+ if !fieldsEqual(av.Interface(), bv.Interface()) {
+ return false
+ }
+ }
+ return true
+}
+
+func validFieldValueForMapField(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
+ // make a defensive copy while we check the contents
+ // (also converts to map[interface{}]interface{} if it's some other type)
+ keyField := fd.GetMessageType().GetFields()[0]
+ valField := fd.GetMessageType().GetFields()[1]
+ m := map[interface{}]interface{}{}
+ iter := val.MapRange()
+ for iter.Next() {
+ k := iter.Key()
+ if k.Kind() == reflect.Interface {
+ // unwrap it
+ k = reflect.ValueOf(k.Interface())
+ }
+ kk, err := validFieldValueForRv(keyField, k)
+ if err != nil {
+ return nil, err
+ }
+ v := iter.Value()
+ if v.Kind() == reflect.Interface {
+ // unwrap it
+ v = reflect.ValueOf(v.Interface())
+ }
+ vv, err := validFieldValueForRv(valField, v)
+ if err != nil {
+ return nil, err
+ }
+ m[kk] = vv
+ }
+ return m, nil
+}
+
+func canConvertMap(src reflect.Value, target reflect.Type) bool {
+ kt := target.Key()
+ vt := target.Elem()
+ iter := src.MapRange()
+ for iter.Next() {
+ if !canConvert(iter.Key(), kt) {
+ return false
+ }
+ if !canConvert(iter.Value(), vt) {
+ return false
+ }
+ }
+ return true
+}
+
+func mergeMapVal(src, target reflect.Value, targetType reflect.Type) error {
+ tkt := targetType.Key()
+ tvt := targetType.Elem()
+ iter := src.MapRange()
+ for iter.Next() {
+ k := iter.Key()
+ v := iter.Value()
+ skt := k.Type()
+ svt := v.Type()
+ var nk, nv reflect.Value
+ if tkt == skt {
+ nk = k
+ } else if tkt.Kind() == reflect.Ptr && tkt.Elem() == skt {
+ nk = k.Addr()
+ } else {
+ nk = reflect.New(tkt).Elem()
+ if err := mergeVal(k, nk); err != nil {
+ return err
+ }
+ }
+ if tvt == svt {
+ nv = v
+ } else if tvt.Kind() == reflect.Ptr && tvt.Elem() == svt {
+ nv = v.Addr()
+ } else {
+ nv = reflect.New(tvt).Elem()
+ if err := mergeVal(v, nv); err != nil {
+ return err
+ }
+ }
+ if target.IsNil() {
+ target.Set(reflect.MakeMap(targetType))
+ }
+ target.SetMapIndex(nk, nv)
+ }
+ return nil
+}
+
+func mergeMapField(m *Message, fd *desc.FieldDescriptor, rv reflect.Value) error {
+ iter := rv.MapRange()
+ for iter.Next() {
+ k := iter.Key()
+ v := iter.Value()
+ if k.Kind() == reflect.Interface && !k.IsNil() {
+ k = k.Elem()
+ }
+ if v.Kind() == reflect.Interface && !v.IsNil() {
+ v = v.Elem()
+ }
+ if err := m.putMapField(fd, k.Interface(), v.Interface()); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/merge.go b/vendor/github.com/jhump/protoreflect/dynamic/merge.go
new file mode 100644
index 0000000..ce727fd
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/merge.go
@@ -0,0 +1,100 @@
+package dynamic
+
+import (
+ "errors"
+ "reflect"
+
+ "github.com/golang/protobuf/proto"
+
+ "github.com/jhump/protoreflect/desc"
+)
+
+// Merge merges the given source message into the given destination message. Use
+// use this instead of proto.Merge when one or both of the messages might be a
+// a dynamic message. If there is a problem merging the messages, such as the
+// two messages having different types, then this method will panic (just as
+// proto.Merges does).
+func Merge(dst, src proto.Message) {
+ if dm, ok := dst.(*Message); ok {
+ if err := dm.MergeFrom(src); err != nil {
+ panic(err.Error())
+ }
+ } else if dm, ok := src.(*Message); ok {
+ if err := dm.MergeInto(dst); err != nil {
+ panic(err.Error())
+ }
+ } else {
+ proto.Merge(dst, src)
+ }
+}
+
+// TryMerge merges the given source message into the given destination message.
+// You can use this instead of proto.Merge when one or both of the messages
+// might be a dynamic message. Unlike proto.Merge, this method will return an
+// error on failure instead of panic'ing.
+func TryMerge(dst, src proto.Message) error {
+ if dm, ok := dst.(*Message); ok {
+ if err := dm.MergeFrom(src); err != nil {
+ return err
+ }
+ } else if dm, ok := src.(*Message); ok {
+ if err := dm.MergeInto(dst); err != nil {
+ return err
+ }
+ } else {
+ // proto.Merge panics on bad input, so we first verify
+ // inputs and return error instead of panic
+ out := reflect.ValueOf(dst)
+ if out.IsNil() {
+ return errors.New("proto: nil destination")
+ }
+ in := reflect.ValueOf(src)
+ if in.Type() != out.Type() {
+ return errors.New("proto: type mismatch")
+ }
+ proto.Merge(dst, src)
+ }
+ return nil
+}
+
+func mergeField(m *Message, fd *desc.FieldDescriptor, val interface{}) error {
+ rv := reflect.ValueOf(val)
+
+ if fd.IsMap() && rv.Kind() == reflect.Map {
+ return mergeMapField(m, fd, rv)
+ }
+
+ if fd.IsRepeated() && rv.Kind() == reflect.Slice && rv.Type() != typeOfBytes {
+ for i := 0; i < rv.Len(); i++ {
+ e := rv.Index(i)
+ if e.Kind() == reflect.Interface && !e.IsNil() {
+ e = e.Elem()
+ }
+ if err := m.addRepeatedField(fd, e.Interface()); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ if fd.IsRepeated() {
+ return m.addRepeatedField(fd, val)
+ } else if fd.GetMessageType() == nil {
+ return m.setField(fd, val)
+ }
+
+ // it's a message type, so we want to merge contents
+ var err error
+ if val, err = validFieldValue(fd, val); err != nil {
+ return err
+ }
+
+ existing, _ := m.doGetField(fd, true)
+ if existing != nil && !reflect.ValueOf(existing).IsNil() {
+ return TryMerge(existing.(proto.Message), val.(proto.Message))
+ }
+
+ // no existing message, so just set field
+ m.internalSetField(fd, val)
+ return nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/message_factory.go b/vendor/github.com/jhump/protoreflect/dynamic/message_factory.go
new file mode 100644
index 0000000..6c54de8
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/message_factory.go
@@ -0,0 +1,189 @@
+package dynamic
+
+import (
+ "reflect"
+ "sync"
+
+ "github.com/golang/protobuf/proto"
+
+ "github.com/jhump/protoreflect/desc"
+)
+
+// MessageFactory can be used to create new empty message objects. A default instance
+// (without extension registry or known-type registry specified) will always return
+// dynamic messages (e.g. type will be *dynamic.Message) except for "well-known" types.
+// The well-known types include primitive wrapper types and a handful of other special
+// types defined in standard protobuf definitions, like Any, Duration, and Timestamp.
+type MessageFactory struct {
+ er *ExtensionRegistry
+ ktr *KnownTypeRegistry
+}
+
+// NewMessageFactoryWithExtensionRegistry creates a new message factory where any
+// dynamic messages produced will use the given extension registry to recognize and
+// parse extension fields.
+func NewMessageFactoryWithExtensionRegistry(er *ExtensionRegistry) *MessageFactory {
+ return NewMessageFactoryWithRegistries(er, nil)
+}
+
+// NewMessageFactoryWithKnownTypeRegistry creates a new message factory where the
+// known types, per the given registry, will be returned as normal protobuf messages
+// (e.g. generated structs, instead of dynamic messages).
+func NewMessageFactoryWithKnownTypeRegistry(ktr *KnownTypeRegistry) *MessageFactory {
+ return NewMessageFactoryWithRegistries(nil, ktr)
+}
+
+// NewMessageFactoryWithDefaults creates a new message factory where all "default" types
+// (those for which protoc-generated code is statically linked into the Go program) are
+// known types. If any dynamic messages are produced, they will recognize and parse all
+// "default" extension fields. This is the equivalent of:
+// NewMessageFactoryWithRegistries(
+// NewExtensionRegistryWithDefaults(),
+// NewKnownTypeRegistryWithDefaults())
+func NewMessageFactoryWithDefaults() *MessageFactory {
+ return NewMessageFactoryWithRegistries(NewExtensionRegistryWithDefaults(), NewKnownTypeRegistryWithDefaults())
+}
+
+// NewMessageFactoryWithRegistries creates a new message factory with the given extension
+// and known type registries.
+func NewMessageFactoryWithRegistries(er *ExtensionRegistry, ktr *KnownTypeRegistry) *MessageFactory {
+ return &MessageFactory{
+ er: er,
+ ktr: ktr,
+ }
+}
+
+// NewMessage creates a new empty message that corresponds to the given descriptor.
+// If the given descriptor describes a "known type" then that type is instantiated.
+// Otherwise, an empty dynamic message is returned.
+func (f *MessageFactory) NewMessage(md *desc.MessageDescriptor) proto.Message {
+ var ktr *KnownTypeRegistry
+ if f != nil {
+ ktr = f.ktr
+ }
+ if m := ktr.CreateIfKnown(md.GetFullyQualifiedName()); m != nil {
+ return m
+ }
+ return NewMessageWithMessageFactory(md, f)
+}
+
+// NewDynamicMessage creates a new empty dynamic message that corresponds to the given
+// descriptor. This is like f.NewMessage(md) except the known type registry is not
+// consulted so the return value is always a dynamic message.
+//
+// This is also like dynamic.NewMessage(md) except that the returned message will use
+// this factory when creating other messages, like during de-serialization of fields
+// that are themselves message types.
+func (f *MessageFactory) NewDynamicMessage(md *desc.MessageDescriptor) *Message {
+ return NewMessageWithMessageFactory(md, f)
+}
+
+// GetKnownTypeRegistry returns the known type registry that this factory uses to
+// instantiate known (e.g. generated) message types.
+func (f *MessageFactory) GetKnownTypeRegistry() *KnownTypeRegistry {
+ if f == nil {
+ return nil
+ }
+ return f.ktr
+}
+
+// GetExtensionRegistry returns the extension registry that this factory uses to
+// create dynamic messages. The registry is used by dynamic messages to recognize
+// and parse extension fields during de-serialization.
+func (f *MessageFactory) GetExtensionRegistry() *ExtensionRegistry {
+ if f == nil {
+ return nil
+ }
+ return f.er
+}
+
+type wkt interface {
+ XXX_WellKnownType() string
+}
+
+var typeOfWkt = reflect.TypeOf((*wkt)(nil)).Elem()
+
+// KnownTypeRegistry is a registry of known message types, as identified by their
+// fully-qualified name. A known message type is one for which a protoc-generated
+// struct exists, so a dynamic message is not necessary to represent it. A
+// MessageFactory uses a KnownTypeRegistry to decide whether to create a generated
+// struct or a dynamic message. The zero-value registry (including the behavior of
+// a nil pointer) only knows about the "well-known types" in protobuf. These
+// include only the wrapper types and a handful of other special types like Any,
+// Duration, and Timestamp.
+type KnownTypeRegistry struct {
+ excludeWkt bool
+ includeDefault bool
+ mu sync.RWMutex
+ types map[string]reflect.Type
+}
+
+// NewKnownTypeRegistryWithDefaults creates a new registry that knows about all
+// "default" types (those for which protoc-generated code is statically linked
+// into the Go program).
+func NewKnownTypeRegistryWithDefaults() *KnownTypeRegistry {
+ return &KnownTypeRegistry{includeDefault: true}
+}
+
+// NewKnownTypeRegistryWithoutWellKnownTypes creates a new registry that does *not*
+// include the "well-known types" in protobuf. So even well-known types would be
+// represented by a dynamic message.
+func NewKnownTypeRegistryWithoutWellKnownTypes() *KnownTypeRegistry {
+ return &KnownTypeRegistry{excludeWkt: true}
+}
+
+// AddKnownType adds the types of the given messages as known types.
+func (r *KnownTypeRegistry) AddKnownType(kts ...proto.Message) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if r.types == nil {
+ r.types = map[string]reflect.Type{}
+ }
+ for _, kt := range kts {
+ r.types[proto.MessageName(kt)] = reflect.TypeOf(kt)
+ }
+}
+
+// CreateIfKnown will construct an instance of the given message if it is a known type.
+// If the given name is unknown, nil is returned.
+func (r *KnownTypeRegistry) CreateIfKnown(messageName string) proto.Message {
+ msgType := r.GetKnownType(messageName)
+ if msgType == nil {
+ return nil
+ }
+
+ if msgType.Kind() == reflect.Ptr {
+ return reflect.New(msgType.Elem()).Interface().(proto.Message)
+ } else {
+ return reflect.New(msgType).Elem().Interface().(proto.Message)
+ }
+}
+
+// GetKnownType will return the reflect.Type for the given message name if it is
+// known. If it is not known, nil is returned.
+func (r *KnownTypeRegistry) GetKnownType(messageName string) reflect.Type {
+ var msgType reflect.Type
+ if r == nil {
+ // a nil registry behaves the same as zero value instance: only know of well-known types
+ t := proto.MessageType(messageName)
+ if t != nil && t.Implements(typeOfWkt) {
+ msgType = t
+ }
+ } else {
+ if r.includeDefault {
+ msgType = proto.MessageType(messageName)
+ } else if !r.excludeWkt {
+ t := proto.MessageType(messageName)
+ if t != nil && t.Implements(typeOfWkt) {
+ msgType = t
+ }
+ }
+ if msgType == nil {
+ r.mu.RLock()
+ msgType = r.types[messageName]
+ r.mu.RUnlock()
+ }
+ }
+
+ return msgType
+}
diff --git a/vendor/github.com/jhump/protoreflect/dynamic/text.go b/vendor/github.com/jhump/protoreflect/dynamic/text.go
new file mode 100644
index 0000000..72636f2
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/dynamic/text.go
@@ -0,0 +1,1175 @@
+package dynamic
+
+// Marshalling and unmarshalling of dynamic messages to/from proto's standard text format
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "text/scanner"
+ "unicode"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+ "github.com/jhump/protoreflect/codec"
+ "github.com/jhump/protoreflect/desc"
+)
+
+// MarshalText serializes this message to bytes in the standard text format,
+// returning an error if the operation fails. The resulting bytes will be a
+// valid UTF8 string.
+//
+// This method uses a compact form: no newlines, and spaces between field
+// identifiers and values are elided.
+func (m *Message) MarshalText() ([]byte, error) {
+ var b indentBuffer
+ b.indentCount = -1 // no indentation
+ if err := m.marshalText(&b); err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
+
+// MarshalTextIndent serializes this message to bytes in the standard text
+// format, returning an error if the operation fails. The resulting bytes will
+// be a valid UTF8 string.
+//
+// This method uses a "pretty-printed" form, with each field on its own line and
+// spaces between field identifiers and values.
+func (m *Message) MarshalTextIndent() ([]byte, error) {
+ var b indentBuffer
+ b.indent = " " // TODO: option for indent?
+ if err := m.marshalText(&b); err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
+
+func (m *Message) marshalText(b *indentBuffer) error {
+ // TODO: option for emitting extended Any format?
+ first := true
+ // first the known fields
+ for _, tag := range m.knownFieldTags() {
+ itag := int32(tag)
+ v := m.values[itag]
+ fd := m.FindFieldDescriptor(itag)
+ if fd.IsMap() {
+ md := fd.GetMessageType()
+ kfd := md.FindFieldByNumber(1)
+ vfd := md.FindFieldByNumber(2)
+ mp := v.(map[interface{}]interface{})
+ keys := make([]interface{}, 0, len(mp))
+ for k := range mp {
+ keys = append(keys, k)
+ }
+ sort.Sort(sortable(keys))
+ for _, mk := range keys {
+ mv := mp[mk]
+ err := b.maybeNext(&first)
+ if err != nil {
+ return err
+ }
+ err = marshalKnownFieldMapEntryText(b, fd, kfd, mk, vfd, mv)
+ if err != nil {
+ return err
+ }
+ }
+ } else if fd.IsRepeated() {
+ sl := v.([]interface{})
+ for _, slv := range sl {
+ err := b.maybeNext(&first)
+ if err != nil {
+ return err
+ }
+ err = marshalKnownFieldText(b, fd, slv)
+ if err != nil {
+ return err
+ }
+ }
+ } else {
+ err := b.maybeNext(&first)
+ if err != nil {
+ return err
+ }
+ err = marshalKnownFieldText(b, fd, v)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ // then the unknown fields
+ for _, tag := range m.unknownFieldTags() {
+ itag := int32(tag)
+ ufs := m.unknownFields[itag]
+ for _, uf := range ufs {
+ err := b.maybeNext(&first)
+ if err != nil {
+ return err
+ }
+ _, err = fmt.Fprintf(b, "%d", tag)
+ if err != nil {
+ return err
+ }
+ if uf.Encoding == proto.WireStartGroup {
+ err = b.WriteByte('{')
+ if err != nil {
+ return err
+ }
+ err = b.start()
+ if err != nil {
+ return err
+ }
+ in := codec.NewBuffer(uf.Contents)
+ err = marshalUnknownGroupText(b, in, true)
+ if err != nil {
+ return err
+ }
+ err = b.end()
+ if err != nil {
+ return err
+ }
+ err = b.WriteByte('}')
+ if err != nil {
+ return err
+ }
+ } else {
+ err = b.sep()
+ if err != nil {
+ return err
+ }
+ if uf.Encoding == proto.WireBytes {
+ err = writeString(b, string(uf.Contents))
+ if err != nil {
+ return err
+ }
+ } else {
+ _, err = b.WriteString(strconv.FormatUint(uf.Value, 10))
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func marshalKnownFieldMapEntryText(b *indentBuffer, fd *desc.FieldDescriptor, kfd *desc.FieldDescriptor, mk interface{}, vfd *desc.FieldDescriptor, mv interface{}) error {
+ var name string
+ if fd.IsExtension() {
+ name = fmt.Sprintf("[%s]", fd.GetFullyQualifiedName())
+ } else {
+ name = fd.GetName()
+ }
+ _, err := b.WriteString(name)
+ if err != nil {
+ return err
+ }
+ err = b.sep()
+ if err != nil {
+ return err
+ }
+
+ err = b.WriteByte('<')
+ if err != nil {
+ return err
+ }
+ err = b.start()
+ if err != nil {
+ return err
+ }
+
+ err = marshalKnownFieldText(b, kfd, mk)
+ if err != nil {
+ return err
+ }
+ err = b.next()
+ if err != nil {
+ return err
+ }
+ err = marshalKnownFieldText(b, vfd, mv)
+ if err != nil {
+ return err
+ }
+
+ err = b.end()
+ if err != nil {
+ return err
+ }
+ return b.WriteByte('>')
+}
+
+func marshalKnownFieldText(b *indentBuffer, fd *desc.FieldDescriptor, v interface{}) error {
+ group := fd.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP
+ if group {
+ var name string
+ if fd.IsExtension() {
+ name = fmt.Sprintf("[%s]", fd.GetMessageType().GetFullyQualifiedName())
+ } else {
+ name = fd.GetMessageType().GetName()
+ }
+ _, err := b.WriteString(name)
+ if err != nil {
+ return err
+ }
+ } else {
+ var name string
+ if fd.IsExtension() {
+ name = fmt.Sprintf("[%s]", fd.GetFullyQualifiedName())
+ } else {
+ name = fd.GetName()
+ }
+ _, err := b.WriteString(name)
+ if err != nil {
+ return err
+ }
+ err = b.sep()
+ if err != nil {
+ return err
+ }
+ }
+ rv := reflect.ValueOf(v)
+ switch rv.Kind() {
+ case reflect.Int32, reflect.Int64:
+ ed := fd.GetEnumType()
+ if ed != nil {
+ n := int32(rv.Int())
+ vd := ed.FindValueByNumber(n)
+ if vd == nil {
+ _, err := b.WriteString(strconv.FormatInt(rv.Int(), 10))
+ return err
+ } else {
+ _, err := b.WriteString(vd.GetName())
+ return err
+ }
+ } else {
+ _, err := b.WriteString(strconv.FormatInt(rv.Int(), 10))
+ return err
+ }
+ case reflect.Uint32, reflect.Uint64:
+ _, err := b.WriteString(strconv.FormatUint(rv.Uint(), 10))
+ return err
+ case reflect.Float32, reflect.Float64:
+ f := rv.Float()
+ var str string
+ if math.IsNaN(f) {
+ str = "nan"
+ } else if math.IsInf(f, 1) {
+ str = "inf"
+ } else if math.IsInf(f, -1) {
+ str = "-inf"
+ } else {
+ var bits int
+ if rv.Kind() == reflect.Float32 {
+ bits = 32
+ } else {
+ bits = 64
+ }
+ str = strconv.FormatFloat(rv.Float(), 'g', -1, bits)
+ }
+ _, err := b.WriteString(str)
+ return err
+ case reflect.Bool:
+ _, err := b.WriteString(strconv.FormatBool(rv.Bool()))
+ return err
+ case reflect.Slice:
+ return writeString(b, string(rv.Bytes()))
+ case reflect.String:
+ return writeString(b, rv.String())
+ default:
+ var err error
+ if group {
+ err = b.WriteByte('{')
+ } else {
+ err = b.WriteByte('<')
+ }
+ if err != nil {
+ return err
+ }
+ err = b.start()
+ if err != nil {
+ return err
+ }
+ // must be a message
+ if dm, ok := v.(*Message); ok {
+ err = dm.marshalText(b)
+ if err != nil {
+ return err
+ }
+ } else {
+ err = proto.CompactText(b, v.(proto.Message))
+ if err != nil {
+ return err
+ }
+ }
+ err = b.end()
+ if err != nil {
+ return err
+ }
+ if group {
+ return b.WriteByte('}')
+ } else {
+ return b.WriteByte('>')
+ }
+ }
+}
+
+// writeString writes a string in the protocol buffer text format.
+// It is similar to strconv.Quote except we don't use Go escape sequences,
+// we treat the string as a byte sequence, and we use octal escapes.
+// These differences are to maintain interoperability with the other
+// languages' implementations of the text format.
+func writeString(b *indentBuffer, s string) error {
+ // use WriteByte here to get any needed indent
+ if err := b.WriteByte('"'); err != nil {
+ return err
+ }
+ // Loop over the bytes, not the runes.
+ for i := 0; i < len(s); i++ {
+ var err error
+ // Divergence from C++: we don't escape apostrophes.
+ // There's no need to escape them, and the C++ parser
+ // copes with a naked apostrophe.
+ switch c := s[i]; c {
+ case '\n':
+ _, err = b.WriteString("\\n")
+ case '\r':
+ _, err = b.WriteString("\\r")
+ case '\t':
+ _, err = b.WriteString("\\t")
+ case '"':
+ _, err = b.WriteString("\\")
+ case '\\':
+ _, err = b.WriteString("\\\\")
+ default:
+ if c >= 0x20 && c < 0x7f {
+ err = b.WriteByte(c)
+ } else {
+ _, err = fmt.Fprintf(b, "\\%03o", c)
+ }
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return b.WriteByte('"')
+}
+
+func marshalUnknownGroupText(b *indentBuffer, in *codec.Buffer, topLevel bool) error {
+ first := true
+ for {
+ if in.EOF() {
+ if topLevel {
+ return nil
+ }
+ // this is a nested message: we are expecting an end-group tag, not EOF!
+ return io.ErrUnexpectedEOF
+ }
+ tag, wireType, err := in.DecodeTagAndWireType()
+ if err != nil {
+ return err
+ }
+ if wireType == proto.WireEndGroup {
+ return nil
+ }
+ err = b.maybeNext(&first)
+ if err != nil {
+ return err
+ }
+ _, err = fmt.Fprintf(b, "%d", tag)
+ if err != nil {
+ return err
+ }
+ if wireType == proto.WireStartGroup {
+ err = b.WriteByte('{')
+ if err != nil {
+ return err
+ }
+ err = b.start()
+ if err != nil {
+ return err
+ }
+ err = marshalUnknownGroupText(b, in, false)
+ if err != nil {
+ return err
+ }
+ err = b.end()
+ if err != nil {
+ return err
+ }
+ err = b.WriteByte('}')
+ if err != nil {
+ return err
+ }
+ continue
+ } else {
+ err = b.sep()
+ if err != nil {
+ return err
+ }
+ if wireType == proto.WireBytes {
+ contents, err := in.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+ err = writeString(b, string(contents))
+ if err != nil {
+ return err
+ }
+ } else {
+ var v uint64
+ switch wireType {
+ case proto.WireVarint:
+ v, err = in.DecodeVarint()
+ case proto.WireFixed32:
+ v, err = in.DecodeFixed32()
+ case proto.WireFixed64:
+ v, err = in.DecodeFixed64()
+ default:
+ return proto.ErrInternalBadWireType
+ }
+ if err != nil {
+ return err
+ }
+ _, err = b.WriteString(strconv.FormatUint(v, 10))
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+}
+
+// UnmarshalText de-serializes the message that is present, in text format, in
+// the given bytes into this message. It first resets the current message. It
+// returns an error if the given bytes do not contain a valid encoding of this
+// message type in the standard text format
+func (m *Message) UnmarshalText(text []byte) error {
+ m.Reset()
+ if err := m.UnmarshalMergeText(text); err != nil {
+ return err
+ }
+ return m.Validate()
+}
+
+// UnmarshalMergeText de-serializes the message that is present, in text format,
+// in the given bytes into this message. Unlike UnmarshalText, it does not first
+// reset the message, instead merging the data in the given bytes into the
+// existing data in this message.
+func (m *Message) UnmarshalMergeText(text []byte) error {
+ return m.unmarshalText(newReader(text), tokenEOF)
+}
+
+func (m *Message) unmarshalText(tr *txtReader, end tokenType) error {
+ for {
+ tok := tr.next()
+ if tok.tokTyp == end {
+ return nil
+ }
+ if tok.tokTyp == tokenEOF {
+ return io.ErrUnexpectedEOF
+ }
+ var fd *desc.FieldDescriptor
+ var extendedAnyType *desc.MessageDescriptor
+ if tok.tokTyp == tokenInt {
+ // tag number (indicates unknown field)
+ tag, err := strconv.ParseInt(tok.val.(string), 10, 32)
+ if err != nil {
+ return err
+ }
+ itag := int32(tag)
+ fd = m.FindFieldDescriptor(itag)
+ if fd == nil {
+ // can't parse the value w/out field descriptor, so skip it
+ tok = tr.next()
+ if tok.tokTyp == tokenEOF {
+ return io.ErrUnexpectedEOF
+ } else if tok.tokTyp == tokenOpenBrace {
+ if err := skipMessageText(tr, true); err != nil {
+ return err
+ }
+ } else if tok.tokTyp == tokenColon {
+ if err := skipFieldValueText(tr); err != nil {
+ return err
+ }
+ } else {
+ return textError(tok, "Expecting a colon ':' or brace '{'; instead got %q", tok.txt)
+ }
+ tok = tr.peek()
+ if tok.tokTyp.IsSep() {
+ tr.next() // consume separator
+ }
+ continue
+ }
+ } else {
+ fieldName, err := unmarshalFieldNameText(tr, tok)
+ if err != nil {
+ return err
+ }
+ fd = m.FindFieldDescriptorByName(fieldName)
+ if fd == nil {
+ // See if it's a group name
+ for _, field := range m.md.GetFields() {
+ if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetMessageType().GetName() == fieldName {
+ fd = field
+ break
+ }
+ }
+ if fd == nil {
+ // maybe this is an extended Any
+ if m.md.GetFullyQualifiedName() == "google.protobuf.Any" && fieldName[0] == '[' && strings.Contains(fieldName, "/") {
+ // strip surrounding "[" and "]" and extract type name from URL
+ typeUrl := fieldName[1 : len(fieldName)-1]
+ mname := typeUrl
+ if slash := strings.LastIndex(mname, "/"); slash >= 0 {
+ mname = mname[slash+1:]
+ }
+ // TODO: add a way to weave an AnyResolver to this point
+ extendedAnyType = findMessageDescriptor(mname, m.md.GetFile())
+ if extendedAnyType == nil {
+ return textError(tok, "could not parse Any with unknown type URL %q", fieldName)
+ }
+ // field 1 is "type_url"
+ typeUrlField := m.md.FindFieldByNumber(1)
+ if err := m.TrySetField(typeUrlField, typeUrl); err != nil {
+ return err
+ }
+ } else {
+ // TODO: add a flag to just ignore unrecognized field names
+ return textError(tok, "%q is not a recognized field name of %q", fieldName, m.md.GetFullyQualifiedName())
+ }
+ }
+ }
+ }
+ tok = tr.next()
+ if tok.tokTyp == tokenEOF {
+ return io.ErrUnexpectedEOF
+ }
+ if extendedAnyType != nil {
+ // consume optional colon; make sure this is a "start message" token
+ if tok.tokTyp == tokenColon {
+ tok = tr.next()
+ if tok.tokTyp == tokenEOF {
+ return io.ErrUnexpectedEOF
+ }
+ }
+ if tok.tokTyp.EndToken() == tokenError {
+ return textError(tok, "Expecting a '<' or '{'; instead got %q", tok.txt)
+ }
+
+ // TODO: use mf.NewMessage and, if not a dynamic message, use proto.UnmarshalText to unmarshal it
+ g := m.mf.NewDynamicMessage(extendedAnyType)
+ if err := g.unmarshalText(tr, tok.tokTyp.EndToken()); err != nil {
+ return err
+ }
+ // now we marshal the message to bytes and store in the Any
+ b, err := g.Marshal()
+ if err != nil {
+ return err
+ }
+ // field 2 is "value"
+ anyValueField := m.md.FindFieldByNumber(2)
+ if err := m.TrySetField(anyValueField, b); err != nil {
+ return err
+ }
+
+ } else if (fd.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP ||
+ fd.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
+ tok.tokTyp.EndToken() != tokenError {
+
+ // TODO: use mf.NewMessage and, if not a dynamic message, use proto.UnmarshalText to unmarshal it
+ g := m.mf.NewDynamicMessage(fd.GetMessageType())
+ if err := g.unmarshalText(tr, tok.tokTyp.EndToken()); err != nil {
+ return err
+ }
+ if fd.IsRepeated() {
+ if err := m.TryAddRepeatedField(fd, g); err != nil {
+ return err
+ }
+ } else {
+ if err := m.TrySetField(fd, g); err != nil {
+ return err
+ }
+ }
+ } else {
+ if tok.tokTyp != tokenColon {
+ return textError(tok, "Expecting a colon ':'; instead got %q", tok.txt)
+ }
+ if err := m.unmarshalFieldValueText(fd, tr); err != nil {
+ return err
+ }
+ }
+ tok = tr.peek()
+ if tok.tokTyp.IsSep() {
+ tr.next() // consume separator
+ }
+ }
+}
+func findMessageDescriptor(name string, fd *desc.FileDescriptor) *desc.MessageDescriptor {
+ md := findMessageInTransitiveDeps(name, fd, map[*desc.FileDescriptor]struct{}{})
+ if md == nil {
+ // couldn't find it; see if we have this message linked in
+ md, _ = desc.LoadMessageDescriptor(name)
+ }
+ return md
+}
+
+func findMessageInTransitiveDeps(name string, fd *desc.FileDescriptor, seen map[*desc.FileDescriptor]struct{}) *desc.MessageDescriptor {
+ if _, ok := seen[fd]; ok {
+ // already checked this file
+ return nil
+ }
+ seen[fd] = struct{}{}
+ md := fd.FindMessage(name)
+ if md != nil {
+ return md
+ }
+ // not in this file so recursively search its deps
+ for _, dep := range fd.GetDependencies() {
+ md = findMessageInTransitiveDeps(name, dep, seen)
+ if md != nil {
+ return md
+ }
+ }
+ // couldn't find it
+ return nil
+}
+
+func textError(tok *token, format string, args ...interface{}) error {
+ var msg string
+ if tok.tokTyp == tokenError {
+ msg = tok.val.(error).Error()
+ } else {
+ msg = fmt.Sprintf(format, args...)
+ }
+ return fmt.Errorf("line %d, col %d: %s", tok.pos.Line, tok.pos.Column, msg)
+}
+
+type setFunction func(*Message, *desc.FieldDescriptor, interface{}) error
+
+func (m *Message) unmarshalFieldValueText(fd *desc.FieldDescriptor, tr *txtReader) error {
+ var set setFunction
+ if fd.IsRepeated() {
+ set = (*Message).addRepeatedField
+ } else {
+ set = mergeField
+ }
+ tok := tr.peek()
+ if tok.tokTyp == tokenOpenBracket {
+ tr.next() // consume tok
+ for {
+ if err := m.unmarshalFieldElementText(fd, tr, set); err != nil {
+ return err
+ }
+ tok = tr.peek()
+ if tok.tokTyp == tokenCloseBracket {
+ tr.next() // consume tok
+ return nil
+ } else if tok.tokTyp.IsSep() {
+ tr.next() // consume separator
+ }
+ }
+ }
+ return m.unmarshalFieldElementText(fd, tr, set)
+}
+
+func (m *Message) unmarshalFieldElementText(fd *desc.FieldDescriptor, tr *txtReader, set setFunction) error {
+ tok := tr.next()
+ if tok.tokTyp == tokenEOF {
+ return io.ErrUnexpectedEOF
+ }
+
+ var expected string
+ switch fd.GetType() {
+ case descriptor.FieldDescriptorProto_TYPE_BOOL:
+ if tok.tokTyp == tokenIdent {
+ if tok.val.(string) == "true" {
+ return set(m, fd, true)
+ } else if tok.val.(string) == "false" {
+ return set(m, fd, false)
+ }
+ }
+ expected = "boolean value"
+ case descriptor.FieldDescriptorProto_TYPE_BYTES:
+ if tok.tokTyp == tokenString {
+ return set(m, fd, []byte(tok.val.(string)))
+ }
+ expected = "bytes string value"
+ case descriptor.FieldDescriptorProto_TYPE_STRING:
+ if tok.tokTyp == tokenString {
+ return set(m, fd, tok.val)
+ }
+ expected = "string value"
+ case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+ switch tok.tokTyp {
+ case tokenFloat:
+ return set(m, fd, float32(tok.val.(float64)))
+ case tokenInt:
+ if f, err := strconv.ParseFloat(tok.val.(string), 32); err != nil {
+ return err
+ } else {
+ return set(m, fd, float32(f))
+ }
+ case tokenIdent:
+ ident := strings.ToLower(tok.val.(string))
+ if ident == "inf" {
+ return set(m, fd, float32(math.Inf(1)))
+ } else if ident == "nan" {
+ return set(m, fd, float32(math.NaN()))
+ }
+ case tokenMinus:
+ peeked := tr.peek()
+ if peeked.tokTyp == tokenIdent {
+ ident := strings.ToLower(peeked.val.(string))
+ if ident == "inf" {
+ tr.next() // consume peeked token
+ return set(m, fd, float32(math.Inf(-1)))
+ }
+ }
+ }
+ expected = "float value"
+ case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+ switch tok.tokTyp {
+ case tokenFloat:
+ return set(m, fd, tok.val)
+ case tokenInt:
+ if f, err := strconv.ParseFloat(tok.val.(string), 64); err != nil {
+ return err
+ } else {
+ return set(m, fd, f)
+ }
+ case tokenIdent:
+ ident := strings.ToLower(tok.val.(string))
+ if ident == "inf" {
+ return set(m, fd, math.Inf(1))
+ } else if ident == "nan" {
+ return set(m, fd, math.NaN())
+ }
+ case tokenMinus:
+ peeked := tr.peek()
+ if peeked.tokTyp == tokenIdent {
+ ident := strings.ToLower(peeked.val.(string))
+ if ident == "inf" {
+ tr.next() // consume peeked token
+ return set(m, fd, math.Inf(-1))
+ }
+ }
+ }
+ expected = "float value"
+ case descriptor.FieldDescriptorProto_TYPE_INT32,
+ descriptor.FieldDescriptorProto_TYPE_SINT32,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+ if tok.tokTyp == tokenInt {
+ if i, err := strconv.ParseInt(tok.val.(string), 10, 32); err != nil {
+ return err
+ } else {
+ return set(m, fd, int32(i))
+ }
+ }
+ expected = "int value"
+ case descriptor.FieldDescriptorProto_TYPE_INT64,
+ descriptor.FieldDescriptorProto_TYPE_SINT64,
+ descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+ if tok.tokTyp == tokenInt {
+ if i, err := strconv.ParseInt(tok.val.(string), 10, 64); err != nil {
+ return err
+ } else {
+ return set(m, fd, i)
+ }
+ }
+ expected = "int value"
+ case descriptor.FieldDescriptorProto_TYPE_UINT32,
+ descriptor.FieldDescriptorProto_TYPE_FIXED32:
+ if tok.tokTyp == tokenInt {
+ if i, err := strconv.ParseUint(tok.val.(string), 10, 32); err != nil {
+ return err
+ } else {
+ return set(m, fd, uint32(i))
+ }
+ }
+ expected = "unsigned int value"
+ case descriptor.FieldDescriptorProto_TYPE_UINT64,
+ descriptor.FieldDescriptorProto_TYPE_FIXED64:
+ if tok.tokTyp == tokenInt {
+ if i, err := strconv.ParseUint(tok.val.(string), 10, 64); err != nil {
+ return err
+ } else {
+ return set(m, fd, i)
+ }
+ }
+ expected = "unsigned int value"
+ case descriptor.FieldDescriptorProto_TYPE_ENUM:
+ if tok.tokTyp == tokenIdent {
+ // TODO: add a flag to just ignore unrecognized enum value names?
+ vd := fd.GetEnumType().FindValueByName(tok.val.(string))
+ if vd != nil {
+ return set(m, fd, vd.GetNumber())
+ }
+ } else if tok.tokTyp == tokenInt {
+ if i, err := strconv.ParseInt(tok.val.(string), 10, 32); err != nil {
+ return err
+ } else {
+ return set(m, fd, int32(i))
+ }
+ }
+ expected = fmt.Sprintf("enum %s value", fd.GetEnumType().GetFullyQualifiedName())
+ case descriptor.FieldDescriptorProto_TYPE_MESSAGE,
+ descriptor.FieldDescriptorProto_TYPE_GROUP:
+
+ endTok := tok.tokTyp.EndToken()
+ if endTok != tokenError {
+ dm := m.mf.NewDynamicMessage(fd.GetMessageType())
+ if err := dm.unmarshalText(tr, endTok); err != nil {
+ return err
+ }
+ // TODO: ideally we would use mf.NewMessage and, if not a dynamic message, use
+ // proto package to unmarshal it. But the text parser isn't particularly amenable
+ // to that, so we instead convert a dynamic message to a generated one if the
+ // known-type registry knows about the generated type...
+ var ktr *KnownTypeRegistry
+ if m.mf != nil {
+ ktr = m.mf.ktr
+ }
+ pm := ktr.CreateIfKnown(fd.GetMessageType().GetFullyQualifiedName())
+ if pm != nil {
+ if err := dm.ConvertTo(pm); err != nil {
+ return set(m, fd, pm)
+ }
+ }
+ return set(m, fd, dm)
+ }
+ expected = fmt.Sprintf("message %s value", fd.GetMessageType().GetFullyQualifiedName())
+ default:
+ return fmt.Errorf("field %q of message %q has unrecognized type: %v", fd.GetFullyQualifiedName(), m.md.GetFullyQualifiedName(), fd.GetType())
+ }
+
+ // if we get here, token was wrong type; create error message
+ var article string
+ if strings.Contains("aieou", expected[0:1]) {
+ article = "an"
+ } else {
+ article = "a"
+ }
+ return textError(tok, "Expecting %s %s; got %q", article, expected, tok.txt)
+}
+
+func unmarshalFieldNameText(tr *txtReader, tok *token) (string, error) {
+ if tok.tokTyp == tokenOpenBracket || tok.tokTyp == tokenOpenParen {
+ // extension name
+ var closeType tokenType
+ var closeChar string
+ if tok.tokTyp == tokenOpenBracket {
+ closeType = tokenCloseBracket
+ closeChar = "close bracket ']'"
+ } else {
+ closeType = tokenCloseParen
+ closeChar = "close paren ')'"
+ }
+ // must be followed by an identifier
+ idents := make([]string, 0, 1)
+ for {
+ tok = tr.next()
+ if tok.tokTyp == tokenEOF {
+ return "", io.ErrUnexpectedEOF
+ } else if tok.tokTyp != tokenIdent {
+ return "", textError(tok, "Expecting an identifier; instead got %q", tok.txt)
+ }
+ idents = append(idents, tok.val.(string))
+ // and then close bracket/paren, or "/" to keep adding URL elements to name
+ tok = tr.next()
+ if tok.tokTyp == tokenEOF {
+ return "", io.ErrUnexpectedEOF
+ } else if tok.tokTyp == closeType {
+ break
+ } else if tok.tokTyp != tokenSlash {
+ return "", textError(tok, "Expecting a %s; instead got %q", closeChar, tok.txt)
+ }
+ }
+ return "[" + strings.Join(idents, "/") + "]", nil
+ } else if tok.tokTyp == tokenIdent {
+ // normal field name
+ return tok.val.(string), nil
+ } else {
+ return "", textError(tok, "Expecting an identifier or tag number; instead got %q", tok.txt)
+ }
+}
+
+func skipFieldNameText(tr *txtReader) error {
+ tok := tr.next()
+ if tok.tokTyp == tokenEOF {
+ return io.ErrUnexpectedEOF
+ } else if tok.tokTyp == tokenInt || tok.tokTyp == tokenIdent {
+ return nil
+ } else {
+ _, err := unmarshalFieldNameText(tr, tok)
+ return err
+ }
+}
+
+func skipFieldValueText(tr *txtReader) error {
+ tok := tr.peek()
+ if tok.tokTyp == tokenOpenBracket {
+ tr.next() // consume tok
+ for {
+ if err := skipFieldElementText(tr); err != nil {
+ return err
+ }
+ tok = tr.peek()
+ if tok.tokTyp == tokenCloseBracket {
+ tr.next() // consume tok
+ return nil
+ } else if tok.tokTyp.IsSep() {
+ tr.next() // consume separator
+ }
+
+ }
+ }
+ return skipFieldElementText(tr)
+}
+
+func skipFieldElementText(tr *txtReader) error {
+ tok := tr.next()
+ switch tok.tokTyp {
+ case tokenEOF:
+ return io.ErrUnexpectedEOF
+ case tokenInt, tokenFloat, tokenString, tokenIdent:
+ return nil
+ case tokenOpenAngle:
+ return skipMessageText(tr, false)
+ default:
+ return textError(tok, "Expecting an angle bracket '<' or a value; instead got %q", tok.txt)
+ }
+}
+
+func skipMessageText(tr *txtReader, isGroup bool) error {
+ for {
+ tok := tr.peek()
+ if tok.tokTyp == tokenEOF {
+ return io.ErrUnexpectedEOF
+ } else if isGroup && tok.tokTyp == tokenCloseBrace {
+ return nil
+ } else if !isGroup && tok.tokTyp == tokenCloseAngle {
+ return nil
+ }
+
+ // field name or tag
+ if err := skipFieldNameText(tr); err != nil {
+ return err
+ }
+
+ // field value
+ tok = tr.next()
+ if tok.tokTyp == tokenEOF {
+ return io.ErrUnexpectedEOF
+ } else if tok.tokTyp == tokenOpenBrace {
+ if err := skipMessageText(tr, true); err != nil {
+ return err
+ }
+ } else if tok.tokTyp == tokenColon {
+ if err := skipFieldValueText(tr); err != nil {
+ return err
+ }
+ } else {
+ return textError(tok, "Expecting a colon ':' or brace '{'; instead got %q", tok.txt)
+ }
+
+ tok = tr.peek()
+ if tok.tokTyp.IsSep() {
+ tr.next() // consume separator
+ }
+ }
+}
+
+type tokenType int
+
+const (
+ tokenError tokenType = iota
+ tokenEOF
+ tokenIdent
+ tokenString
+ tokenInt
+ tokenFloat
+ tokenColon
+ tokenComma
+ tokenSemiColon
+ tokenOpenBrace
+ tokenCloseBrace
+ tokenOpenBracket
+ tokenCloseBracket
+ tokenOpenAngle
+ tokenCloseAngle
+ tokenOpenParen
+ tokenCloseParen
+ tokenSlash
+ tokenMinus
+)
+
+func (t tokenType) IsSep() bool {
+ return t == tokenComma || t == tokenSemiColon
+}
+
+func (t tokenType) EndToken() tokenType {
+ switch t {
+ case tokenOpenAngle:
+ return tokenCloseAngle
+ case tokenOpenBrace:
+ return tokenCloseBrace
+ default:
+ return tokenError
+ }
+}
+
+type token struct {
+ tokTyp tokenType
+ val interface{}
+ txt string
+ pos scanner.Position
+}
+
+type txtReader struct {
+ scanner scanner.Scanner
+ peeked token
+ havePeeked bool
+}
+
+func newReader(text []byte) *txtReader {
+ sc := scanner.Scanner{}
+ sc.Init(bytes.NewReader(text))
+ sc.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanChars |
+ scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+ // identifiers are same restrictions as Go identifiers, except we also allow dots since
+ // we accept fully-qualified names
+ sc.IsIdentRune = func(ch rune, i int) bool {
+ return ch == '_' || unicode.IsLetter(ch) ||
+ (i > 0 && unicode.IsDigit(ch)) ||
+ (i > 0 && ch == '.')
+ }
+ // ignore errors; we handle them if/when we see malformed tokens
+ sc.Error = func(s *scanner.Scanner, msg string) {}
+ return &txtReader{scanner: sc}
+}
+
+func (p *txtReader) peek() *token {
+ if p.havePeeked {
+ return &p.peeked
+ }
+ t := p.scanner.Scan()
+ if t == scanner.EOF {
+ p.peeked.tokTyp = tokenEOF
+ p.peeked.val = nil
+ p.peeked.txt = ""
+ p.peeked.pos = p.scanner.Position
+ } else if err := p.processToken(t, p.scanner.TokenText(), p.scanner.Position); err != nil {
+ p.peeked.tokTyp = tokenError
+ p.peeked.val = err
+ }
+ p.havePeeked = true
+ return &p.peeked
+}
+
+func (p *txtReader) processToken(t rune, text string, pos scanner.Position) error {
+ p.peeked.pos = pos
+ p.peeked.txt = text
+ switch t {
+ case scanner.Ident:
+ p.peeked.tokTyp = tokenIdent
+ p.peeked.val = text
+ case scanner.Int:
+ p.peeked.tokTyp = tokenInt
+ p.peeked.val = text // can't parse the number because we don't know if it's signed or unsigned
+ case scanner.Float:
+ p.peeked.tokTyp = tokenFloat
+ var err error
+ if p.peeked.val, err = strconv.ParseFloat(text, 64); err != nil {
+ return err
+ }
+ case scanner.Char, scanner.String:
+ p.peeked.tokTyp = tokenString
+ var err error
+ if p.peeked.val, err = strconv.Unquote(text); err != nil {
+ return err
+ }
+ case '-': // unary minus, for negative ints and floats
+ ch := p.scanner.Peek()
+ if ch < '0' || ch > '9' {
+ p.peeked.tokTyp = tokenMinus
+ p.peeked.val = '-'
+ } else {
+ t := p.scanner.Scan()
+ if t == scanner.EOF {
+ return io.ErrUnexpectedEOF
+ } else if t == scanner.Float {
+ p.peeked.tokTyp = tokenFloat
+ text += p.scanner.TokenText()
+ p.peeked.txt = text
+ var err error
+ if p.peeked.val, err = strconv.ParseFloat(text, 64); err != nil {
+ p.peeked.pos = p.scanner.Position
+ return err
+ }
+ } else if t == scanner.Int {
+ p.peeked.tokTyp = tokenInt
+ text += p.scanner.TokenText()
+ p.peeked.txt = text
+ p.peeked.val = text // can't parse the number because we don't know if it's signed or unsigned
+ } else {
+ p.peeked.pos = p.scanner.Position
+ return fmt.Errorf("expecting an int or float but got %q", p.scanner.TokenText())
+ }
+ }
+ case ':':
+ p.peeked.tokTyp = tokenColon
+ p.peeked.val = ':'
+ case ',':
+ p.peeked.tokTyp = tokenComma
+ p.peeked.val = ','
+ case ';':
+ p.peeked.tokTyp = tokenSemiColon
+ p.peeked.val = ';'
+ case '{':
+ p.peeked.tokTyp = tokenOpenBrace
+ p.peeked.val = '{'
+ case '}':
+ p.peeked.tokTyp = tokenCloseBrace
+ p.peeked.val = '}'
+ case '<':
+ p.peeked.tokTyp = tokenOpenAngle
+ p.peeked.val = '<'
+ case '>':
+ p.peeked.tokTyp = tokenCloseAngle
+ p.peeked.val = '>'
+ case '[':
+ p.peeked.tokTyp = tokenOpenBracket
+ p.peeked.val = '['
+ case ']':
+ p.peeked.tokTyp = tokenCloseBracket
+ p.peeked.val = ']'
+ case '(':
+ p.peeked.tokTyp = tokenOpenParen
+ p.peeked.val = '('
+ case ')':
+ p.peeked.tokTyp = tokenCloseParen
+ p.peeked.val = ')'
+ case '/':
+ // only allowed to separate URL components in expanded Any format
+ p.peeked.tokTyp = tokenSlash
+ p.peeked.val = '/'
+ default:
+ return fmt.Errorf("invalid character: %c", t)
+ }
+ return nil
+}
+
+func (p *txtReader) next() *token {
+ t := p.peek()
+ if t.tokTyp != tokenEOF && t.tokTyp != tokenError {
+ p.havePeeked = false
+ }
+ return t
+}
diff --git a/vendor/github.com/jhump/protoreflect/internal/standard_files.go b/vendor/github.com/jhump/protoreflect/internal/standard_files.go
new file mode 100644
index 0000000..4a8b47a
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/internal/standard_files.go
@@ -0,0 +1,127 @@
+// Package internal contains some code that should not be exported but needs to
+// be shared across more than one of the protoreflect sub-packages.
+package internal
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io/ioutil"
+
+ "github.com/golang/protobuf/proto"
+ dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+)
+
+// TODO: replace this alias configuration with desc.RegisterImportPath?
+
+// StdFileAliases are the standard protos included with protoc, but older versions of
+// their respective packages registered them using incorrect paths.
+var StdFileAliases = map[string]string{
+ // Files for the github.com/golang/protobuf/ptypes package at one point were
+ // registered using the path where the proto files are mirrored in GOPATH,
+ // inside the golang/protobuf repo.
+ // (Fixed as of https://github.com/golang/protobuf/pull/412)
+ "google/protobuf/any.proto": "github.com/golang/protobuf/ptypes/any/any.proto",
+ "google/protobuf/duration.proto": "github.com/golang/protobuf/ptypes/duration/duration.proto",
+ "google/protobuf/empty.proto": "github.com/golang/protobuf/ptypes/empty/empty.proto",
+ "google/protobuf/struct.proto": "github.com/golang/protobuf/ptypes/struct/struct.proto",
+ "google/protobuf/timestamp.proto": "github.com/golang/protobuf/ptypes/timestamp/timestamp.proto",
+ "google/protobuf/wrappers.proto": "github.com/golang/protobuf/ptypes/wrappers/wrappers.proto",
+ // Files for the google.golang.org/genproto/protobuf package at one point
+ // were registered with an anomalous "src/" prefix.
+ // (Fixed as of https://github.com/google/go-genproto/pull/31)
+ "google/protobuf/api.proto": "src/google/protobuf/api.proto",
+ "google/protobuf/field_mask.proto": "src/google/protobuf/field_mask.proto",
+ "google/protobuf/source_context.proto": "src/google/protobuf/source_context.proto",
+ "google/protobuf/type.proto": "src/google/protobuf/type.proto",
+
+ // Other standard files (descriptor.proto and compiler/plugin.proto) are
+ // registered correctly, so we don't need rules for them here.
+}
+
+func init() {
+ // We provide aliasing in both directions, to support files with the
+ // proper import path linked against older versions of the generated
+ // files AND files that used the aliased import path but linked against
+ // newer versions of the generated files (which register with the
+ // correct path).
+
+ // Get all files defined above
+ keys := make([]string, 0, len(StdFileAliases))
+ for k := range StdFileAliases {
+ keys = append(keys, k)
+ }
+ // And add inverse mappings
+ for _, k := range keys {
+ alias := StdFileAliases[k]
+ StdFileAliases[alias] = k
+ }
+}
+
+type ErrNoSuchFile string
+
+func (e ErrNoSuchFile) Error() string {
+ return fmt.Sprintf("no such file: %q", string(e))
+}
+
+// LoadFileDescriptor loads a registered descriptor and decodes it. If the given
+// name cannot be loaded but is a known standard name, an alias will be tried,
+// so the standard files can be loaded even if linked against older "known bad"
+// versions of packages.
+func LoadFileDescriptor(file string) (*dpb.FileDescriptorProto, error) {
+ fdb := proto.FileDescriptor(file)
+ aliased := false
+ if fdb == nil {
+ var ok bool
+ alias, ok := StdFileAliases[file]
+ if ok {
+ aliased = true
+ if fdb = proto.FileDescriptor(alias); fdb == nil {
+ return nil, ErrNoSuchFile(file)
+ }
+ } else {
+ return nil, ErrNoSuchFile(file)
+ }
+ }
+
+ fd, err := DecodeFileDescriptor(file, fdb)
+ if err != nil {
+ return nil, err
+ }
+
+ if aliased {
+ // the file descriptor will have the alias used to load it, but
+ // we need it to have the specified name in order to link it
+ fd.Name = proto.String(file)
+ }
+
+ return fd, nil
+}
+
+// DecodeFileDescriptor decodes the bytes of a registered file descriptor.
+// Registered file descriptors are first "proto encoded" (e.g. binary format
+// for the descriptor protos) and then gzipped. So this function gunzips and
+// then unmarshals into a descriptor proto.
+func DecodeFileDescriptor(element string, fdb []byte) (*dpb.FileDescriptorProto, error) {
+ raw, err := decompress(fdb)
+ if err != nil {
+ return nil, fmt.Errorf("failed to decompress %q descriptor: %v", element, err)
+ }
+ fd := dpb.FileDescriptorProto{}
+ if err := proto.Unmarshal(raw, &fd); err != nil {
+ return nil, fmt.Errorf("bad descriptor for %q: %v", element, err)
+ }
+ return &fd, nil
+}
+
+func decompress(b []byte) ([]byte, error) {
+ r, err := gzip.NewReader(bytes.NewReader(b))
+ if err != nil {
+ return nil, fmt.Errorf("bad gzipped descriptor: %v", err)
+ }
+ out, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, fmt.Errorf("bad gzipped descriptor: %v", err)
+ }
+ return out, nil
+}