diff --git a/vendor/github.com/golang/protobuf/proto/text_encode.go b/vendor/github.com/golang/protobuf/proto/text_encode.go
new file mode 100644
index 0000000..a31134e
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/text_encode.go
@@ -0,0 +1,560 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package proto
+
+import (
+	"bytes"
+	"encoding"
+	"fmt"
+	"io"
+	"math"
+	"sort"
+	"strings"
+
+	"google.golang.org/protobuf/encoding/prototext"
+	"google.golang.org/protobuf/encoding/protowire"
+	"google.golang.org/protobuf/proto"
+	"google.golang.org/protobuf/reflect/protoreflect"
+	"google.golang.org/protobuf/reflect/protoregistry"
+)
+
+const wrapTextMarshalV2 = false
+
+// TextMarshaler is a configurable text format marshaler.
+type TextMarshaler struct {
+	Compact   bool // use compact text format (one line)
+	ExpandAny bool // expand google.protobuf.Any messages of known types
+}
+
+// Marshal writes the proto text format of m to w.
+func (tm *TextMarshaler) Marshal(w io.Writer, m Message) error {
+	b, err := tm.marshal(m)
+	if len(b) > 0 {
+		if _, err := w.Write(b); err != nil {
+			return err
+		}
+	}
+	return err
+}
+
+// Text returns a proto text formatted string of m.
+func (tm *TextMarshaler) Text(m Message) string {
+	b, _ := tm.marshal(m)
+	return string(b)
+}
+
+func (tm *TextMarshaler) marshal(m Message) ([]byte, error) {
+	mr := MessageReflect(m)
+	if mr == nil || !mr.IsValid() {
+		return []byte("<nil>"), nil
+	}
+
+	if wrapTextMarshalV2 {
+		if m, ok := m.(encoding.TextMarshaler); ok {
+			return m.MarshalText()
+		}
+
+		opts := prototext.MarshalOptions{
+			AllowPartial: true,
+			EmitUnknown:  true,
+		}
+		if !tm.Compact {
+			opts.Indent = "  "
+		}
+		if !tm.ExpandAny {
+			opts.Resolver = (*protoregistry.Types)(nil)
+		}
+		return opts.Marshal(mr.Interface())
+	} else {
+		w := &textWriter{
+			compact:   tm.Compact,
+			expandAny: tm.ExpandAny,
+			complete:  true,
+		}
+
+		if m, ok := m.(encoding.TextMarshaler); ok {
+			b, err := m.MarshalText()
+			if err != nil {
+				return nil, err
+			}
+			w.Write(b)
+			return w.buf, nil
+		}
+
+		err := w.writeMessage(mr)
+		return w.buf, err
+	}
+}
+
+var (
+	defaultTextMarshaler = TextMarshaler{}
+	compactTextMarshaler = TextMarshaler{Compact: true}
+)
+
+// MarshalText writes the proto text format of m to w.
+func MarshalText(w io.Writer, m Message) error { return defaultTextMarshaler.Marshal(w, m) }
+
+// MarshalTextString returns a proto text formatted string of m.
+func MarshalTextString(m Message) string { return defaultTextMarshaler.Text(m) }
+
+// CompactText writes the compact proto text format of m to w.
+func CompactText(w io.Writer, m Message) error { return compactTextMarshaler.Marshal(w, m) }
+
+// CompactTextString returns a compact proto text formatted string of m.
+func CompactTextString(m Message) string { return compactTextMarshaler.Text(m) }
+
+var (
+	newline         = []byte("\n")
+	endBraceNewline = []byte("}\n")
+	posInf          = []byte("inf")
+	negInf          = []byte("-inf")
+	nan             = []byte("nan")
+)
+
+// textWriter is an io.Writer that tracks its indentation level.
+type textWriter struct {
+	compact   bool // same as TextMarshaler.Compact
+	expandAny bool // same as TextMarshaler.ExpandAny
+	complete  bool // whether the current position is a complete line
+	indent    int  // indentation level; never negative
+	buf       []byte
+}
+
+func (w *textWriter) Write(p []byte) (n int, _ error) {
+	newlines := bytes.Count(p, newline)
+	if newlines == 0 {
+		if !w.compact && w.complete {
+			w.writeIndent()
+		}
+		w.buf = append(w.buf, p...)
+		w.complete = false
+		return len(p), nil
+	}
+
+	frags := bytes.SplitN(p, newline, newlines+1)
+	if w.compact {
+		for i, frag := range frags {
+			if i > 0 {
+				w.buf = append(w.buf, ' ')
+				n++
+			}
+			w.buf = append(w.buf, frag...)
+			n += len(frag)
+		}
+		return n, nil
+	}
+
+	for i, frag := range frags {
+		if w.complete {
+			w.writeIndent()
+		}
+		w.buf = append(w.buf, frag...)
+		n += len(frag)
+		if i+1 < len(frags) {
+			w.buf = append(w.buf, '\n')
+			n++
+		}
+	}
+	w.complete = len(frags[len(frags)-1]) == 0
+	return n, nil
+}
+
+func (w *textWriter) WriteByte(c byte) error {
+	if w.compact && c == '\n' {
+		c = ' '
+	}
+	if !w.compact && w.complete {
+		w.writeIndent()
+	}
+	w.buf = append(w.buf, c)
+	w.complete = c == '\n'
+	return nil
+}
+
+func (w *textWriter) writeName(fd protoreflect.FieldDescriptor) {
+	if !w.compact && w.complete {
+		w.writeIndent()
+	}
+	w.complete = false
+
+	if fd.Kind() != protoreflect.GroupKind {
+		w.buf = append(w.buf, fd.Name()...)
+		w.WriteByte(':')
+	} else {
+		// Use message type name for group field name.
+		w.buf = append(w.buf, fd.Message().Name()...)
+	}
+
+	if !w.compact {
+		w.WriteByte(' ')
+	}
+}
+
+func requiresQuotes(u string) bool {
+	// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
+	for _, ch := range u {
+		switch {
+		case ch == '.' || ch == '/' || ch == '_':
+			continue
+		case '0' <= ch && ch <= '9':
+			continue
+		case 'A' <= ch && ch <= 'Z':
+			continue
+		case 'a' <= ch && ch <= 'z':
+			continue
+		default:
+			return true
+		}
+	}
+	return false
+}
+
+// writeProto3Any writes an expanded google.protobuf.Any message.
+//
+// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
+// required messages are not linked in).
+//
+// It returns (true, error) when sv was written in expanded format or an error
+// was encountered.
+func (w *textWriter) writeProto3Any(m protoreflect.Message) (bool, error) {
+	md := m.Descriptor()
+	fdURL := md.Fields().ByName("type_url")
+	fdVal := md.Fields().ByName("value")
+
+	url := m.Get(fdURL).String()
+	mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
+	if err != nil {
+		return false, nil
+	}
+
+	b := m.Get(fdVal).Bytes()
+	m2 := mt.New()
+	if err := proto.Unmarshal(b, m2.Interface()); err != nil {
+		return false, nil
+	}
+	w.Write([]byte("["))
+	if requiresQuotes(url) {
+		w.writeQuotedString(url)
+	} else {
+		w.Write([]byte(url))
+	}
+	if w.compact {
+		w.Write([]byte("]:<"))
+	} else {
+		w.Write([]byte("]: <\n"))
+		w.indent++
+	}
+	if err := w.writeMessage(m2); err != nil {
+		return true, err
+	}
+	if w.compact {
+		w.Write([]byte("> "))
+	} else {
+		w.indent--
+		w.Write([]byte(">\n"))
+	}
+	return true, nil
+}
+
+func (w *textWriter) writeMessage(m protoreflect.Message) error {
+	md := m.Descriptor()
+	if w.expandAny && md.FullName() == "google.protobuf.Any" {
+		if canExpand, err := w.writeProto3Any(m); canExpand {
+			return err
+		}
+	}
+
+	fds := md.Fields()
+	for i := 0; i < fds.Len(); {
+		fd := fds.Get(i)
+		if od := fd.ContainingOneof(); od != nil {
+			fd = m.WhichOneof(od)
+			i += od.Fields().Len()
+		} else {
+			i++
+		}
+		if fd == nil || !m.Has(fd) {
+			continue
+		}
+
+		switch {
+		case fd.IsList():
+			lv := m.Get(fd).List()
+			for j := 0; j < lv.Len(); j++ {
+				w.writeName(fd)
+				v := lv.Get(j)
+				if err := w.writeSingularValue(v, fd); err != nil {
+					return err
+				}
+				w.WriteByte('\n')
+			}
+		case fd.IsMap():
+			kfd := fd.MapKey()
+			vfd := fd.MapValue()
+			mv := m.Get(fd).Map()
+
+			type entry struct{ key, val protoreflect.Value }
+			var entries []entry
+			mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
+				entries = append(entries, entry{k.Value(), v})
+				return true
+			})
+			sort.Slice(entries, func(i, j int) bool {
+				switch kfd.Kind() {
+				case protoreflect.BoolKind:
+					return !entries[i].key.Bool() && entries[j].key.Bool()
+				case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
+					return entries[i].key.Int() < entries[j].key.Int()
+				case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
+					return entries[i].key.Uint() < entries[j].key.Uint()
+				case protoreflect.StringKind:
+					return entries[i].key.String() < entries[j].key.String()
+				default:
+					panic("invalid kind")
+				}
+			})
+			for _, entry := range entries {
+				w.writeName(fd)
+				w.WriteByte('<')
+				if !w.compact {
+					w.WriteByte('\n')
+				}
+				w.indent++
+				w.writeName(kfd)
+				if err := w.writeSingularValue(entry.key, kfd); err != nil {
+					return err
+				}
+				w.WriteByte('\n')
+				w.writeName(vfd)
+				if err := w.writeSingularValue(entry.val, vfd); err != nil {
+					return err
+				}
+				w.WriteByte('\n')
+				w.indent--
+				w.WriteByte('>')
+				w.WriteByte('\n')
+			}
+		default:
+			w.writeName(fd)
+			if err := w.writeSingularValue(m.Get(fd), fd); err != nil {
+				return err
+			}
+			w.WriteByte('\n')
+		}
+	}
+
+	if b := m.GetUnknown(); len(b) > 0 {
+		w.writeUnknownFields(b)
+	}
+	return w.writeExtensions(m)
+}
+
+func (w *textWriter) writeSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
+	switch fd.Kind() {
+	case protoreflect.FloatKind, protoreflect.DoubleKind:
+		switch vf := v.Float(); {
+		case math.IsInf(vf, +1):
+			w.Write(posInf)
+		case math.IsInf(vf, -1):
+			w.Write(negInf)
+		case math.IsNaN(vf):
+			w.Write(nan)
+		default:
+			fmt.Fprint(w, v.Interface())
+		}
+	case protoreflect.StringKind:
+		// NOTE: This does not validate UTF-8 for historical reasons.
+		w.writeQuotedString(string(v.String()))
+	case protoreflect.BytesKind:
+		w.writeQuotedString(string(v.Bytes()))
+	case protoreflect.MessageKind, protoreflect.GroupKind:
+		var bra, ket byte = '<', '>'
+		if fd.Kind() == protoreflect.GroupKind {
+			bra, ket = '{', '}'
+		}
+		w.WriteByte(bra)
+		if !w.compact {
+			w.WriteByte('\n')
+		}
+		w.indent++
+		m := v.Message()
+		if m2, ok := m.Interface().(encoding.TextMarshaler); ok {
+			b, err := m2.MarshalText()
+			if err != nil {
+				return err
+			}
+			w.Write(b)
+		} else {
+			w.writeMessage(m)
+		}
+		w.indent--
+		w.WriteByte(ket)
+	case protoreflect.EnumKind:
+		if ev := fd.Enum().Values().ByNumber(v.Enum()); ev != nil {
+			fmt.Fprint(w, ev.Name())
+		} else {
+			fmt.Fprint(w, v.Enum())
+		}
+	default:
+		fmt.Fprint(w, v.Interface())
+	}
+	return nil
+}
+
+// writeQuotedString writes a quoted string in the protocol buffer text format.
+func (w *textWriter) writeQuotedString(s string) {
+	w.WriteByte('"')
+	for i := 0; i < len(s); i++ {
+		switch c := s[i]; c {
+		case '\n':
+			w.buf = append(w.buf, `\n`...)
+		case '\r':
+			w.buf = append(w.buf, `\r`...)
+		case '\t':
+			w.buf = append(w.buf, `\t`...)
+		case '"':
+			w.buf = append(w.buf, `\"`...)
+		case '\\':
+			w.buf = append(w.buf, `\\`...)
+		default:
+			if isPrint := c >= 0x20 && c < 0x7f; isPrint {
+				w.buf = append(w.buf, c)
+			} else {
+				w.buf = append(w.buf, fmt.Sprintf(`\%03o`, c)...)
+			}
+		}
+	}
+	w.WriteByte('"')
+}
+
+func (w *textWriter) writeUnknownFields(b []byte) {
+	if !w.compact {
+		fmt.Fprintf(w, "/* %d unknown bytes */\n", len(b))
+	}
+
+	for len(b) > 0 {
+		num, wtyp, n := protowire.ConsumeTag(b)
+		if n < 0 {
+			return
+		}
+		b = b[n:]
+
+		if wtyp == protowire.EndGroupType {
+			w.indent--
+			w.Write(endBraceNewline)
+			continue
+		}
+		fmt.Fprint(w, num)
+		if wtyp != protowire.StartGroupType {
+			w.WriteByte(':')
+		}
+		if !w.compact || wtyp == protowire.StartGroupType {
+			w.WriteByte(' ')
+		}
+		switch wtyp {
+		case protowire.VarintType:
+			v, n := protowire.ConsumeVarint(b)
+			if n < 0 {
+				return
+			}
+			b = b[n:]
+			fmt.Fprint(w, v)
+		case protowire.Fixed32Type:
+			v, n := protowire.ConsumeFixed32(b)
+			if n < 0 {
+				return
+			}
+			b = b[n:]
+			fmt.Fprint(w, v)
+		case protowire.Fixed64Type:
+			v, n := protowire.ConsumeFixed64(b)
+			if n < 0 {
+				return
+			}
+			b = b[n:]
+			fmt.Fprint(w, v)
+		case protowire.BytesType:
+			v, n := protowire.ConsumeBytes(b)
+			if n < 0 {
+				return
+			}
+			b = b[n:]
+			fmt.Fprintf(w, "%q", v)
+		case protowire.StartGroupType:
+			w.WriteByte('{')
+			w.indent++
+		default:
+			fmt.Fprintf(w, "/* unknown wire type %d */", wtyp)
+		}
+		w.WriteByte('\n')
+	}
+}
+
+// writeExtensions writes all the extensions in m.
+func (w *textWriter) writeExtensions(m protoreflect.Message) error {
+	md := m.Descriptor()
+	if md.ExtensionRanges().Len() == 0 {
+		return nil
+	}
+
+	type ext struct {
+		desc protoreflect.FieldDescriptor
+		val  protoreflect.Value
+	}
+	var exts []ext
+	m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
+		if fd.IsExtension() {
+			exts = append(exts, ext{fd, v})
+		}
+		return true
+	})
+	sort.Slice(exts, func(i, j int) bool {
+		return exts[i].desc.Number() < exts[j].desc.Number()
+	})
+
+	for _, ext := range exts {
+		// For message set, use the name of the message as the extension name.
+		name := string(ext.desc.FullName())
+		if isMessageSet(ext.desc.ContainingMessage()) {
+			name = strings.TrimSuffix(name, ".message_set_extension")
+		}
+
+		if !ext.desc.IsList() {
+			if err := w.writeSingularExtension(name, ext.val, ext.desc); err != nil {
+				return err
+			}
+		} else {
+			lv := ext.val.List()
+			for i := 0; i < lv.Len(); i++ {
+				if err := w.writeSingularExtension(name, lv.Get(i), ext.desc); err != nil {
+					return err
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func (w *textWriter) writeSingularExtension(name string, v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
+	fmt.Fprintf(w, "[%s]:", name)
+	if !w.compact {
+		w.WriteByte(' ')
+	}
+	if err := w.writeSingularValue(v, fd); err != nil {
+		return err
+	}
+	w.WriteByte('\n')
+	return nil
+}
+
+func (w *textWriter) writeIndent() {
+	if !w.complete {
+		return
+	}
+	for i := 0; i < w.indent*2; i++ {
+		w.buf = append(w.buf, ' ')
+	}
+	w.complete = false
+}
