DIGITALOCEAN: go get -u github.com/digitalocean/godo

This commit is contained in:
Tom Limoncelli 2020-05-23 10:15:05 -04:00
parent 4c40130951
commit 8d37020e30
54 changed files with 677 additions and 257 deletions

9
go.mod
View file

@ -16,12 +16,12 @@ require (
github.com/cenkalti/backoff v2.1.1+incompatible // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible // indirect
github.com/digitalocean/godo v1.35.1
github.com/digitalocean/godo v1.36.0
github.com/dnsimple/dnsimple-go v0.62.0
github.com/exoscale/egoscale v0.23.0
github.com/go-acme/lego v2.7.2+incompatible
github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe
github.com/golang/protobuf v1.4.0 // indirect
github.com/golang/protobuf v1.4.2 // indirect
github.com/google/go-github v17.0.0+incompatible
github.com/google/go-querystring v1.0.1-0.20190318165438-c8c88dbee036 // indirect
github.com/gopherjs/jquery v0.0.0-20191017083323-73f4c7416038
@ -47,12 +47,13 @@ require (
github.com/urfave/cli/v2 v2.2.0
github.com/vultr/govultr v0.2.0
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df // indirect
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e // indirect
google.golang.org/api v0.22.0
google.golang.org/appengine v1.6.6 // indirect
gopkg.in/ini.v1 v1.42.0 // indirect
gopkg.in/ns1/ns1-go.v2 v2.0.0-20170502175150-c563826f4cbe
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.2.8
gopkg.in/yaml.v2 v2.3.0
)

18
go.sum
View file

@ -63,8 +63,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible h1:4jGdduO4ceTJFKf0IhgaB8NJapGqKHwC2b4xQ/cXujM=
github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/digitalocean/godo v1.35.1 h1:3P5timR4LTqcCafzrCgV2j83ck4aWb937ybFC7YQVFw=
github.com/digitalocean/godo v1.35.1/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU=
github.com/digitalocean/godo v1.36.0 h1:eRF8wNzHZyU7/wI3De/MQgiVSWdseDaf27bXj2gnOO0=
github.com/digitalocean/godo v1.36.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU=
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dnsimple/dnsimple-go v0.62.0 h1:Lr4U8F08FBL90rMEtQMR547RebifgwTPGCRC/+6ZW4g=
@ -101,6 +101,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@ -290,8 +292,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZ
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 h1:eDrdRpKgkcCqKZQwyZRyeFZgfqt37SL7Kv3tok06cKE=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
@ -363,6 +365,8 @@ google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -388,6 +392,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
@ -403,8 +409,8 @@ gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View file

@ -1,6 +1,8 @@
# Change Log
## unreleased
## [v1.36.0] - 2020-05-12
- #331 Expose expiry_seconds for Registry.DockerCredentials. @andrewsomething
## [v1.35.1] - 2020-04-21

View file

@ -18,7 +18,7 @@ import (
)
const (
libraryVersion = "1.35.1"
libraryVersion = "1.36.0"
defaultBaseURL = "https://api.digitalocean.com/"
userAgent = "godo/" + libraryVersion
mediaType = "application/json"

View file

@ -5,6 +5,7 @@ import (
"context"
"fmt"
"net/http"
"strconv"
"time"
)
@ -43,7 +44,8 @@ type RegistryCreateRequest struct {
// RegistryDockerCredentialsRequest represents a request to retrieve docker
// credentials for a registry.
type RegistryDockerCredentialsRequest struct {
ReadWrite bool `json:"read_write"`
ReadWrite bool `json:"read_write"`
ExpirySeconds *int `json:"expiry_seconds,omitempty"`
}
// Registry represents a registry.
@ -138,13 +140,19 @@ type DockerCredentials struct {
// DockerCredentials retrieves a Docker config file containing the registry's credentials.
func (svc *RegistryServiceOp) DockerCredentials(ctx context.Context, request *RegistryDockerCredentialsRequest) (*DockerCredentials, *Response, error) {
path := fmt.Sprintf("%s/%s?read_write=%t", registryPath, "docker-credentials", request.ReadWrite)
path := fmt.Sprintf("%s/%s", registryPath, "docker-credentials")
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
q := req.URL.Query()
q.Add("read_write", strconv.FormatBool(request.ReadWrite))
if request.ExpirySeconds != nil {
q.Add("expiry_seconds", strconv.Itoa(*request.ExpirySeconds))
}
req.URL.RawQuery = q.Encode()
var buf bytes.Buffer
resp, err := svc.client.Do(ctx, req, &buf)
if err != nil {

View file

@ -33,8 +33,8 @@ func SizeVarint(v uint64) int {
return protowire.SizeVarint(v)
}
// DecodeVarint parses a varint encoded integer from b, returning the
// integer value and the length of the varint.
// DecodeVarint parses a varint encoded integer from b,
// returning the integer value and the length of the varint.
// It returns (0, 0) if there is a parse error.
func DecodeVarint(b []byte) (uint64, int) {
v, n := protowire.ConsumeVarint(b)
@ -112,9 +112,9 @@ func (b *Buffer) Marshal(m Message) error {
return err
}
// Unmarshal parses the wire-format message in the buffer and places the decoded results in m.
//
// Unlike proto.Unmarshal, this does not reset the message before starting to unmarshal.
// Unmarshal parses the wire-format message in the buffer and
// places the decoded results in m.
// It does not reset m before unmarshaling.
func (b *Buffer) Unmarshal(m Message) error {
err := UnmarshalMerge(b.Unread(), m)
b.idx = len(b.buf)
@ -260,7 +260,7 @@ func (b *Buffer) DecodeStringBytes() (string, error) {
}
// DecodeMessage consumes a length-prefixed message from the buffer.
// It does not reset m.
// It does not reset m before unmarshaling.
func (b *Buffer) DecodeMessage(m Message) error {
v, err := b.DecodeRawBytes(false)
if err != nil {
@ -272,7 +272,7 @@ func (b *Buffer) DecodeMessage(m Message) error {
// DecodeGroup consumes a message group from the buffer.
// It assumes that the start group marker has already been consumed and
// consumes all bytes until (and including the end group marker).
// It does not reset m.
// It does not reset m before unmarshaling.
func (b *Buffer) DecodeGroup(m Message) error {
v, n, err := consumeGroup(b.buf[b.idx:])
if err != nil {

View file

@ -9,6 +9,8 @@ import (
"errors"
"fmt"
"strconv"
protoV2 "google.golang.org/protobuf/proto"
)
var (
@ -82,11 +84,30 @@ func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32,
return val, nil
}
// Deprecated: Do not use.
// Deprecated: Do not use; this type existed for intenal-use only.
type InternalMessageInfo struct{}
func (*InternalMessageInfo) DiscardUnknown(Message) { panic("not implemented") }
func (*InternalMessageInfo) Marshal([]byte, Message, bool) ([]byte, error) { panic("not implemented") }
func (*InternalMessageInfo) Merge(Message, Message) { panic("not implemented") }
func (*InternalMessageInfo) Size(Message) int { panic("not implemented") }
func (*InternalMessageInfo) Unmarshal(Message, []byte) error { panic("not implemented") }
// Deprecated: Do not use; this method existed for intenal-use only.
func (*InternalMessageInfo) DiscardUnknown(m Message) {
DiscardUnknown(m)
}
// Deprecated: Do not use; this method existed for intenal-use only.
func (*InternalMessageInfo) Marshal(b []byte, m Message, deterministic bool) ([]byte, error) {
return protoV2.MarshalOptions{Deterministic: deterministic}.MarshalAppend(b, MessageV2(m))
}
// Deprecated: Do not use; this method existed for intenal-use only.
func (*InternalMessageInfo) Merge(dst, src Message) {
protoV2.Merge(MessageV2(dst), MessageV2(src))
}
// Deprecated: Do not use; this method existed for intenal-use only.
func (*InternalMessageInfo) Size(m Message) int {
return protoV2.Size(MessageV2(m))
}
// Deprecated: Do not use; this method existed for intenal-use only.
func (*InternalMessageInfo) Unmarshal(m Message, b []byte) error {
return protoV2.UnmarshalOptions{Merge: true}.Unmarshal(b, MessageV2(m))
}

View file

@ -68,7 +68,7 @@ func HasExtension(m Message, xt *ExtensionDesc) (has bool) {
return has
}
// ClearExtension removes the the exntesion field from m
// ClearExtension removes the extension field from m
// either as an explicitly populated field or as an unknown field.
func ClearExtension(m Message, xt *ExtensionDesc) {
mr := MessageReflect(m)
@ -108,7 +108,7 @@ func ClearAllExtensions(m Message) {
clearUnknown(mr, mr.Descriptor().ExtensionRanges())
}
// GetExtension retrieves a proto2 extended field from pb.
// GetExtension retrieves a proto2 extended field from m.
//
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
// then GetExtension parses the encoded field and returns a Go value of the specified type.

View file

@ -29,7 +29,7 @@ var fileCache sync.Map // map[filePath]fileDescGZIP
// RegisterFile is called from generated code to register the compressed
// FileDescriptorProto with the file path for a proto source file.
//
// Deprecated: Use protoregistry.GlobalFiles.Register instead.
// Deprecated: Use protoregistry.GlobalFiles.RegisterFile instead.
func RegisterFile(s filePath, d fileDescGZIP) {
// Decompress the descriptor.
zr, err := gzip.NewReader(bytes.NewReader(d))
@ -53,7 +53,7 @@ func RegisterFile(s filePath, d fileDescGZIP) {
// FileDescriptor returns the compressed FileDescriptorProto given the file path
// for a proto source file. It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalFiles.RangeFilesByPath instead.
// Deprecated: Use protoregistry.GlobalFiles.FindFileByPath instead.
func FileDescriptor(s filePath) fileDescGZIP {
if v, ok := fileCache.Load(s); ok {
return v.(fileDescGZIP)
@ -98,7 +98,7 @@ var numFilesCache sync.Map // map[protoreflect.FullName]int
// RegisterEnum is called from the generated code to register the mapping of
// enum value names to enum numbers for the enum identified by s.
//
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
// Deprecated: Use protoregistry.GlobalTypes.RegisterEnum instead.
func RegisterEnum(s enumName, _ enumsByNumber, m enumsByName) {
if _, ok := enumCache.Load(s); ok {
panic("proto: duplicate enum registered: " + s)
@ -181,7 +181,7 @@ var messageTypeCache sync.Map // map[messageName]reflect.Type
// RegisterType is called from generated code to register the message Go type
// for a message of the given name.
//
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
// Deprecated: Use protoregistry.GlobalTypes.RegisterMessage instead.
func RegisterType(m Message, s messageName) {
mt := protoimpl.X.LegacyMessageTypeOf(m, protoreflect.FullName(s))
if err := protoregistry.GlobalTypes.RegisterMessage(mt); err != nil {
@ -280,7 +280,7 @@ func MessageName(m Message) messageName {
// RegisterExtension is called from the generated code to register
// the extension descriptor.
//
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
// Deprecated: Use protoregistry.GlobalTypes.RegisterExtension instead.
func RegisterExtension(d *ExtensionDesc) {
if err := protoregistry.GlobalTypes.RegisterExtension(d); err != nil {
panic(err)

View file

@ -94,16 +94,16 @@ var (
)
// MarshalText writes the proto text format of m to w.
func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
func MarshalText(w io.Writer, m Message) error { return defaultTextMarshaler.Marshal(w, m) }
// MarshalTextString returns a proto text formatted string of m.
func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
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, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
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(pb Message) string { return compactTextMarshaler.Text(pb) }
func CompactTextString(m Message) string { return compactTextMarshaler.Text(m) }
var (
newline = []byte("\n")

View file

@ -107,6 +107,7 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
// dialCall is an in-flight Transport dial call to a host.
type dialCall struct {
_ incomparable
p *clientConnPool
done chan struct{} // closed when done
res *ClientConn // valid after done is closed
@ -180,6 +181,7 @@ func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn)
}
type addConnCall struct {
_ incomparable
p *clientConnPool
done chan struct{} // closed when done
err error
@ -200,12 +202,6 @@ func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
close(c.done)
}
func (p *clientConnPool) addConn(key string, cc *ClientConn) {
p.mu.Lock()
p.addConnLocked(key, cc)
p.mu.Unlock()
}
// p.mu must be held
func (p *clientConnPool) addConnLocked(key string, cc *ClientConn) {
for _, v := range p.conns[key] {

View file

@ -8,6 +8,8 @@ package http2
// flow is the flow control window's size.
type flow struct {
_ incomparable
// n is the number of DATA bytes we're allowed to send.
// A flow is kept both on a conn and a per-stream.
n int32

View file

@ -105,7 +105,14 @@ func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
return nil
}
// incomparable is a zero-width, non-comparable type. Adding it to a struct
// makes that struct also non-comparable, and generally doesn't add
// any size (as long as it's first).
type incomparable [0]func()
type node struct {
_ incomparable
// children is non-nil for internal nodes
children *[256]*node

View file

@ -241,6 +241,7 @@ func (cw closeWaiter) Wait() {
// Its buffered writer is lazily allocated as needed, to minimize
// idle memory usage with many connections.
type bufferedWriter struct {
_ incomparable
w io.Writer // immutable
bw *bufio.Writer // non-nil when data is buffered
}
@ -313,6 +314,7 @@ func bodyAllowedForStatus(status int) bool {
}
type httpError struct {
_ incomparable
msg string
timeout bool
}
@ -376,3 +378,8 @@ func (s *sorter) SortStrings(ss []string) {
func validPseudoPath(v string) bool {
return (len(v) > 0 && v[0] == '/') || v == "*"
}
// incomparable is a zero-width, non-comparable type. Adding it to a struct
// makes that struct also non-comparable, and generally doesn't add
// any size (as long as it's first).
type incomparable [0]func()

View file

@ -761,6 +761,7 @@ func (sc *serverConn) readFrames() {
// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
type frameWriteResult struct {
_ incomparable
wr FrameWriteRequest // what was written (or attempted)
err error // result of the writeFrame call
}
@ -771,7 +772,7 @@ type frameWriteResult struct {
// serverConn.
func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) {
err := wr.write.writeFrame(sc)
sc.wroteFrameCh <- frameWriteResult{wr, err}
sc.wroteFrameCh <- frameWriteResult{wr: wr, err: err}
}
func (sc *serverConn) closeAllStreamsOnConnClose() {
@ -1161,7 +1162,7 @@ func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
if wr.write.staysWithinBuffer(sc.bw.Available()) {
sc.writingFrameAsync = false
err := wr.write.writeFrame(sc)
sc.wroteFrame(frameWriteResult{wr, err})
sc.wroteFrame(frameWriteResult{wr: wr, err: err})
} else {
sc.writingFrameAsync = true
go sc.writeFrameAsync(wr)
@ -2057,7 +2058,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
var trailer http.Header
for _, v := range rp.header["Trailer"] {
for _, key := range strings.Split(v, ",") {
key = http.CanonicalHeaderKey(strings.TrimSpace(key))
key = http.CanonicalHeaderKey(textproto.TrimString(key))
switch key {
case "Transfer-Encoding", "Trailer", "Content-Length":
// Bogus. (copy of http1 rules)
@ -2275,6 +2276,7 @@ func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) {
// requestBody is the Handler's Request.Body type.
// Read and Close may be called concurrently.
type requestBody struct {
_ incomparable
stream *stream
conn *serverConn
closed bool // for use by Close only

View file

@ -108,6 +108,19 @@ type Transport struct {
// waiting for their turn.
StrictMaxConcurrentStreams bool
// ReadIdleTimeout is the timeout after which a health check using ping
// frame will be carried out if no frame is received on the connection.
// Note that a ping response will is considered a received frame, so if
// there is no other traffic on the connection, the health check will
// be performed every ReadIdleTimeout interval.
// If zero, no health check is performed.
ReadIdleTimeout time.Duration
// PingTimeout is the timeout after which the connection will be closed
// if a response to Ping is not received.
// Defaults to 15s.
PingTimeout time.Duration
// t1, if non-nil, is the standard library Transport using
// this transport. Its settings are used (but not its
// RoundTrip method, etc).
@ -131,6 +144,14 @@ func (t *Transport) disableCompression() bool {
return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
}
func (t *Transport) pingTimeout() time.Duration {
if t.PingTimeout == 0 {
return 15 * time.Second
}
return t.PingTimeout
}
// ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
// It returns an error if t1 has already been HTTP/2-enabled.
func ConfigureTransport(t1 *http.Transport) error {
@ -675,6 +696,20 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
return cc, nil
}
func (cc *ClientConn) healthCheck() {
pingTimeout := cc.t.pingTimeout()
// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
// trigger the healthCheck again if there is no frame received.
ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
defer cancel()
err := cc.Ping(ctx)
if err != nil {
cc.closeForLostPing()
cc.t.connPool().MarkDead(cc)
return
}
}
func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
cc.mu.Lock()
defer cc.mu.Unlock()
@ -846,14 +881,12 @@ func (cc *ClientConn) sendGoAway() error {
return nil
}
// Close closes the client connection immediately.
//
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
func (cc *ClientConn) Close() error {
// closes the client connection immediately. In-flight requests are interrupted.
// err is sent to streams.
func (cc *ClientConn) closeForError(err error) error {
cc.mu.Lock()
defer cc.cond.Broadcast()
defer cc.mu.Unlock()
err := errors.New("http2: client connection force closed via ClientConn.Close")
for id, cs := range cc.streams {
select {
case cs.resc <- resAndError{err: err}:
@ -866,6 +899,20 @@ func (cc *ClientConn) Close() error {
return cc.tconn.Close()
}
// Close closes the client connection immediately.
//
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
func (cc *ClientConn) Close() error {
err := errors.New("http2: client connection force closed via ClientConn.Close")
return cc.closeForError(err)
}
// closes the client connection immediately. In-flight requests are interrupted.
func (cc *ClientConn) closeForLostPing() error {
err := errors.New("http2: client connection lost")
return cc.closeForError(err)
}
const maxAllocFrameSize = 512 << 10
// frameBuffer returns a scratch buffer suitable for writing DATA frames.
@ -916,7 +963,7 @@ func commaSeparatedTrailers(req *http.Request) (string, error) {
k = http.CanonicalHeaderKey(k)
switch k {
case "Transfer-Encoding", "Trailer", "Content-Length":
return "", &badStringError{"invalid Trailer key", k}
return "", fmt.Errorf("invalid Trailer key %q", k)
}
keys = append(keys, k)
}
@ -1394,13 +1441,6 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
}
}
type badStringError struct {
what string
str string
}
func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
// requires cc.mu be held.
func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
cc.hbuf.Reset()
@ -1616,6 +1656,7 @@ func (cc *ClientConn) writeHeader(name, value string) {
}
type resAndError struct {
_ incomparable
res *http.Response
err error
}
@ -1663,6 +1704,7 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
type clientConnReadLoop struct {
_ incomparable
cc *ClientConn
closeWhenIdle bool
}
@ -1742,8 +1784,17 @@ func (rl *clientConnReadLoop) run() error {
rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse
gotReply := false // ever saw a HEADERS reply
gotSettings := false
readIdleTimeout := cc.t.ReadIdleTimeout
var t *time.Timer
if readIdleTimeout != 0 {
t = time.AfterFunc(readIdleTimeout, cc.healthCheck)
defer t.Stop()
}
for {
f, err := cc.fr.ReadFrame()
if t != nil {
t.Reset(readIdleTimeout)
}
if err != nil {
cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
}
@ -2479,6 +2530,7 @@ func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) {
// gzipReader wraps a response body so it can lazily
// call gzip.NewReader on the first call to Read
type gzipReader struct {
_ incomparable
body io.ReadCloser // underlying Response.Body
zr *gzip.Reader // lazily-initialized gzip reader
zerr error // sticky error

View file

@ -14,9 +14,8 @@ import (
)
const (
Version = 4 // protocol version
HeaderLen = 20 // header length without extension headers
maxHeaderLen = 60 // sensible default, revisit if later RFCs define new usage of version and header length fields
Version = 4 // protocol version
HeaderLen = 20 // header length without extension headers
)
type HeaderFlags int

View file

@ -10,8 +10,6 @@ script:
matrix:
include:
- go: 1.8.x
env: GOAPP=true
- go: 1.9.x
env: GOAPP=true
- go: 1.10.x

View file

@ -58,8 +58,11 @@ var (
apiHTTPClient = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: limitDial,
Proxy: http.ProxyFromEnvironment,
Dial: limitDial,
MaxIdleConns: 1000,
MaxIdleConnsPerHost: 10000,
IdleConnTimeout: 90 * time.Second,
},
}

View file

@ -16,6 +16,7 @@ import (
"google.golang.org/protobuf/internal/flags"
"google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/internal/set"
"google.golang.org/protobuf/internal/strs"
"google.golang.org/protobuf/proto"
pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
@ -339,10 +340,10 @@ func (d decoder) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
case pref.StringKind:
if s, ok := tok.String(); ok {
if utf8.ValidString(s) {
return pref.ValueOfString(s), nil
if strs.EnforceUTF8(fd) && !utf8.ValidString(s) {
return pref.Value{}, d.newError(tok.Pos(), "contains invalid UTF-8")
}
return pref.Value{}, d.newError(tok.Pos(), "contains invalid UTF-8")
return pref.ValueOfString(s), nil
}
case pref.BytesKind:

View file

@ -18,6 +18,7 @@ import (
"google.golang.org/protobuf/internal/flags"
"google.golang.org/protobuf/internal/mapsort"
"google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/internal/strs"
"google.golang.org/protobuf/proto"
pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
@ -55,6 +56,15 @@ type MarshalOptions struct {
// Indent can only be composed of space or tab characters.
Indent string
// EmitASCII specifies whether to format strings and bytes as ASCII only
// as opposed to using UTF-8 encoding when possible.
EmitASCII bool
// allowInvalidUTF8 specifies whether to permit the encoding of strings
// with invalid UTF-8. This is unexported as it is intended to only
// be specified by the Format method.
allowInvalidUTF8 bool
// AllowPartial allows messages that have missing required fields to marshal
// without returning an error. If AllowPartial is false (the default),
// Marshal will return error if there are any missing required fields.
@ -81,6 +91,7 @@ func (o MarshalOptions) Format(m proto.Message) string {
if m == nil || !m.ProtoReflect().IsValid() {
return "<nil>" // invalid syntax, but okay since this is for debugging
}
o.allowInvalidUTF8 = true
o.AllowPartial = true
o.EmitUnknown = true
b, _ := o.Marshal(m)
@ -91,7 +102,6 @@ func (o MarshalOptions) Format(m proto.Message) string {
// MarshalOptions object. Do not depend on the output being stable. It may
// change over time across different versions of the program.
func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
const outputASCII = false
var delims = [2]byte{'{', '}'}
if o.Multiline && o.Indent == "" {
@ -101,11 +111,17 @@ func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
o.Resolver = protoregistry.GlobalTypes
}
internalEnc, err := text.NewEncoder(o.Indent, delims, outputASCII)
internalEnc, err := text.NewEncoder(o.Indent, delims, o.EmitASCII)
if err != nil {
return nil, err
}
// Treat nil message interface as an empty message,
// in which case there is nothing to output.
if m == nil {
return []byte{}, nil
}
enc := encoder{internalEnc, o}
err = enc.marshalMessage(m.ProtoReflect(), false)
if err != nil {
@ -209,7 +225,7 @@ func (e encoder) marshalSingular(val pref.Value, fd pref.FieldDescriptor) error
case pref.StringKind:
s := val.String()
if !utf8.ValidString(s) {
if !e.opts.allowInvalidUTF8 && strs.EnforceUTF8(fd) && !utf8.ValidString(s) {
return errors.InvalidUTF8(string(fd.FullName()))
}
e.WriteString(s)

View file

@ -106,7 +106,7 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
var descriptorAccessors = map[reflect.Type][]string{
reflect.TypeOf((*pref.FileDescriptor)(nil)).Elem(): {"Path", "Package", "Imports", "Messages", "Enums", "Extensions", "Services"},
reflect.TypeOf((*pref.MessageDescriptor)(nil)).Elem(): {"IsMapEntry", "Fields", "Oneofs", "ReservedNames", "ReservedRanges", "RequiredNumbers", "ExtensionRanges", "Messages", "Enums", "Extensions"},
reflect.TypeOf((*pref.FieldDescriptor)(nil)).Elem(): {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "IsPacked", "IsExtension", "IsWeak", "IsList", "IsMap", "MapKey", "MapValue", "HasDefault", "Default", "ContainingOneof", "ContainingMessage", "Message", "Enum"},
reflect.TypeOf((*pref.FieldDescriptor)(nil)).Elem(): {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "HasPresence", "IsExtension", "IsPacked", "IsWeak", "IsList", "IsMap", "MapKey", "MapValue", "HasDefault", "Default", "ContainingOneof", "ContainingMessage", "Message", "Enum"},
reflect.TypeOf((*pref.OneofDescriptor)(nil)).Elem(): {"Fields"}, // not directly used; must keep in sync with formatDescOpt
reflect.TypeOf((*pref.EnumDescriptor)(nil)).Elem(): {"Values", "ReservedNames", "ReservedRanges"},
reflect.TypeOf((*pref.EnumValueDescriptor)(nil)).Elem(): {"Number"},

View file

@ -61,16 +61,17 @@ const (
// Field numbers for google.protobuf.FieldDescriptorProto.
const (
FieldDescriptorProto_Name = 1 // optional string
FieldDescriptorProto_Number = 3 // optional int32
FieldDescriptorProto_Label = 4 // optional google.protobuf.FieldDescriptorProto.Label
FieldDescriptorProto_Type = 5 // optional google.protobuf.FieldDescriptorProto.Type
FieldDescriptorProto_TypeName = 6 // optional string
FieldDescriptorProto_Extendee = 2 // optional string
FieldDescriptorProto_DefaultValue = 7 // optional string
FieldDescriptorProto_OneofIndex = 9 // optional int32
FieldDescriptorProto_JsonName = 10 // optional string
FieldDescriptorProto_Options = 8 // optional google.protobuf.FieldOptions
FieldDescriptorProto_Name = 1 // optional string
FieldDescriptorProto_Number = 3 // optional int32
FieldDescriptorProto_Label = 4 // optional google.protobuf.FieldDescriptorProto.Label
FieldDescriptorProto_Type = 5 // optional google.protobuf.FieldDescriptorProto.Type
FieldDescriptorProto_TypeName = 6 // optional string
FieldDescriptorProto_Extendee = 2 // optional string
FieldDescriptorProto_DefaultValue = 7 // optional string
FieldDescriptorProto_OneofIndex = 9 // optional int32
FieldDescriptorProto_JsonName = 10 // optional string
FieldDescriptorProto_Options = 8 // optional google.protobuf.FieldOptions
FieldDescriptorProto_Proto3Optional = 17 // optional bool
)
// Field numbers for google.protobuf.OneofDescriptorProto.

View file

@ -30,9 +30,9 @@ func Less(a, b protoreflect.FieldDescriptor) bool {
return a.Number() < b.Number()
}
return oa.Index() < ob.Index()
case oa != nil:
case oa != nil && !oa.IsSynthetic():
return false
case ob != nil:
case ob != nil && !ob.IsSynthetic():
return true
default:
return a.Number() < b.Number()

View file

@ -77,7 +77,7 @@ func (fd *File) Enums() pref.EnumDescriptors { return &fd.L1.Enums }
func (fd *File) Messages() pref.MessageDescriptors { return &fd.L1.Messages }
func (fd *File) Extensions() pref.ExtensionDescriptors { return &fd.L1.Extensions }
func (fd *File) Services() pref.ServiceDescriptors { return &fd.L1.Services }
func (fd *File) SourceLocations() pref.SourceLocations { return &fd.L2.Locations }
func (fd *File) SourceLocations() pref.SourceLocations { return &fd.lazyInit().Locations }
func (fd *File) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) }
func (fd *File) ProtoType(pref.FileDescriptor) {}
func (fd *File) ProtoInternal(pragma.DoNotImplement) {}
@ -202,20 +202,21 @@ type (
L1 FieldL1
}
FieldL1 struct {
Options func() pref.ProtoMessage
Number pref.FieldNumber
Cardinality pref.Cardinality // must be consistent with Message.RequiredNumbers
Kind pref.Kind
JSONName jsonName
IsWeak bool // promoted from google.protobuf.FieldOptions
HasPacked bool // promoted from google.protobuf.FieldOptions
IsPacked bool // promoted from google.protobuf.FieldOptions
HasEnforceUTF8 bool // promoted from google.protobuf.FieldOptions
EnforceUTF8 bool // promoted from google.protobuf.FieldOptions
Default defaultValue
ContainingOneof pref.OneofDescriptor // must be consistent with Message.Oneofs.Fields
Enum pref.EnumDescriptor
Message pref.MessageDescriptor
Options func() pref.ProtoMessage
Number pref.FieldNumber
Cardinality pref.Cardinality // must be consistent with Message.RequiredNumbers
Kind pref.Kind
JSONName jsonName
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
IsWeak bool // promoted from google.protobuf.FieldOptions
HasPacked bool // promoted from google.protobuf.FieldOptions
IsPacked bool // promoted from google.protobuf.FieldOptions
HasEnforceUTF8 bool // promoted from google.protobuf.FieldOptions
EnforceUTF8 bool // promoted from google.protobuf.FieldOptions
Default defaultValue
ContainingOneof pref.OneofDescriptor // must be consistent with Message.Oneofs.Fields
Enum pref.EnumDescriptor
Message pref.MessageDescriptor
}
Oneof struct {
@ -277,6 +278,12 @@ func (fd *Field) Cardinality() pref.Cardinality { return fd.L1.Cardinality }
func (fd *Field) Kind() pref.Kind { return fd.L1.Kind }
func (fd *Field) HasJSONName() bool { return fd.L1.JSONName.has }
func (fd *Field) JSONName() string { return fd.L1.JSONName.get(fd) }
func (fd *Field) HasPresence() bool {
return fd.L1.Cardinality != pref.Repeated && (fd.L0.ParentFile.L1.Syntax == pref.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil)
}
func (fd *Field) HasOptionalKeyword() bool {
return (fd.L0.ParentFile.L1.Syntax == pref.Proto2 && fd.L1.Cardinality == pref.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional
}
func (fd *Field) IsPacked() bool {
if !fd.L1.HasPacked && fd.L0.ParentFile.L1.Syntax != pref.Proto2 && fd.L1.Cardinality == pref.Repeated {
switch fd.L1.Kind {
@ -338,6 +345,9 @@ func (fd *Field) EnforceUTF8() bool {
return fd.L0.ParentFile.L1.Syntax == pref.Proto3
}
func (od *Oneof) IsSynthetic() bool {
return od.L0.ParentFile.L1.Syntax == pref.Proto3 && len(od.L1.Fields.List) == 1 && od.L1.Fields.List[0].HasOptionalKeyword()
}
func (od *Oneof) Options() pref.ProtoMessage {
if f := od.L1.Options; f != nil {
return f()
@ -361,12 +371,13 @@ type (
Kind pref.Kind
}
ExtensionL2 struct {
Options func() pref.ProtoMessage
JSONName jsonName
IsPacked bool // promoted from google.protobuf.FieldOptions
Default defaultValue
Enum pref.EnumDescriptor
Message pref.MessageDescriptor
Options func() pref.ProtoMessage
JSONName jsonName
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
IsPacked bool // promoted from google.protobuf.FieldOptions
Default defaultValue
Enum pref.EnumDescriptor
Message pref.MessageDescriptor
}
)
@ -376,11 +387,15 @@ func (xd *Extension) Options() pref.ProtoMessage {
}
return descopts.Field
}
func (xd *Extension) Number() pref.FieldNumber { return xd.L1.Number }
func (xd *Extension) Cardinality() pref.Cardinality { return xd.L1.Cardinality }
func (xd *Extension) Kind() pref.Kind { return xd.L1.Kind }
func (xd *Extension) HasJSONName() bool { return xd.lazyInit().JSONName.has }
func (xd *Extension) JSONName() string { return xd.lazyInit().JSONName.get(xd) }
func (xd *Extension) Number() pref.FieldNumber { return xd.L1.Number }
func (xd *Extension) Cardinality() pref.Cardinality { return xd.L1.Cardinality }
func (xd *Extension) Kind() pref.Kind { return xd.L1.Kind }
func (xd *Extension) HasJSONName() bool { return xd.lazyInit().JSONName.has }
func (xd *Extension) JSONName() string { return xd.lazyInit().JSONName.get(xd) }
func (xd *Extension) HasPresence() bool { return xd.L1.Cardinality != pref.Repeated }
func (xd *Extension) HasOptionalKeyword() bool {
return (xd.L0.ParentFile.L1.Syntax == pref.Proto2 && xd.L1.Cardinality == pref.Optional) || xd.lazyInit().IsProto3Optional
}
func (xd *Extension) IsPacked() bool { return xd.lazyInit().IsPacked }
func (xd *Extension) IsExtension() bool { return true }
func (xd *Extension) IsWeak() bool { return false }
@ -592,7 +607,7 @@ func (dv *defaultValue) get(fd pref.FieldDescriptor) pref.Value {
// TODO: Avoid panic if we're running with the race detector
// and instead spawn a goroutine that periodically resets
// this value back to the original to induce a race.
panic("detected mutation on the default bytes")
panic(fmt.Sprintf("detected mutation on the default bytes for %v", fd.FullName()))
}
return dv.val
}

View file

@ -441,6 +441,8 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Des
panic("oneof type already set")
}
fd.L1.ContainingOneof = od
case fieldnum.FieldDescriptorProto_Proto3Optional:
fd.L1.IsProto3Optional = protowire.DecodeBool(v)
}
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
@ -537,6 +539,13 @@ func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
num, typ, n := protowire.ConsumeTag(b)
b = b[n:]
switch typ {
case protowire.VarintType:
v, m := protowire.ConsumeVarint(b)
b = b[m:]
switch num {
case fieldnum.FieldDescriptorProto_Proto3Optional:
xd.L2.IsProto3Optional = protowire.DecodeBool(v)
}
case protowire.BytesType:
v, m := protowire.ConsumeBytes(b)
b = b[m:]

View file

@ -5078,6 +5078,46 @@ var coderStringPtr = pointerCoderFuncs{
merge: mergeStringPtr,
}
// appendStringPtrValidateUTF8 wire encodes a *string pointer as a String.
// It panics if the pointer is nil.
func appendStringPtrValidateUTF8(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := **p.StringPtr()
b = protowire.AppendVarint(b, f.wiretag)
b = protowire.AppendString(b, v)
if !utf8.ValidString(v) {
return b, errInvalidUTF8{}
}
return b, nil
}
// consumeStringPtrValidateUTF8 wire decodes a *string pointer as a String.
func consumeStringPtrValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != protowire.BytesType {
return out, errUnknown
}
v, n := protowire.ConsumeString(b)
if n < 0 {
return out, protowire.ParseError(n)
}
if !utf8.ValidString(v) {
return out, errInvalidUTF8{}
}
vp := p.StringPtr()
if *vp == nil {
*vp = new(string)
}
**vp = v
out.n = n
return out, nil
}
var coderStringPtrValidateUTF8 = pointerCoderFuncs{
size: sizeStringPtr,
marshal: appendStringPtrValidateUTF8,
unmarshal: consumeStringPtrValidateUTF8,
merge: mergeStringPtr,
}
// sizeStringSlice returns the size of wire encoding a []string pointer as a repeated String.
func sizeStringSlice(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
s := *p.StringSlice()

View file

@ -53,11 +53,13 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
mi.coderFields = make(map[protowire.Number]*coderFieldInfo)
fields := mi.Desc.Fields()
preallocFields := make([]coderFieldInfo, fields.Len())
for i := 0; i < fields.Len(); i++ {
fd := fields.Get(i)
fs := si.fieldsByNumber[fd.Number()]
if fd.ContainingOneof() != nil {
isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic()
if isOneof {
fs = si.oneofsByName[fd.ContainingOneof().Name()]
}
ft := fs.Type
@ -71,7 +73,7 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
var funcs pointerCoderFuncs
var childMessage *MessageInfo
switch {
case fd.ContainingOneof() != nil:
case isOneof:
fieldOffset = offsetOf(fs, mi.Exporter)
case fd.IsWeak():
fieldOffset = si.weakOffset
@ -80,7 +82,8 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
fieldOffset = offsetOf(fs, mi.Exporter)
childMessage, funcs = fieldCoder(fd, ft)
}
cf := &coderFieldInfo{
cf := &preallocFields[i]
*cf = coderFieldInfo{
num: fd.Number(),
offset: fieldOffset,
wiretag: wiretag,
@ -89,17 +92,16 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
funcs: funcs,
mi: childMessage,
validation: newFieldValidationInfo(mi, si, fd, ft),
isPointer: (fd.Cardinality() == pref.Repeated ||
fd.Kind() == pref.MessageKind ||
fd.Kind() == pref.GroupKind ||
fd.Syntax() != pref.Proto3),
isPointer: fd.Cardinality() == pref.Repeated || fd.HasPresence(),
isRequired: fd.Cardinality() == pref.Required,
}
mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
mi.coderFields[cf.num] = cf
}
for i, oneofs := 0, mi.Desc.Oneofs(); i < oneofs.Len(); i++ {
mi.initOneofFieldCoders(oneofs.Get(i), si)
if od := oneofs.Get(i); !od.IsSynthetic() {
mi.initOneofFieldCoders(od, si)
}
}
if messageset.IsMessageSet(mi.Desc) {
if !mi.extensionOffset.IsValid() {
@ -123,7 +125,7 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
}
mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1)
for _, cf := range mi.orderedCoderFields {
if int(cf.num) > len(mi.denseCoderFields) {
if int(cf.num) >= len(mi.denseCoderFields) {
break
}
mi.denseCoderFields[cf.num] = cf

View file

@ -338,6 +338,9 @@ func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) (*MessageInfo, pointer
return nil, coderDoublePtr
}
case pref.StringKind:
if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) {
return nil, coderStringPtrValidateUTF8
}
if ft.Kind() == reflect.String {
return nil, coderStringPtr
}

View file

@ -162,7 +162,7 @@ func (c *boolConverter) IsValidPB(v pref.Value) bool {
return ok
}
func (c *boolConverter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *boolConverter) New() pref.Value { return c.def }
func (c *boolConverter) Zero() pref.Value { return c.def }
@ -186,7 +186,7 @@ func (c *int32Converter) IsValidPB(v pref.Value) bool {
return ok
}
func (c *int32Converter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *int32Converter) New() pref.Value { return c.def }
func (c *int32Converter) Zero() pref.Value { return c.def }
@ -210,7 +210,7 @@ func (c *int64Converter) IsValidPB(v pref.Value) bool {
return ok
}
func (c *int64Converter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *int64Converter) New() pref.Value { return c.def }
func (c *int64Converter) Zero() pref.Value { return c.def }
@ -234,7 +234,7 @@ func (c *uint32Converter) IsValidPB(v pref.Value) bool {
return ok
}
func (c *uint32Converter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *uint32Converter) New() pref.Value { return c.def }
func (c *uint32Converter) Zero() pref.Value { return c.def }
@ -258,7 +258,7 @@ func (c *uint64Converter) IsValidPB(v pref.Value) bool {
return ok
}
func (c *uint64Converter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *uint64Converter) New() pref.Value { return c.def }
func (c *uint64Converter) Zero() pref.Value { return c.def }
@ -282,7 +282,7 @@ func (c *float32Converter) IsValidPB(v pref.Value) bool {
return ok
}
func (c *float32Converter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *float32Converter) New() pref.Value { return c.def }
func (c *float32Converter) Zero() pref.Value { return c.def }
@ -306,7 +306,7 @@ func (c *float64Converter) IsValidPB(v pref.Value) bool {
return ok
}
func (c *float64Converter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *float64Converter) New() pref.Value { return c.def }
func (c *float64Converter) Zero() pref.Value { return c.def }
@ -336,7 +336,7 @@ func (c *stringConverter) IsValidPB(v pref.Value) bool {
return ok
}
func (c *stringConverter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *stringConverter) New() pref.Value { return c.def }
func (c *stringConverter) Zero() pref.Value { return c.def }
@ -363,7 +363,7 @@ func (c *bytesConverter) IsValidPB(v pref.Value) bool {
return ok
}
func (c *bytesConverter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *bytesConverter) New() pref.Value { return c.def }
func (c *bytesConverter) Zero() pref.Value { return c.def }
@ -400,7 +400,7 @@ func (c *enumConverter) IsValidPB(v pref.Value) bool {
}
func (c *enumConverter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *enumConverter) New() pref.Value {
@ -455,7 +455,7 @@ func (c *messageConverter) IsValidPB(v pref.Value) bool {
}
func (c *messageConverter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *messageConverter) New() pref.Value {

View file

@ -22,7 +22,7 @@ func newListConverter(t reflect.Type, fd pref.FieldDescriptor) Converter {
}
type listConverter struct {
goType reflect.Type
goType reflect.Type // []T
c Converter
}
@ -48,11 +48,11 @@ func (c *listConverter) IsValidPB(v pref.Value) bool {
if !ok {
return false
}
return list.v.Type().Elem() == c.goType && list.IsValid()
return list.v.Type().Elem() == c.goType
}
func (c *listConverter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *listConverter) New() pref.Value {
@ -64,7 +64,7 @@ func (c *listConverter) Zero() pref.Value {
}
type listPtrConverter struct {
goType reflect.Type
goType reflect.Type // *[]T
c Converter
}
@ -88,7 +88,7 @@ func (c *listPtrConverter) IsValidPB(v pref.Value) bool {
}
func (c *listPtrConverter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *listPtrConverter) New() pref.Value {

View file

@ -12,7 +12,7 @@ import (
)
type mapConverter struct {
goType reflect.Type
goType reflect.Type // map[K]V
keyConv, valConv Converter
}
@ -43,11 +43,11 @@ func (c *mapConverter) IsValidPB(v pref.Value) bool {
if !ok {
return false
}
return mapv.v.Type() == c.goType && mapv.IsValid()
return mapv.v.Type() == c.goType
}
func (c *mapConverter) IsValidGo(v reflect.Value) bool {
return v.Type() == c.goType
return v.IsValid() && v.Type() == c.goType
}
func (c *mapConverter) New() pref.Value {

View file

@ -7,14 +7,12 @@ package impl
import (
"encoding/binary"
"encoding/json"
"fmt"
"hash/crc32"
"math"
"reflect"
"google.golang.org/protobuf/internal/errors"
pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
piface "google.golang.org/protobuf/runtime/protoiface"
)
@ -92,13 +90,3 @@ func (Export) CompressGZIP(in []byte) (out []byte) {
out = append(out, gzipFooter[:]...)
return out
}
// WeakNil returns a typed nil pointer to a concrete message.
// It panics if the message is not linked into the binary.
func (Export) WeakNil(s pref.FullName) piface.MessageV1 {
mt, err := protoregistry.GlobalTypes.FindMessageByName(s)
if err != nil {
panic(fmt.Sprintf("weak message %v is not linked in", s))
}
return mt.Zero().Interface().(piface.MessageV1)
}

View file

@ -155,6 +155,8 @@ func (x placeholderExtension) Cardinality() pref.Cardinality { retu
func (x placeholderExtension) Kind() pref.Kind { return 0 }
func (x placeholderExtension) HasJSONName() bool { return false }
func (x placeholderExtension) JSONName() string { return "" }
func (x placeholderExtension) HasPresence() bool { return false }
func (x placeholderExtension) HasOptionalKeyword() bool { return false }
func (x placeholderExtension) IsExtension() bool { return true }
func (x placeholderExtension) IsWeak() bool { return false }
func (x placeholderExtension) IsPacked() bool { return false }

View file

@ -15,7 +15,6 @@ import (
"google.golang.org/protobuf/internal/genname"
"google.golang.org/protobuf/reflect/protoreflect"
pref "google.golang.org/protobuf/reflect/protoreflect"
piface "google.golang.org/protobuf/runtime/protoiface"
)
// MessageInfo provides protobuf related functionality for a given Go type
@ -109,7 +108,7 @@ func (mi *MessageInfo) getPointer(m pref.Message) (p pointer, ok bool) {
type (
SizeCache = int32
WeakFields = map[int32]piface.MessageV1
WeakFields = map[int32]protoreflect.ProtoMessage
UnknownFields = []byte
ExtensionFields = map[int32]ExtensionField
)

View file

@ -53,7 +53,7 @@ func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
fs := si.fieldsByNumber[fd.Number()]
var fi fieldInfo
switch {
case fd.ContainingOneof() != nil:
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
fi = fieldInfoForOneof(fd, si.oneofsByName[fd.ContainingOneof().Name()], mi.Exporter, si.oneofWrappersByNumber[fd.Number()])
case fd.IsMap():
fi = fieldInfoForMap(fd, fs, mi.Exporter)
@ -72,7 +72,7 @@ func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
mi.oneofs = map[pref.Name]*oneofInfo{}
for i := 0; i < md.Oneofs().Len(); i++ {
od := md.Oneofs().Get(i)
mi.oneofs[od.Name()] = makeOneofInfo(od, si.oneofsByName[od.Name()], mi.Exporter, si.oneofWrappersByType)
mi.oneofs[od.Name()] = makeOneofInfo(od, si, mi.Exporter)
}
mi.denseFields = make([]*fieldInfo, fds.Len()*2)
@ -84,7 +84,7 @@ func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
for i := 0; i < fds.Len(); {
fd := fds.Get(i)
if od := fd.ContainingOneof(); od != nil {
if od := fd.ContainingOneof(); od != nil && !od.IsSynthetic() {
mi.rangeInfos = append(mi.rangeInfos, mi.oneofs[od.Name()])
i += od.Fields().Len()
} else {
@ -170,6 +170,8 @@ func (m *extensionMap) Has(xt pref.ExtensionType) (ok bool) {
return x.Value().List().Len() > 0
case xd.IsMap():
return x.Value().Map().Len() > 0
case xd.Message() != nil:
return x.Value().Message().IsValid()
}
return true
}
@ -186,15 +188,28 @@ func (m *extensionMap) Get(xt pref.ExtensionType) pref.Value {
return xt.Zero()
}
func (m *extensionMap) Set(xt pref.ExtensionType, v pref.Value) {
if !xt.IsValidValue(v) {
xd := xt.TypeDescriptor()
isValid := true
switch {
case !xt.IsValidValue(v):
isValid = false
case xd.IsList():
isValid = v.List().IsValid()
case xd.IsMap():
isValid = v.Map().IsValid()
case xd.Message() != nil:
isValid = v.Message().IsValid()
}
if !isValid {
panic(fmt.Sprintf("%v: assigning invalid value", xt.TypeDescriptor().FullName()))
}
if *m == nil {
*m = make(map[int32]ExtensionField)
}
var x ExtensionField
x.Set(xt, v)
(*m)[int32(xt.TypeDescriptor().Number())] = x
(*m)[int32(xd.Number())] = x
}
func (m *extensionMap) Mutable(xt pref.ExtensionType) pref.Value {
xd := xt.TypeDescriptor()
@ -323,24 +338,27 @@ func (mi *MessageInfo) checkField(fd pref.FieldDescriptor) (*fieldInfo, pref.Ext
}
if fi != nil {
if fi.fieldDesc != fd {
panic("mismatching field descriptor")
if got, want := fd.FullName(), fi.fieldDesc.FullName(); got != want {
panic(fmt.Sprintf("mismatching field: got %v, want %v", got, want))
}
panic(fmt.Sprintf("mismatching field: %v", fd.FullName()))
}
return fi, nil
}
if fd.IsExtension() {
if fd.ContainingMessage().FullName() != mi.Desc.FullName() {
if got, want := fd.ContainingMessage().FullName(), mi.Desc.FullName(); got != want {
// TODO: Should this be exact containing message descriptor match?
panic("mismatching containing message")
panic(fmt.Sprintf("extension %v has mismatching containing message: got %v, want %v", fd.FullName(), got, want))
}
if !mi.Desc.ExtensionRanges().Has(fd.Number()) {
panic("invalid extension field")
panic(fmt.Sprintf("extension %v extends %v outside the extension range", fd.FullName(), mi.Desc.FullName()))
}
xtd, ok := fd.(pref.ExtensionTypeDescriptor)
if !ok {
panic("extension descriptor does not implement ExtensionTypeDescriptor")
panic(fmt.Sprintf("extension %v does not implement protoreflect.ExtensionTypeDescriptor", fd.FullName()))
}
return nil, xtd.Type()
}
panic("invalid field descriptor")
panic(fmt.Sprintf("field %v is invalid", fd.FullName()))
}

View file

@ -31,13 +31,13 @@ type fieldInfo struct {
func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x exporter, ot reflect.Type) fieldInfo {
ft := fs.Type
if ft.Kind() != reflect.Interface {
panic(fmt.Sprintf("invalid type: got %v, want interface kind", ft))
panic(fmt.Sprintf("field %v has invalid type: got %v, want interface kind", fd.FullName(), ft))
}
if ot.Kind() != reflect.Struct {
panic(fmt.Sprintf("invalid type: got %v, want struct kind", ot))
panic(fmt.Sprintf("field %v has invalid type: got %v, want struct kind", fd.FullName(), ot))
}
if !reflect.PtrTo(ot).Implements(ft) {
panic(fmt.Sprintf("invalid type: %v does not implement %v", ot, ft))
panic(fmt.Sprintf("field %v has invalid type: %v does not implement %v", fd.FullName(), ot, ft))
}
conv := NewConverter(ot.Field(0).Type, fd)
isMessage := fd.Message() != nil
@ -90,7 +90,7 @@ func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x export
},
mutable: func(p pointer) pref.Value {
if !isMessage {
panic("invalid Mutable on field with non-composite type")
panic(fmt.Sprintf("field %v with invalid Mutable call on field with non-composite type", fd.FullName()))
}
rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
@ -114,7 +114,7 @@ func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x export
func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
ft := fs.Type
if ft.Kind() != reflect.Map {
panic(fmt.Sprintf("invalid type: got %v, want map kind", ft))
panic(fmt.Sprintf("field %v has invalid type: got %v, want map kind", fd.FullName(), ft))
}
conv := NewConverter(ft, fd)
@ -147,7 +147,7 @@ func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField, x exporter
rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
pv := conv.GoValueOf(v)
if pv.IsNil() {
panic(fmt.Sprintf("invalid value: setting map field to read-only value"))
panic(fmt.Sprintf("map field %v cannot be set with read-only value", fd.FullName()))
}
rv.Set(pv)
},
@ -167,7 +167,7 @@ func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField, x exporter
func fieldInfoForList(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
ft := fs.Type
if ft.Kind() != reflect.Slice {
panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft))
panic(fmt.Sprintf("field %v has invalid type: got %v, want slice kind", fd.FullName(), ft))
}
conv := NewConverter(reflect.PtrTo(ft), fd)
@ -200,7 +200,7 @@ func fieldInfoForList(fd pref.FieldDescriptor, fs reflect.StructField, x exporte
rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
pv := conv.GoValueOf(v)
if pv.IsNil() {
panic(fmt.Sprintf("invalid value: setting repeated field to read-only value"))
panic(fmt.Sprintf("list field %v cannot be set with read-only value", fd.FullName()))
}
rv.Set(pv.Elem())
},
@ -221,11 +221,11 @@ var (
func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
ft := fs.Type
nullable := fd.Syntax() == pref.Proto2
nullable := fd.HasPresence()
isBytes := ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8
if nullable {
if ft.Kind() != reflect.Ptr && ft.Kind() != reflect.Slice {
panic(fmt.Sprintf("invalid type: got %v, want pointer", ft))
panic(fmt.Sprintf("field %v has invalid type: got %v, want pointer", fd.FullName(), ft))
}
if ft.Kind() == reflect.Ptr {
ft = ft.Elem()
@ -257,7 +257,7 @@ func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField, x expor
case reflect.String, reflect.Slice:
return rv.Len() > 0
default:
panic(fmt.Sprintf("invalid type: %v", rv.Type())) // should never happen
panic(fmt.Sprintf("field %v has invalid type: %v", fd.FullName(), rv.Type())) // should never happen
}
},
clear: func(p pointer) {
@ -290,9 +290,9 @@ func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField, x expor
rv.Set(conv.GoValueOf(v))
if isBytes && rv.Len() == 0 {
if nullable {
rv.Set(emptyBytes) // preserve presence in proto2
rv.Set(emptyBytes) // preserve presence
} else {
rv.Set(nilBytes) // do not preserve presence in proto3
rv.Set(nilBytes) // do not preserve presence
}
}
},
@ -314,7 +314,7 @@ func fieldInfoForWeakMessage(fd pref.FieldDescriptor, weakOffset offset) fieldIn
messageName := fd.Message().FullName()
messageType, _ = preg.GlobalTypes.FindMessageByName(messageName)
if messageType == nil {
panic(fmt.Sprintf("weak message %v is not linked in", messageName))
panic(fmt.Sprintf("weak message %v for field %v is not linked in", messageName, fd.FullName()))
}
})
}
@ -347,7 +347,10 @@ func fieldInfoForWeakMessage(fd pref.FieldDescriptor, weakOffset offset) fieldIn
lazyInit()
m := v.Message()
if m.Descriptor() != messageType.Descriptor() {
panic("mismatching message descriptor")
if got, want := m.Descriptor().FullName(), messageType.Descriptor().FullName(); got != want {
panic(fmt.Sprintf("field %v has mismatching message descriptor: got %v, want %v", fd.FullName(), got, want))
}
panic(fmt.Sprintf("field %v has mismatching message descriptor: %v", fd.FullName(), m.Descriptor().FullName()))
}
p.Apply(weakOffset).WeakFields().set(num, m.Interface())
},
@ -402,7 +405,7 @@ func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField, x expo
rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
rv.Set(conv.GoValueOf(v))
if rv.IsNil() {
panic("invalid nil pointer")
panic(fmt.Sprintf("field %v has invalid nil pointer", fd.FullName()))
}
},
mutable: func(p pointer) pref.Value {
@ -426,11 +429,25 @@ type oneofInfo struct {
which func(pointer) pref.FieldNumber
}
func makeOneofInfo(od pref.OneofDescriptor, fs reflect.StructField, x exporter, wrappersByType map[reflect.Type]pref.FieldNumber) *oneofInfo {
fieldOffset := offsetOf(fs, x)
return &oneofInfo{
oneofDesc: od,
which: func(p pointer) pref.FieldNumber {
func makeOneofInfo(od pref.OneofDescriptor, si structInfo, x exporter) *oneofInfo {
oi := &oneofInfo{oneofDesc: od}
if od.IsSynthetic() {
fs := si.fieldsByNumber[od.Fields().Get(0).Number()]
fieldOffset := offsetOf(fs, x)
oi.which = func(p pointer) pref.FieldNumber {
if p.IsNil() {
return 0
}
rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
if rv.IsNil() { // valid on either *T or []byte
return 0
}
return od.Fields().Get(0).Number()
}
} else {
fs := si.oneofsByName[od.Name()]
fieldOffset := offsetOf(fs, x)
oi.which = func(p pointer) pref.FieldNumber {
if p.IsNil() {
return 0
}
@ -442,7 +459,8 @@ func makeOneofInfo(od pref.OneofDescriptor, fs reflect.StructField, x exporter,
if rv.IsNil() {
return 0
}
return wrappersByType[rv.Type().Elem()]
},
return si.oneofWrappersByType[rv.Type().Elem()]
}
}
return oi
}

View file

@ -114,7 +114,7 @@ func (m *messageState) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.
if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od {
return od.Fields().ByNumber(oi.which(m.pointer()))
}
panic("invalid oneof descriptor")
panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName()))
}
func (m *messageState) GetUnknown() protoreflect.RawFields {
m.messageInfo().init()
@ -234,7 +234,7 @@ func (m *messageReflectWrapper) WhichOneof(od protoreflect.OneofDescriptor) prot
if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od {
return od.Fields().ByNumber(oi.which(m.pointer()))
}
panic("invalid oneof descriptor")
panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName()))
}
func (m *messageReflectWrapper) GetUnknown() protoreflect.RawFields {
m.messageInfo().init()

View file

@ -148,7 +148,11 @@ func (ms *messageState) pointer() pointer {
return pointer{p: unsafe.Pointer(ms)}
}
func (ms *messageState) messageInfo() *MessageInfo {
return ms.LoadMessageInfo()
mi := ms.LoadMessageInfo()
if mi == nil {
panic("invalid nil message info; this suggests memory corruption due to a race or shallow copy on the message struct")
}
return mi
}
func (ms *messageState) LoadMessageInfo() *MessageInfo {
return (*MessageInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&ms.atomicMessageInfo))))

View file

@ -108,7 +108,7 @@ const (
func newFieldValidationInfo(mi *MessageInfo, si structInfo, fd pref.FieldDescriptor, ft reflect.Type) validationInfo {
var vi validationInfo
switch {
case fd.ContainingOneof() != nil:
case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
switch fd.Kind() {
case pref.MessageKind:
vi.typ = validationTypeMessage

View file

@ -5,9 +5,10 @@
package impl
import (
"reflect"
"fmt"
pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
)
// weakFields adds methods to the exported WeakFields type for internal use.
@ -16,31 +17,58 @@ import (
// defined directly on it.
type weakFields WeakFields
func (w *weakFields) get(num pref.FieldNumber) (_ pref.ProtoMessage, ok bool) {
if *w == nil {
return nil, false
}
m, ok := (*w)[int32(num)]
if !ok {
return nil, false
}
// As a legacy quirk, consider a typed nil to be unset.
//
// TODO: Consider fixing the generated set methods to clear the field
// when provided with a typed nil.
if v := reflect.ValueOf(m); v.Kind() == reflect.Ptr && v.IsNil() {
return nil, false
}
return Export{}.ProtoMessageV2Of(m), true
func (w weakFields) get(num pref.FieldNumber) (pref.ProtoMessage, bool) {
m, ok := w[int32(num)]
return m, ok
}
func (w *weakFields) set(num pref.FieldNumber, m pref.ProtoMessage) {
if *w == nil {
*w = make(weakFields)
}
(*w)[int32(num)] = Export{}.ProtoMessageV1Of(m)
(*w)[int32(num)] = m
}
func (w *weakFields) clear(num pref.FieldNumber) {
delete(*w, int32(num))
}
func (Export) HasWeak(w WeakFields, num pref.FieldNumber) bool {
_, ok := w[int32(num)]
return ok
}
func (Export) ClearWeak(w *WeakFields, num pref.FieldNumber) {
delete(*w, int32(num))
}
func (Export) GetWeak(w WeakFields, num pref.FieldNumber, name pref.FullName) pref.ProtoMessage {
if m, ok := w[int32(num)]; ok {
return m
}
mt, _ := protoregistry.GlobalTypes.FindMessageByName(name)
if mt == nil {
panic(fmt.Sprintf("message %v for weak field is not linked in", name))
}
return mt.Zero().Interface()
}
func (Export) SetWeak(w *WeakFields, num pref.FieldNumber, name pref.FullName, m pref.ProtoMessage) {
if m != nil {
mt, _ := protoregistry.GlobalTypes.FindMessageByName(name)
if mt == nil {
panic(fmt.Sprintf("message %v for weak field is not linked in", name))
}
if mt != m.ProtoReflect().Type() {
panic(fmt.Sprintf("invalid message type for weak field: got %T, want %T", m, mt.Zero().Interface()))
}
}
if m == nil || !m.ProtoReflect().IsValid() {
delete(*w, int32(num))
return
}
if *w == nil {
*w = make(weakFields)
}
(*w)[int32(num)] = m
}

View file

@ -52,7 +52,7 @@ import (
// 10. Send out the CL for review and submit it.
const (
Major = 1
Minor = 21
Minor = 23
Patch = 0
PreRelease = ""
)

View file

@ -12,6 +12,12 @@ import (
// CheckInitialized returns an error if any required fields in m are not set.
func CheckInitialized(m Message) error {
// Treat a nil message interface as an "untyped" empty message,
// which we assume to have no required fields.
if m == nil {
return nil
}
return checkInitialized(m.ProtoReflect())
}

View file

@ -74,19 +74,54 @@ type MarshalOptions struct {
// Marshal returns the wire-format encoding of m.
func Marshal(m Message) ([]byte, error) {
// Treat nil message interface as an empty message; nothing to output.
if m == nil {
return nil, nil
}
out, err := MarshalOptions{}.marshal(nil, m.ProtoReflect())
if len(out.Buf) == 0 && err == nil {
out.Buf = emptyBytesForMessage(m)
}
return out.Buf, err
}
// Marshal returns the wire-format encoding of m.
func (o MarshalOptions) Marshal(m Message) ([]byte, error) {
// Treat nil message interface as an empty message; nothing to output.
if m == nil {
return nil, nil
}
out, err := o.marshal(nil, m.ProtoReflect())
if len(out.Buf) == 0 && err == nil {
out.Buf = emptyBytesForMessage(m)
}
return out.Buf, err
}
// emptyBytesForMessage returns a nil buffer if and only if m is invalid,
// otherwise it returns a non-nil empty buffer.
//
// This is to assist the edge-case where user-code does the following:
// m1.OptionalBytes, _ = proto.Marshal(m2)
// where they expect the proto2 "optional_bytes" field to be populated
// if any only if m2 is a valid message.
func emptyBytesForMessage(m Message) []byte {
if m == nil || !m.ProtoReflect().IsValid() {
return nil
}
return emptyBuf[:]
}
// MarshalAppend appends the wire-format encoding of m to b,
// returning the result.
func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) {
// Treat nil message interface as an empty message; nothing to append.
if m == nil {
return b, nil
}
out, err := o.marshal(b, m.ProtoReflect())
return out.Buf, err
}

View file

@ -9,28 +9,84 @@ import (
)
// HasExtension reports whether an extension field is populated.
// It panics if ext does not extend m.
func HasExtension(m Message, ext protoreflect.ExtensionType) bool {
return m.ProtoReflect().Has(ext.TypeDescriptor())
// It returns false if m is invalid or if xt does not extend m.
func HasExtension(m Message, xt protoreflect.ExtensionType) bool {
// Treat nil message interface as an empty message; no populated fields.
if m == nil {
return false
}
// As a special-case, we reports invalid or mismatching descriptors
// as always not being populated (since they aren't).
if xt == nil || m.ProtoReflect().Descriptor() != xt.TypeDescriptor().ContainingMessage() {
return false
}
return m.ProtoReflect().Has(xt.TypeDescriptor())
}
// ClearExtension clears an extension field such that subsequent
// HasExtension calls return false.
// It panics if ext does not extend m.
func ClearExtension(m Message, ext protoreflect.ExtensionType) {
m.ProtoReflect().Clear(ext.TypeDescriptor())
// It panics if m is invalid or if xt does not extend m.
func ClearExtension(m Message, xt protoreflect.ExtensionType) {
m.ProtoReflect().Clear(xt.TypeDescriptor())
}
// GetExtension retrieves the value for an extension field.
// If the field is unpopulated, it returns the default value for
// scalars and an immutable, empty value for lists, maps, or messages.
// It panics if ext does not extend m.
func GetExtension(m Message, ext protoreflect.ExtensionType) interface{} {
return ext.InterfaceOf(m.ProtoReflect().Get(ext.TypeDescriptor()))
// scalars and an immutable, empty value for lists or messages.
// It panics if xt does not extend m.
func GetExtension(m Message, xt protoreflect.ExtensionType) interface{} {
// Treat nil message interface as an empty message; return the default.
if m == nil {
return xt.InterfaceOf(xt.Zero())
}
return xt.InterfaceOf(m.ProtoReflect().Get(xt.TypeDescriptor()))
}
// SetExtension stores the value of an extension field.
// It panics if ext does not extend m or if value type is invalid for the field.
func SetExtension(m Message, ext protoreflect.ExtensionType, value interface{}) {
m.ProtoReflect().Set(ext.TypeDescriptor(), ext.ValueOf(value))
// It panics if m is invalid, xt does not extend m, or if type of v
// is invalid for the specified extension field.
func SetExtension(m Message, xt protoreflect.ExtensionType, v interface{}) {
xd := xt.TypeDescriptor()
pv := xt.ValueOf(v)
// Specially treat an invalid list, map, or message as clear.
isValid := true
switch {
case xd.IsList():
isValid = pv.List().IsValid()
case xd.IsMap():
isValid = pv.Map().IsValid()
case xd.Message() != nil:
isValid = pv.Message().IsValid()
}
if !isValid {
m.ProtoReflect().Clear(xd)
return
}
m.ProtoReflect().Set(xd, pv)
}
// RangeExtensions iterates over every populated extension field in m in an
// undefined order, calling f for each extension type and value encountered.
// It returns immediately if f returns false.
// While iterating, mutating operations may only be performed
// on the current extension field.
func RangeExtensions(m Message, f func(protoreflect.ExtensionType, interface{}) bool) {
// Treat nil message interface as an empty message; nothing to range over.
if m == nil {
return
}
m.ProtoReflect().Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
if fd.IsExtension() {
xt := fd.(protoreflect.ExtensionTypeDescriptor).Type()
vi := xt.InterfaceOf(v)
return f(xt, vi)
}
return true
})
}

View file

@ -5,6 +5,8 @@
package proto
import (
"fmt"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoiface"
)
@ -21,8 +23,14 @@ import (
// It is semantically equivalent to unmarshaling the encoded form of src
// into dst with the UnmarshalOptions.Merge option specified.
func Merge(dst, src Message) {
// TODO: Should nil src be treated as semantically equivalent to a
// untyped, read-only, empty message? What about a nil dst?
dstMsg, srcMsg := dst.ProtoReflect(), src.ProtoReflect()
if dstMsg.Descriptor() != srcMsg.Descriptor() {
if got, want := dstMsg.Descriptor().FullName(), srcMsg.Descriptor().FullName(); got != want {
panic(fmt.Sprintf("descriptor mismatch: %v != %v", got, want))
}
panic("descriptor mismatch")
}
mergeOptions{}.mergeMessage(dstMsg, srcMsg)
@ -69,7 +77,7 @@ func (o mergeOptions) mergeMessage(dst, src protoreflect.Message) {
}
if !dst.IsValid() {
panic("cannot merge into invalid destination message")
panic(fmt.Sprintf("cannot merge into invalid %v message", dst.Descriptor().FullName()))
}
src.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {

View file

@ -4,7 +4,11 @@
package proto
import "google.golang.org/protobuf/reflect/protoreflect"
import (
"fmt"
"google.golang.org/protobuf/reflect/protoreflect"
)
// Reset clears every field in the message.
// The resulting message shares no observable memory with its previous state
@ -19,7 +23,7 @@ func Reset(m Message) {
func resetMessage(m protoreflect.Message) {
if !m.IsValid() {
panic("cannot reset invalid message")
panic(fmt.Sprintf("cannot reset invalid %v message", m.Descriptor().FullName()))
}
// Clear all known fields.

View file

@ -18,6 +18,11 @@ func Size(m Message) int {
// Size returns the size in bytes of the wire-format encoding of m.
func (o MarshalOptions) Size(m Message) int {
// Treat a nil message interface as an empty message; nothing to output.
if m == nil {
return 0
}
return sizeMessage(m.ProtoReflect())
}

View file

@ -22,8 +22,9 @@
//
// The protobuf descriptor interfaces are not meant to be implemented by
// user code since they might need to be extended in the future to support
// additions to the protobuf language. Protobuf descriptors can be constructed
// using the "google.golang.org/protobuf/reflect/protodesc" package.
// additions to the protobuf language.
// The "google.golang.org/protobuf/reflect/protodesc" package converts between
// google.protobuf.DescriptorProto messages and protobuf descriptors.
//
//
// Go Type Descriptors

View file

@ -281,11 +281,19 @@ type FieldDescriptor interface {
// It is usually the camel-cased form of the field name.
JSONName() string
// HasPresence reports whether the field distinguishes between unpopulated
// and default values.
HasPresence() bool
// IsExtension reports whether this is an extension field. If false,
// then Parent and ContainingMessage refer to the same message.
// Otherwise, ContainingMessage and Parent likely differ.
IsExtension() bool
// HasOptionalKeyword reports whether the "optional" keyword was explicitly
// specified in the source .proto file.
HasOptionalKeyword() bool
// IsWeak reports whether this is a weak field, which does not impose a
// direct dependency on the target type.
// If true, then Message returns a placeholder type.
@ -375,6 +383,11 @@ type FieldDescriptors interface {
type OneofDescriptor interface {
Descriptor
// IsSynthetic reports whether this is a synthetic oneof created to support
// proto3 optional semantics. If true, Fields contains exactly one field
// with HasOptionalKeyword specified.
IsSynthetic() bool
// Fields is a list of fields belonging to this oneof.
Fields() FieldDescriptors

View file

@ -114,8 +114,8 @@ type Message interface {
// Mutable is a mutating operation and unsafe for concurrent use.
Mutable(FieldDescriptor) Value
// NewField returns a new value for assignable to the field of a given descriptor.
// For scalars, this returns the default value.
// NewField returns a new value that is assignable to the field
// for the given descriptor. For scalars, this returns the default value.
// For lists, maps, and messages, this returns a new, empty, mutable value.
NewField(FieldDescriptor) Value

View file

@ -7,7 +7,6 @@ package protoreflect
import (
"fmt"
"math"
"reflect"
)
// Value is a union where only one Go type may be set at a time.
@ -87,7 +86,7 @@ func ValueOf(v interface{}) Value {
case Message, List, Map:
return valueOfIface(v)
default:
panic(fmt.Sprintf("invalid type: %v", reflect.TypeOf(v)))
panic(fmt.Sprintf("invalid type: %T", v))
}
}
@ -197,13 +196,55 @@ func (v Value) Interface() interface{} {
}
}
func (v Value) typeName() string {
switch v.typ {
case nilType:
return "nil"
case boolType:
return "bool"
case int32Type:
return "int32"
case int64Type:
return "int64"
case uint32Type:
return "uint32"
case uint64Type:
return "uint64"
case float32Type:
return "float32"
case float64Type:
return "float64"
case stringType:
return "string"
case bytesType:
return "bytes"
case enumType:
return "enum"
default:
switch v := v.getIface().(type) {
case Message:
return "message"
case List:
return "list"
case Map:
return "map"
default:
return fmt.Sprintf("<unknown: %T>", v)
}
}
}
func (v Value) panicMessage(what string) string {
return fmt.Sprintf("type mismatch: cannot convert %v to %s", v.typeName(), what)
}
// Bool returns v as a bool and panics if the type is not a bool.
func (v Value) Bool() bool {
switch v.typ {
case boolType:
return v.num > 0
default:
panic("proto: value type mismatch")
panic(v.panicMessage("bool"))
}
}
@ -213,7 +254,7 @@ func (v Value) Int() int64 {
case int32Type, int64Type:
return int64(v.num)
default:
panic("proto: value type mismatch")
panic(v.panicMessage("int"))
}
}
@ -223,7 +264,7 @@ func (v Value) Uint() uint64 {
case uint32Type, uint64Type:
return uint64(v.num)
default:
panic("proto: value type mismatch")
panic(v.panicMessage("uint"))
}
}
@ -233,7 +274,7 @@ func (v Value) Float() float64 {
case float32Type, float64Type:
return math.Float64frombits(uint64(v.num))
default:
panic("proto: value type mismatch")
panic(v.panicMessage("float"))
}
}
@ -254,7 +295,7 @@ func (v Value) Bytes() []byte {
case bytesType:
return v.getBytes()
default:
panic("proto: value type mismatch")
panic(v.panicMessage("bytes"))
}
}
@ -264,37 +305,37 @@ func (v Value) Enum() EnumNumber {
case enumType:
return EnumNumber(v.num)
default:
panic("proto: value type mismatch")
panic(v.panicMessage("enum"))
}
}
// Message returns v as a Message and panics if the type is not a Message.
func (v Value) Message() Message {
switch v := v.getIface().(type) {
switch vi := v.getIface().(type) {
case Message:
return v
return vi
default:
panic("proto: value type mismatch")
panic(v.panicMessage("message"))
}
}
// List returns v as a List and panics if the type is not a List.
func (v Value) List() List {
switch v := v.getIface().(type) {
switch vi := v.getIface().(type) {
case List:
return v
return vi
default:
panic("proto: value type mismatch")
panic(v.panicMessage("list"))
}
}
// Map returns v as a Map and panics if the type is not a Map.
func (v Value) Map() Map {
switch v := v.getIface().(type) {
switch vi := v.getIface().(type) {
case Map:
return v
return vi
default:
panic("proto: value type mismatch")
panic(v.panicMessage("map"))
}
}
@ -303,8 +344,9 @@ func (v Value) MapKey() MapKey {
switch v.typ {
case boolType, int32Type, int64Type, uint32Type, uint64Type, stringType:
return MapKey(v)
default:
panic(v.panicMessage("map key"))
}
panic("proto: invalid map key type")
}
// MapKey is used to index maps, where the Go type of the MapKey must match

1
vendor/gopkg.in/yaml.v2/apic.go generated vendored
View file

@ -86,6 +86,7 @@ func yaml_emitter_initialize(emitter *yaml_emitter_t) {
raw_buffer: make([]byte, 0, output_raw_buffer_size),
states: make([]yaml_emitter_state_t, 0, initial_stack_size),
events: make([]yaml_event_t, 0, initial_queue_size),
best_width: -1,
}
}

13
vendor/modules.txt vendored
View file

@ -89,7 +89,7 @@ github.com/davecgh/go-spew/spew
# github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible
## explicit
github.com/dgrijalva/jwt-go
# github.com/digitalocean/godo v1.35.1
# github.com/digitalocean/godo v1.36.0
## explicit
github.com/digitalocean/godo
# github.com/dimchansky/utfbom v1.1.0
@ -130,7 +130,7 @@ github.com/gobwas/glob/util/runes
github.com/gobwas/glob/util/strings
# github.com/gofrs/uuid v3.2.0+incompatible
github.com/gofrs/uuid
# github.com/golang/protobuf v1.4.0
# github.com/golang/protobuf v1.4.2
## explicit
github.com/golang/protobuf/proto
github.com/golang/protobuf/ptypes
@ -318,7 +318,7 @@ golang.org/x/crypto/pkcs12/internal/rc2
# golang.org/x/mod v0.2.0
golang.org/x/mod/module
golang.org/x/mod/semver
# golang.org/x/net v0.0.0-20200421231249-e086a090c8fd
# golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2
## explicit
golang.org/x/net/bpf
golang.org/x/net/context
@ -383,7 +383,8 @@ google.golang.org/api/option/internaloption
google.golang.org/api/transport/cert
google.golang.org/api/transport/http
google.golang.org/api/transport/http/internal/propagation
# google.golang.org/appengine v1.6.5
# google.golang.org/appengine v1.6.6
## explicit
google.golang.org/appengine
google.golang.org/appengine/internal
google.golang.org/appengine/internal/app_identity
@ -433,7 +434,7 @@ google.golang.org/grpc/serviceconfig
google.golang.org/grpc/stats
google.golang.org/grpc/status
google.golang.org/grpc/tap
# google.golang.org/protobuf v1.21.0
# google.golang.org/protobuf v1.23.0
google.golang.org/protobuf/encoding/prototext
google.golang.org/protobuf/encoding/protowire
google.golang.org/protobuf/internal/descfmt
@ -484,6 +485,6 @@ gopkg.in/square/go-jose.v2
gopkg.in/square/go-jose.v2/cipher
gopkg.in/square/go-jose.v2/json
gopkg.in/square/go-jose.v2/jwt
# gopkg.in/yaml.v2 v2.2.8
# gopkg.in/yaml.v2 v2.3.0
## explicit
gopkg.in/yaml.v2