Bump "safe" dependencies (#19)

* github.com/gogo/protobuf: v1.1.1 -> v1.2.0

Signed-off-by: Vincent Demeester <vdemeest@redhat.com>

* github.com/spf13/pflag: v1.0.2 -> v1.0.3

Signed-off-by: Vincent Demeester <vdemeest@redhat.com>

* gopkg.in/yaml.v2: v2.2.1 -> v2.2.2

Signed-off-by: Vincent Demeester <vdemeest@redhat.com>
This commit is contained in:
Vincent Demeester 2018-12-27 18:48:37 +01:00 committed by Knative Prow Robot
parent 6be7c335a2
commit 5e0d1e671f
16 changed files with 2963 additions and 143 deletions

18
Gopkg.lock generated
View File

@ -18,15 +18,15 @@
version = "v1.0.0" version = "v1.0.0"
[[projects]] [[projects]]
digest = "1:8679b8a64f3613e9749c5640c3535c83399b8e69f67ce54d91dc73f6d77373af" digest = "1:abea725bcf0210887f5da19d804fffa1dd45a42a56bdf5f02322345e3fee4f0d"
name = "github.com/gogo/protobuf" name = "github.com/gogo/protobuf"
packages = [ packages = [
"proto", "proto",
"sortkeys", "sortkeys",
] ]
pruneopts = "NUT" pruneopts = "NUT"
revision = "636bf0302bc95575d69441b25a2603156ffdddf1" revision = "4cbf7e384e768b4e01799441fdf2a706a5635ae7"
version = "v1.1.1" version = "v1.2.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -172,12 +172,12 @@
version = "v2.0.1" version = "v2.0.1"
[[projects]] [[projects]]
digest = "1:e3707aeaccd2adc89eba6c062fec72116fe1fc1ba71097da85b4d8ae1668a675" digest = "1:9d8420bbf131d1618bde6530af37c3799340d3762cc47210c1d9532a4c3a2779"
name = "github.com/spf13/pflag" name = "github.com/spf13/pflag"
packages = ["."] packages = ["."]
pruneopts = "NUT" pruneopts = "NUT"
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
version = "v1.0.2" version = "v1.0.3"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -264,12 +264,12 @@
version = "v0.9.1" version = "v0.9.1"
[[projects]] [[projects]]
digest = "1:7c95b35057a0ff2e19f707173cc1a947fa43a6eb5c4d300d196ece0334046082" digest = "1:18108594151654e9e696b27b181b953f9a90b16bf14d253dd1b397b025a1487f"
name = "gopkg.in/yaml.v2" name = "gopkg.in/yaml.v2"
packages = ["."] packages = ["."]
pruneopts = "NUT" pruneopts = "NUT"
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" revision = "51d6538a90f86fe93ac480b35f37b2be17fef232"
version = "v2.2.1" version = "v2.2.2"
[[projects]] [[projects]]
digest = "1:8960ef753a87391086a307122d23cd5007cee93c28189437e4f1b6ed72bffc50" digest = "1:8960ef753a87391086a307122d23cd5007cee93c28189437e4f1b6ed72bffc50"

View File

@ -1,7 +1,6 @@
Protocol Buffers for Go with Gadgets
Copyright (c) 2013, The GoGo Authors. All rights reserved. Copyright (c) 2013, The GoGo Authors. All rights reserved.
http://github.com/gogo/protobuf
Protocol Buffers for Go with Gadgets
Go support for Protocol Buffers - Google's data interchange format Go support for Protocol Buffers - Google's data interchange format

View File

@ -37,27 +37,9 @@ package proto
import ( import (
"errors" "errors"
"fmt"
"reflect" "reflect"
) )
// RequiredNotSetError is the error returned if Marshal is called with
// a protocol buffer struct whose required fields have not
// all been initialized. It is also the error returned if Unmarshal is
// called with an encoded protocol buffer that does not include all the
// required fields.
//
// When printed, RequiredNotSetError reports the first unset required field in a
// message. If the field cannot be precisely determined, it is reported as
// "{Unknown}".
type RequiredNotSetError struct {
field string
}
func (e *RequiredNotSetError) Error() string {
return fmt.Sprintf("proto: required field %q not set", e.field)
}
var ( var (
// errRepeatedHasNil is the error returned if Marshal is called with // errRepeatedHasNil is the error returned if Marshal is called with
// a struct with a repeated field containing a nil element. // a struct with a repeated field containing a nil element.

View File

@ -265,7 +265,6 @@ package proto
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"log" "log"
"reflect" "reflect"
@ -274,7 +273,66 @@ import (
"sync" "sync"
) )
var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string") // RequiredNotSetError is an error type returned by either Marshal or Unmarshal.
// Marshal reports this when a required field is not initialized.
// Unmarshal reports this when a required field is missing from the wire data.
type RequiredNotSetError struct{ field string }
func (e *RequiredNotSetError) Error() string {
if e.field == "" {
return fmt.Sprintf("proto: required field not set")
}
return fmt.Sprintf("proto: required field %q not set", e.field)
}
func (e *RequiredNotSetError) RequiredNotSet() bool {
return true
}
type invalidUTF8Error struct{ field string }
func (e *invalidUTF8Error) Error() string {
if e.field == "" {
return "proto: invalid UTF-8 detected"
}
return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field)
}
func (e *invalidUTF8Error) InvalidUTF8() bool {
return true
}
// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8.
// This error should not be exposed to the external API as such errors should
// be recreated with the field information.
var errInvalidUTF8 = &invalidUTF8Error{}
// isNonFatal reports whether the error is either a RequiredNotSet error
// or a InvalidUTF8 error.
func isNonFatal(err error) bool {
if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() {
return true
}
if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() {
return true
}
return false
}
type nonFatal struct{ E error }
// Merge merges err into nf and reports whether it was successful.
// Otherwise it returns false for any fatal non-nil errors.
func (nf *nonFatal) Merge(err error) (ok bool) {
if err == nil {
return true // not an error
}
if !isNonFatal(err) {
return false // fatal error
}
if nf.E == nil {
nf.E = err // store first instance of non-fatal error
}
return true
}
// Message is implemented by generated protocol buffer messages. // Message is implemented by generated protocol buffer messages.
type Message interface { type Message interface {
@ -570,9 +628,11 @@ func SetDefaults(pb Message) {
setDefaults(reflect.ValueOf(pb), true, false) setDefaults(reflect.ValueOf(pb), true, false)
} }
// v is a pointer to a struct. // v is a struct.
func setDefaults(v reflect.Value, recur, zeros bool) { func setDefaults(v reflect.Value, recur, zeros bool) {
if v.Kind() == reflect.Ptr {
v = v.Elem() v = v.Elem()
}
defaultMu.RLock() defaultMu.RLock()
dm, ok := defaults[v.Type()] dm, ok := defaults[v.Type()]
@ -674,8 +734,11 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
for _, ni := range dm.nested { for _, ni := range dm.nested {
f := v.Field(ni) f := v.Field(ni)
// f is *T or []*T or map[T]*T // f is *T or T or []*T or []T
switch f.Kind() { switch f.Kind() {
case reflect.Struct:
setDefaults(f, recur, zeros)
case reflect.Ptr: case reflect.Ptr:
if f.IsNil() { if f.IsNil() {
continue continue
@ -685,7 +748,7 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
case reflect.Slice: case reflect.Slice:
for i := 0; i < f.Len(); i++ { for i := 0; i < f.Len(); i++ {
e := f.Index(i) e := f.Index(i)
if e.IsNil() { if e.Kind() == reflect.Ptr && e.IsNil() {
continue continue
} }
setDefaults(e, recur, zeros) setDefaults(e, recur, zeros)
@ -757,6 +820,9 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) { func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
var canHaveDefault bool var canHaveDefault bool
switch ft.Kind() { switch ft.Kind() {
case reflect.Struct:
nestedMessage = true // non-nullable
case reflect.Ptr: case reflect.Ptr:
if ft.Elem().Kind() == reflect.Struct { if ft.Elem().Kind() == reflect.Struct {
nestedMessage = true nestedMessage = true
@ -766,7 +832,7 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes
case reflect.Slice: case reflect.Slice:
switch ft.Elem().Kind() { switch ft.Elem().Kind() {
case reflect.Ptr: case reflect.Ptr, reflect.Struct:
nestedMessage = true // repeated message nestedMessage = true // repeated message
case reflect.Uint8: case reflect.Uint8:
canHaveDefault = true // bytes field canHaveDefault = true // bytes field

View File

@ -26,7 +26,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build !purego !appengine,!js // +build !purego,!appengine,!js
// This file contains the implementation of the proto field accesses using package unsafe. // This file contains the implementation of the proto field accesses using package unsafe.

View File

@ -144,7 +144,7 @@ type Properties struct {
Repeated bool Repeated bool
Packed bool // relevant for repeated primitives only Packed bool // relevant for repeated primitives only
Enum string // set for enum types only Enum string // set for enum types only
proto3 bool // whether this is known to be a proto3 field; set for []byte only proto3 bool // whether this is known to be a proto3 field
oneof bool // whether this is a oneof field oneof bool // whether this is a oneof field
Default string // default value Default string // default value
@ -153,14 +153,15 @@ type Properties struct {
CastType string CastType string
StdTime bool StdTime bool
StdDuration bool StdDuration bool
WktPointer bool
stype reflect.Type // set for struct types only stype reflect.Type // set for struct types only
ctype reflect.Type // set for custom types only ctype reflect.Type // set for custom types only
sprop *StructProperties // set for struct types only sprop *StructProperties // set for struct types only
mtype reflect.Type // set for map types only mtype reflect.Type // set for map types only
mkeyprop *Properties // set for map types only MapKeyProp *Properties // set for map types only
mvalprop *Properties // set for map types only MapValProp *Properties // set for map types only
} }
// String formats the properties in the protobuf struct field tag style. // String formats the properties in the protobuf struct field tag style.
@ -274,6 +275,8 @@ outer:
p.StdTime = true p.StdTime = true
case f == "stdduration": case f == "stdduration":
p.StdDuration = true p.StdDuration = true
case f == "wktptr":
p.WktPointer = true
} }
} }
} }
@ -296,6 +299,10 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
p.setTag(lockGetProp) p.setTag(lockGetProp)
return return
} }
if p.WktPointer && !isMap {
p.setTag(lockGetProp)
return
}
switch t1 := typ; t1.Kind() { switch t1 := typ; t1.Kind() {
case reflect.Struct: case reflect.Struct:
p.stype = typ p.stype = typ
@ -317,9 +324,9 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
case reflect.Map: case reflect.Map:
p.mtype = t1 p.mtype = t1
p.mkeyprop = &Properties{} p.MapKeyProp = &Properties{}
p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
p.mvalprop = &Properties{} p.MapValProp = &Properties{}
vtype := p.mtype.Elem() vtype := p.mtype.Elem()
if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
// The value type is not a message (*T) or bytes ([]byte), // The value type is not a message (*T) or bytes ([]byte),
@ -327,10 +334,11 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
vtype = reflect.PtrTo(vtype) vtype = reflect.PtrTo(vtype)
} }
p.mvalprop.CustomType = p.CustomType p.MapValProp.CustomType = p.CustomType
p.mvalprop.StdDuration = p.StdDuration p.MapValProp.StdDuration = p.StdDuration
p.mvalprop.StdTime = p.StdTime p.MapValProp.StdTime = p.StdTime
p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) p.MapValProp.WktPointer = p.WktPointer
p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
} }
p.setTag(lockGetProp) p.setTag(lockGetProp)
} }

View File

@ -97,6 +97,8 @@ type marshalElemInfo struct {
var ( var (
marshalInfoMap = map[reflect.Type]*marshalInfo{} marshalInfoMap = map[reflect.Type]*marshalInfo{}
marshalInfoLock sync.Mutex marshalInfoLock sync.Mutex
uint8SliceType = reflect.TypeOf(([]uint8)(nil)).Kind()
) )
// getMarshalInfo returns the information to marshal a given type of message. // getMarshalInfo returns the information to marshal a given type of message.
@ -246,16 +248,13 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
// If the message can marshal itself, let it do it, for compatibility. // If the message can marshal itself, let it do it, for compatibility.
// NOTE: This is not efficient. // NOTE: This is not efficient.
if u.hasmarshaler { if u.hasmarshaler {
if deterministic {
return nil, errors.New("proto: deterministic not supported by the Marshal method of " + u.typ.String())
}
m := ptr.asPointerTo(u.typ).Interface().(Marshaler) m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
b1, err := m.Marshal() b1, err := m.Marshal()
b = append(b, b1...) b = append(b, b1...)
return b, err return b, err
} }
var err, errreq error var err, errLater error
// The old marshaler encodes extensions at beginning. // The old marshaler encodes extensions at beginning.
if u.extensions.IsValid() { if u.extensions.IsValid() {
e := ptr.offset(u.extensions).toExtensions() e := ptr.offset(u.extensions).toExtensions()
@ -280,11 +279,13 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
b = append(b, s...) b = append(b, s...)
} }
for _, f := range u.fields { for _, f := range u.fields {
if f.required && errreq == nil { if f.required {
if ptr.offset(f.field).getPointer().isNil() { if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
// Required field is not set. // Required field is not set.
// We record the error but keep going, to give a complete marshaling. // We record the error but keep going, to give a complete marshaling.
errreq = &RequiredNotSetError{f.name} if errLater == nil {
errLater = &RequiredNotSetError{f.name}
}
continue continue
} }
} }
@ -297,14 +298,21 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
if err1, ok := err.(*RequiredNotSetError); ok { if err1, ok := err.(*RequiredNotSetError); ok {
// Required field in submessage is not set. // Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling. // We record the error but keep going, to give a complete marshaling.
if errreq == nil { if errLater == nil {
errreq = &RequiredNotSetError{f.name + "." + err1.field} errLater = &RequiredNotSetError{f.name + "." + err1.field}
} }
continue continue
} }
if err == errRepeatedHasNil { if err == errRepeatedHasNil {
err = errors.New("proto: repeated field " + f.name + " has nil element") err = errors.New("proto: repeated field " + f.name + " has nil element")
} }
if err == errInvalidUTF8 {
if errLater == nil {
fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
errLater = &invalidUTF8Error{fullName}
}
continue
}
return b, err return b, err
} }
} }
@ -312,7 +320,7 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
s := *ptr.offset(u.unrecognized).toBytes() s := *ptr.offset(u.unrecognized).toBytes()
b = append(b, s...) b = append(b, s...)
} }
return b, errreq return b, errLater
} }
// computeMarshalInfo initializes the marshal info. // computeMarshalInfo initializes the marshal info.
@ -577,6 +585,8 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
ctype := false ctype := false
isTime := false isTime := false
isDuration := false isDuration := false
isWktPointer := false
validateUTF8 := true
for i := 2; i < len(tags); i++ { for i := 2; i < len(tags); i++ {
if tags[i] == "packed" { if tags[i] == "packed" {
packed = true packed = true
@ -593,7 +603,11 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
if tags[i] == "stdduration" { if tags[i] == "stdduration" {
isDuration = true isDuration = true
} }
if tags[i] == "wktptr" {
isWktPointer = true
} }
}
validateUTF8 = validateUTF8 && proto3
if !proto3 && !pointer && !slice { if !proto3 && !pointer && !slice {
nozero = false nozero = false
} }
@ -638,6 +652,112 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
return makeDurationMarshaler(getMarshalInfo(t)) return makeDurationMarshaler(getMarshalInfo(t))
} }
if isWktPointer {
switch t.Kind() {
case reflect.Float64:
if pointer {
if slice {
return makeStdDoubleValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdDoubleValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdDoubleValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdDoubleValueMarshaler(getMarshalInfo(t))
case reflect.Float32:
if pointer {
if slice {
return makeStdFloatValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdFloatValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdFloatValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdFloatValueMarshaler(getMarshalInfo(t))
case reflect.Int64:
if pointer {
if slice {
return makeStdInt64ValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdInt64ValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdInt64ValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdInt64ValueMarshaler(getMarshalInfo(t))
case reflect.Uint64:
if pointer {
if slice {
return makeStdUInt64ValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdUInt64ValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdUInt64ValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdUInt64ValueMarshaler(getMarshalInfo(t))
case reflect.Int32:
if pointer {
if slice {
return makeStdInt32ValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdInt32ValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdInt32ValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdInt32ValueMarshaler(getMarshalInfo(t))
case reflect.Uint32:
if pointer {
if slice {
return makeStdUInt32ValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdUInt32ValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdUInt32ValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdUInt32ValueMarshaler(getMarshalInfo(t))
case reflect.Bool:
if pointer {
if slice {
return makeStdBoolValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdBoolValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdBoolValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdBoolValueMarshaler(getMarshalInfo(t))
case reflect.String:
if pointer {
if slice {
return makeStdStringValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdStringValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdStringValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdStringValueMarshaler(getMarshalInfo(t))
case uint8SliceType:
if pointer {
if slice {
return makeStdBytesValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdBytesValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdBytesValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdBytesValueMarshaler(getMarshalInfo(t))
default:
panic(fmt.Sprintf("unknown wktpointer type %#v", t))
}
}
switch t.Kind() { switch t.Kind() {
case reflect.Bool: case reflect.Bool:
if pointer { if pointer {
@ -834,6 +954,18 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
} }
return sizeFloat64Value, appendFloat64Value return sizeFloat64Value, appendFloat64Value
case reflect.String: case reflect.String:
if validateUTF8 {
if pointer {
return sizeStringPtr, appendUTF8StringPtr
}
if slice {
return sizeStringSlice, appendUTF8StringSlice
}
if nozero {
return sizeStringValueNoZero, appendUTF8StringValueNoZero
}
return sizeStringValue, appendUTF8StringValue
}
if pointer { if pointer {
return sizeStringPtr, appendStringPtr return sizeStringPtr, appendStringPtr
} }
@ -2090,9 +2222,6 @@ func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byt
} }
func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
v := *ptr.toString() v := *ptr.toString()
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag) b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v))) b = appendVarint(b, uint64(len(v)))
b = append(b, v...) b = append(b, v...)
@ -2103,9 +2232,6 @@ func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]b
if v == "" { if v == "" {
return b, nil return b, nil
} }
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag) b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v))) b = appendVarint(b, uint64(len(v)))
b = append(b, v...) b = append(b, v...)
@ -2117,9 +2243,6 @@ func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, err
return b, nil return b, nil
} }
v := *p v := *p
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag) b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v))) b = appendVarint(b, uint64(len(v)))
b = append(b, v...) b = append(b, v...)
@ -2128,12 +2251,74 @@ func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, err
func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
s := *ptr.toStringSlice() s := *ptr.toStringSlice()
for _, v := range s { for _, v := range s {
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
}
return b, nil
}
func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
v := *ptr.toString()
if !utf8.ValidString(v) { if !utf8.ValidString(v) {
return nil, errInvalidUTF8 invalidUTF8 = true
} }
b = appendVarint(b, wiretag) b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v))) b = appendVarint(b, uint64(len(v)))
b = append(b, v...) b = append(b, v...)
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
v := *ptr.toString()
if v == "" {
return b, nil
}
if !utf8.ValidString(v) {
invalidUTF8 = true
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
p := *ptr.toStringPtr()
if p == nil {
return b, nil
}
v := *p
if !utf8.ValidString(v) {
invalidUTF8 = true
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
s := *ptr.toStringSlice()
for _, v := range s {
if !utf8.ValidString(v) {
invalidUTF8 = true
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
}
if invalidUTF8 {
return b, errInvalidUTF8
} }
return b, nil return b, nil
} }
@ -2213,7 +2398,8 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
}, },
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getPointerSlice() s := ptr.getPointerSlice()
var err, errreq error var err error
var nerr nonFatal
for _, v := range s { for _, v := range s {
if v.isNil() { if v.isNil() {
return b, errRepeatedHasNil return b, errRepeatedHasNil
@ -2221,22 +2407,14 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
b = appendVarint(b, wiretag) // start group b = appendVarint(b, wiretag) // start group
b, err = u.marshal(b, v, deterministic) b, err = u.marshal(b, v, deterministic)
b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
if err != nil { if !nerr.Merge(err) {
if _, ok := err.(*RequiredNotSetError); ok {
// Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling.
if errreq == nil {
errreq = err
}
continue
}
if err == ErrNil { if err == ErrNil {
err = errRepeatedHasNil err = errRepeatedHasNil
} }
return b, err return b, err
} }
} }
return b, errreq return b, nerr.E
} }
} }
@ -2280,7 +2458,8 @@ func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
}, },
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getPointerSlice() s := ptr.getPointerSlice()
var err, errreq error var err error
var nerr nonFatal
for _, v := range s { for _, v := range s {
if v.isNil() { if v.isNil() {
return b, errRepeatedHasNil return b, errRepeatedHasNil
@ -2289,22 +2468,15 @@ func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
siz := u.cachedsize(v) siz := u.cachedsize(v)
b = appendVarint(b, uint64(siz)) b = appendVarint(b, uint64(siz))
b, err = u.marshal(b, v, deterministic) b, err = u.marshal(b, v, deterministic)
if err != nil {
if _, ok := err.(*RequiredNotSetError); ok { if !nerr.Merge(err) {
// Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling.
if errreq == nil {
errreq = err
}
continue
}
if err == ErrNil { if err == ErrNil {
err = errRepeatedHasNil err = errRepeatedHasNil
} }
return b, err return b, err
} }
} }
return b, errreq return b, nerr.E
} }
} }
@ -2318,15 +2490,21 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
tags := strings.Split(f.Tag.Get("protobuf"), ",") tags := strings.Split(f.Tag.Get("protobuf"), ",")
keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",") keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",")
valTags := strings.Split(f.Tag.Get("protobuf_val"), ",") valTags := strings.Split(f.Tag.Get("protobuf_val"), ",")
stdOptions := false
for _, t := range tags { for _, t := range tags {
if strings.HasPrefix(t, "customtype=") { if strings.HasPrefix(t, "customtype=") {
valTags = append(valTags, t) valTags = append(valTags, t)
} }
if t == "stdtime" { if t == "stdtime" {
valTags = append(valTags, t) valTags = append(valTags, t)
stdOptions = true
} }
if t == "stdduration" { if t == "stdduration" {
valTags = append(valTags, t) valTags = append(valTags, t)
stdOptions = true
}
if t == "wktptr" {
valTags = append(valTags, t)
} }
} }
keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map
@ -2340,6 +2518,25 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
// value. // value.
// Key cannot be pointer-typed. // Key cannot be pointer-typed.
valIsPtr := valType.Kind() == reflect.Ptr valIsPtr := valType.Kind() == reflect.Ptr
// If value is a message with nested maps, calling
// valSizer in marshal may be quadratic. We should use
// cached version in marshal (but not in size).
// If value is not message type, we don't have size cache,
// but it cannot be nested either. Just use valSizer.
valCachedSizer := valSizer
if valIsPtr && !stdOptions && valType.Elem().Kind() == reflect.Struct {
u := getMarshalInfo(valType.Elem())
valCachedSizer = func(ptr pointer, tagsize int) int {
// Same as message sizer, but use cache.
p := ptr.getPointer()
if p.isNil() {
return 0
}
siz := u.cachedsize(p)
return siz + SizeVarint(uint64(siz)) + tagsize
}
}
return func(ptr pointer, tagsize int) int { return func(ptr pointer, tagsize int) int {
m := ptr.asPointerTo(t).Elem() // the map m := ptr.asPointerTo(t).Elem() // the map
n := 0 n := 0
@ -2360,24 +2557,26 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
if len(keys) > 1 && deterministic { if len(keys) > 1 && deterministic {
sort.Sort(mapKeys(keys)) sort.Sort(mapKeys(keys))
} }
var nerr nonFatal
for _, k := range keys { for _, k := range keys {
ki := k.Interface() ki := k.Interface()
vi := m.MapIndex(k).Interface() vi := m.MapIndex(k).Interface()
kaddr := toAddrPointer(&ki, false) // pointer to key kaddr := toAddrPointer(&ki, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
b = appendVarint(b, tag) b = appendVarint(b, tag)
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
b = appendVarint(b, uint64(siz)) b = appendVarint(b, uint64(siz))
b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic) b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
b, err = valMarshaler(b, vaddr, valWireTag, deterministic) b, err = valMarshaler(b, vaddr, valWireTag, deterministic)
if err != nil && err != ErrNil { // allow nil value in map if err != ErrNil && !nerr.Merge(err) { // allow nil value in map
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
} }
@ -2450,6 +2649,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
defer mu.Unlock() defer mu.Unlock()
var err error var err error
var nerr nonFatal
// Fast-path for common cases: zero or one extensions. // Fast-path for common cases: zero or one extensions.
// Don't bother sorting the keys. // Don't bother sorting the keys.
@ -2469,11 +2669,11 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic) b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
// Sort the keys to provide a deterministic encoding. // Sort the keys to provide a deterministic encoding.
@ -2500,11 +2700,11 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic) b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
// message set format is: // message set format is:
@ -2561,6 +2761,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
defer mu.Unlock() defer mu.Unlock()
var err error var err error
var nerr nonFatal
// Fast-path for common cases: zero or one extensions. // Fast-path for common cases: zero or one extensions.
// Don't bother sorting the keys. // Don't bother sorting the keys.
@ -2587,12 +2788,12 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
b = append(b, 1<<3|WireEndGroup) b = append(b, 1<<3|WireEndGroup)
} }
return b, nil return b, nerr.E
} }
// Sort the keys to provide a deterministic encoding. // Sort the keys to provide a deterministic encoding.
@ -2626,11 +2827,11 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
b = append(b, 1<<3|WireEndGroup) b = append(b, 1<<3|WireEndGroup)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
// sizeV1Extensions computes the size of encoded data for a V1-API extension field. // sizeV1Extensions computes the size of encoded data for a V1-API extension field.
@ -2673,6 +2874,7 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
sort.Ints(keys) sort.Ints(keys)
var err error var err error
var nerr nonFatal
for _, k := range keys { for _, k := range keys {
e := m[int32(k)] e := m[int32(k)]
if e.value == nil || e.desc == nil { if e.value == nil || e.desc == nil {
@ -2689,11 +2891,11 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic) b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
// newMarshaler is the interface representing objects that can marshal themselves. // newMarshaler is the interface representing objects that can marshal themselves.
@ -2758,6 +2960,11 @@ func Marshal(pb Message) ([]byte, error) {
// a Buffer for most applications. // a Buffer for most applications.
func (p *Buffer) Marshal(pb Message) error { func (p *Buffer) Marshal(pb Message) error {
var err error var err error
if p.deterministic {
if _, ok := pb.(Marshaler); ok {
return fmt.Errorf("proto: deterministic not supported by the Marshal method of %T", pb)
}
}
if m, ok := pb.(newMarshaler); ok { if m, ok := pb.(newMarshaler); ok {
siz := m.XXX_Size() siz := m.XXX_Size()
p.grow(siz) // make sure buf has enough capacity p.grow(siz) // make sure buf has enough capacity

View File

@ -99,6 +99,8 @@ type unmarshalFieldInfo struct {
// if a required field, contains a single set bit at this field's index in the required field list. // if a required field, contains a single set bit at this field's index in the required field list.
reqMask uint64 reqMask uint64
name string // name of the field, for error reporting
} }
var ( var (
@ -139,7 +141,7 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions()) return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
} }
var reqMask uint64 // bitmask of required fields we've seen. var reqMask uint64 // bitmask of required fields we've seen.
var rnse *RequiredNotSetError // an instance of a RequiredNotSetError returned by a submessage. var errLater error
for len(b) > 0 { for len(b) > 0 {
// Read tag and wire type. // Read tag and wire type.
// Special case 1 and 2 byte varints. // Special case 1 and 2 byte varints.
@ -178,11 +180,20 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
if r, ok := err.(*RequiredNotSetError); ok { if r, ok := err.(*RequiredNotSetError); ok {
// Remember this error, but keep parsing. We need to produce // Remember this error, but keep parsing. We need to produce
// a full parse even if a required field is missing. // a full parse even if a required field is missing.
rnse = r if errLater == nil {
errLater = r
}
reqMask |= f.reqMask reqMask |= f.reqMask
continue continue
} }
if err != errInternalBadWireType { if err != errInternalBadWireType {
if err == errInvalidUTF8 {
if errLater == nil {
fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
errLater = &invalidUTF8Error{fullName}
}
continue
}
return err return err
} }
// Fragments with bad wire type are treated as unknown fields. // Fragments with bad wire type are treated as unknown fields.
@ -244,20 +255,16 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
emap[int32(tag)] = e emap[int32(tag)] = e
} }
} }
if rnse != nil { if reqMask != u.reqMask && errLater == nil {
// A required field of a submessage/group is missing. Return that error.
return rnse
}
if reqMask != u.reqMask {
// A required field of this message is missing. // A required field of this message is missing.
for _, n := range u.reqFields { for _, n := range u.reqFields {
if reqMask&1 == 0 { if reqMask&1 == 0 {
return &RequiredNotSetError{n} errLater = &RequiredNotSetError{n}
} }
reqMask >>= 1 reqMask >>= 1
} }
} }
return nil return errLater
} }
// computeUnmarshalInfo fills in u with information for use // computeUnmarshalInfo fills in u with information for use
@ -360,7 +367,7 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
} }
// Store the info in the correct slot in the message. // Store the info in the correct slot in the message.
u.setTag(tag, toField(&f), unmarshal, reqMask) u.setTag(tag, toField(&f), unmarshal, reqMask, name)
} }
// Find any types associated with oneof fields. // Find any types associated with oneof fields.
@ -376,10 +383,17 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
f := typ.Field(0) // oneof implementers have one field f := typ.Field(0) // oneof implementers have one field
baseUnmarshal := fieldUnmarshaler(&f) baseUnmarshal := fieldUnmarshaler(&f)
tagstr := strings.Split(f.Tag.Get("protobuf"), ",")[1] tags := strings.Split(f.Tag.Get("protobuf"), ",")
tag, err := strconv.Atoi(tagstr) fieldNum, err := strconv.Atoi(tags[1])
if err != nil { if err != nil {
panic("protobuf tag field not an integer: " + tagstr) panic("protobuf tag field not an integer: " + tags[1])
}
var name string
for _, tag := range tags {
if strings.HasPrefix(tag, "name=") {
name = strings.TrimPrefix(tag, "name=")
break
}
} }
// Find the oneof field that this struct implements. // Find the oneof field that this struct implements.
@ -390,7 +404,7 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
// That lets us know where this struct should be stored // That lets us know where this struct should be stored
// when we encounter it during unmarshaling. // when we encounter it during unmarshaling.
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
u.setTag(tag, of.field, unmarshal, 0) u.setTag(fieldNum, of.field, unmarshal, 0, name)
} }
} }
} }
@ -411,7 +425,7 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
// [0 0] is [tag=0/wiretype=varint varint-encoded-0]. // [0 0] is [tag=0/wiretype=varint varint-encoded-0].
u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) { u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) {
return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w) return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w)
}, 0) }, 0, "")
// Set mask for required field check. // Set mask for required field check.
u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1 u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1
@ -423,8 +437,9 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
// tag = tag # for field // tag = tag # for field
// field/unmarshal = unmarshal info for that field. // field/unmarshal = unmarshal info for that field.
// reqMask = if required, bitmask for field position in required field list. 0 otherwise. // reqMask = if required, bitmask for field position in required field list. 0 otherwise.
func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64) { // name = short name of the field.
i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask} func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64, name string) {
i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask, name: name}
n := u.typ.NumField() n := u.typ.NumField()
if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here? if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here?
for len(u.dense) <= tag { for len(u.dense) <= tag {
@ -455,10 +470,16 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
ctype := false ctype := false
isTime := false isTime := false
isDuration := false isDuration := false
isWktPointer := false
proto3 := false
validateUTF8 := true
for _, tag := range tagArray[3:] { for _, tag := range tagArray[3:] {
if strings.HasPrefix(tag, "name=") { if strings.HasPrefix(tag, "name=") {
name = tag[5:] name = tag[5:]
} }
if tag == "proto3" {
proto3 = true
}
if strings.HasPrefix(tag, "customtype=") { if strings.HasPrefix(tag, "customtype=") {
ctype = true ctype = true
} }
@ -468,7 +489,11 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
if tag == "stdduration" { if tag == "stdduration" {
isDuration = true isDuration = true
} }
if tag == "wktptr" {
isWktPointer = true
} }
}
validateUTF8 = validateUTF8 && proto3
// Figure out packaging (pointer, slice, or both) // Figure out packaging (pointer, slice, or both)
slice := false slice := false
@ -522,6 +547,112 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
return makeUnmarshalDuration(getUnmarshalInfo(t), name) return makeUnmarshalDuration(getUnmarshalInfo(t), name)
} }
if isWktPointer {
switch t.Kind() {
case reflect.Float64:
if pointer {
if slice {
return makeStdDoubleValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdDoubleValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdDoubleValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdDoubleValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Float32:
if pointer {
if slice {
return makeStdFloatValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdFloatValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdFloatValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdFloatValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Int64:
if pointer {
if slice {
return makeStdInt64ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdInt64ValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdInt64ValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdInt64ValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Uint64:
if pointer {
if slice {
return makeStdUInt64ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdUInt64ValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdUInt64ValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdUInt64ValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Int32:
if pointer {
if slice {
return makeStdInt32ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdInt32ValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdInt32ValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdInt32ValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Uint32:
if pointer {
if slice {
return makeStdUInt32ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdUInt32ValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdUInt32ValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdUInt32ValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Bool:
if pointer {
if slice {
return makeStdBoolValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdBoolValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdBoolValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdBoolValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.String:
if pointer {
if slice {
return makeStdStringValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdStringValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdStringValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdStringValueUnmarshaler(getUnmarshalInfo(t), name)
case uint8SliceType:
if pointer {
if slice {
return makeStdBytesValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdBytesValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdBytesValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdBytesValueUnmarshaler(getUnmarshalInfo(t), name)
default:
panic(fmt.Sprintf("unknown wktpointer type %#v", t))
}
}
// We'll never have both pointer and slice for basic types. // We'll never have both pointer and slice for basic types.
if pointer && slice && t.Kind() != reflect.Struct { if pointer && slice && t.Kind() != reflect.Struct {
panic("both pointer and slice for basic type in " + t.Name()) panic("both pointer and slice for basic type in " + t.Name())
@ -656,6 +787,15 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
} }
return unmarshalBytesValue return unmarshalBytesValue
case reflect.String: case reflect.String:
if validateUTF8 {
if pointer {
return unmarshalUTF8StringPtr
}
if slice {
return unmarshalUTF8StringSlice
}
return unmarshalUTF8StringValue
}
if pointer { if pointer {
return unmarshalStringPtr return unmarshalStringPtr
} }
@ -1516,9 +1656,6 @@ func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) {
return nil, io.ErrUnexpectedEOF return nil, io.ErrUnexpectedEOF
} }
v := string(b[:x]) v := string(b[:x])
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
*f.toString() = v *f.toString() = v
return b[x:], nil return b[x:], nil
} }
@ -1536,9 +1673,6 @@ func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) {
return nil, io.ErrUnexpectedEOF return nil, io.ErrUnexpectedEOF
} }
v := string(b[:x]) v := string(b[:x])
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
*f.toStringPtr() = &v *f.toStringPtr() = &v
return b[x:], nil return b[x:], nil
} }
@ -1556,14 +1690,72 @@ func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) {
return nil, io.ErrUnexpectedEOF return nil, io.ErrUnexpectedEOF
} }
v := string(b[:x]) v := string(b[:x])
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
s := f.toStringSlice() s := f.toStringSlice()
*s = append(*s, v) *s = append(*s, v)
return b[x:], nil return b[x:], nil
} }
func unmarshalUTF8StringValue(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return b, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
*f.toString() = v
if !utf8.ValidString(v) {
return b[x:], errInvalidUTF8
}
return b[x:], nil
}
func unmarshalUTF8StringPtr(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return b, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
*f.toStringPtr() = &v
if !utf8.ValidString(v) {
return b[x:], errInvalidUTF8
}
return b[x:], nil
}
func unmarshalUTF8StringSlice(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return b, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
s := f.toStringSlice()
*s = append(*s, v)
if !utf8.ValidString(v) {
return b[x:], errInvalidUTF8
}
return b[x:], nil
}
var emptyBuf [0]byte var emptyBuf [0]byte
func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) { func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) {
@ -1731,6 +1923,9 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
if t == "stdduration" { if t == "stdduration" {
valTags = append(valTags, t) valTags = append(valTags, t)
} }
if t == "wktptr" {
valTags = append(valTags, t)
}
} }
unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key")) unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key"))
unmarshalVal := typeUnmarshaler(vt, strings.Join(valTags, ",")) unmarshalVal := typeUnmarshaler(vt, strings.Join(valTags, ","))
@ -1755,6 +1950,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
// Maps will be somewhat slow. Oh well. // Maps will be somewhat slow. Oh well.
// Read key and value from data. // Read key and value from data.
var nerr nonFatal
k := reflect.New(kt) k := reflect.New(kt)
v := reflect.New(vt) v := reflect.New(vt)
for len(b) > 0 { for len(b) > 0 {
@ -1775,7 +1971,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
err = errInternalBadWireType // skip unknown tag err = errInternalBadWireType // skip unknown tag
} }
if err == nil { if nerr.Merge(err) {
continue continue
} }
if err != errInternalBadWireType { if err != errInternalBadWireType {
@ -1798,7 +1994,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
// Insert into map. // Insert into map.
m.SetMapIndex(k.Elem(), v.Elem()) m.SetMapIndex(k.Elem(), v.Elem())
return r, nil return r, nerr.E
} }
} }
@ -1824,15 +2020,16 @@ func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshal
// Unmarshal data into holder. // Unmarshal data into holder.
// We unmarshal into the first field of the holder object. // We unmarshal into the first field of the holder object.
var err error var err error
var nerr nonFatal
b, err = unmarshal(b, valToPointer(v).offset(field0), w) b, err = unmarshal(b, valToPointer(v).offset(field0), w)
if err != nil { if !nerr.Merge(err) {
return nil, err return nil, err
} }
// Write pointer to holder into target field. // Write pointer to holder into target field.
f.asPointerTo(ityp).Elem().Set(v) f.asPointerTo(ityp).Elem().Set(v)
return b, nil return b, nerr.E
} }
} }

View File

@ -364,7 +364,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return err return err
} }
} }
if err := tm.writeAny(w, key, props.mkeyprop); err != nil { if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
return err return err
} }
if err := w.WriteByte('\n'); err != nil { if err := w.WriteByte('\n'); err != nil {
@ -381,7 +381,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return err return err
} }
} }
if err := tm.writeAny(w, val, props.mvalprop); err != nil { if err := tm.writeAny(w, val, props.MapValProp); err != nil {
return err return err
} }
if err := w.WriteByte('\n'); err != nil { if err := w.WriteByte('\n'); err != nil {

View File

@ -636,17 +636,17 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
if err := p.consumeToken(":"); err != nil { if err := p.consumeToken(":"); err != nil {
return err return err
} }
if err := p.readAny(key, props.mkeyprop); err != nil { if err := p.readAny(key, props.MapKeyProp); err != nil {
return err return err
} }
if err := p.consumeOptionalSeparator(); err != nil { if err := p.consumeOptionalSeparator(); err != nil {
return err return err
} }
case "value": case "value":
if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
return err return err
} }
if err := p.readAny(val, props.mvalprop); err != nil { if err := p.readAny(val, props.MapValProp); err != nil {
return err return err
} }
if err := p.consumeOptionalSeparator(); err != nil { if err := p.consumeOptionalSeparator(); err != nil {
@ -923,6 +923,16 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
fv.SetFloat(f) fv.SetFloat(f)
return nil return nil
} }
case reflect.Int8:
if x, err := strconv.ParseInt(tok.value, 0, 8); err == nil {
fv.SetInt(x)
return nil
}
case reflect.Int16:
if x, err := strconv.ParseInt(tok.value, 0, 16); err == nil {
fv.SetInt(x)
return nil
}
case reflect.Int32: case reflect.Int32:
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil { if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
fv.SetInt(x) fv.SetInt(x)
@ -970,6 +980,16 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
} }
// TODO: Handle nested messages which implement encoding.TextUnmarshaler. // TODO: Handle nested messages which implement encoding.TextUnmarshaler.
return p.readStruct(fv, terminator) return p.readStruct(fv, terminator)
case reflect.Uint8:
if x, err := strconv.ParseUint(tok.value, 0, 8); err == nil {
fv.SetUint(x)
return nil
}
case reflect.Uint16:
if x, err := strconv.ParseUint(tok.value, 0, 16); err == nil {
fv.SetUint(x)
return nil
}
case reflect.Uint32: case reflect.Uint32:
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
fv.SetUint(uint64(x)) fv.SetUint(uint64(x))

1888
vendor/github.com/gogo/protobuf/proto/wrappers.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

113
vendor/github.com/gogo/protobuf/proto/wrappers_gogo.go generated vendored Normal file
View File

@ -0,0 +1,113 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2018, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
type float64Value struct {
Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *float64Value) Reset() { *m = float64Value{} }
func (*float64Value) ProtoMessage() {}
func (*float64Value) String() string { return "float64<string>" }
type float32Value struct {
Value float32 `protobuf:"fixed32,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *float32Value) Reset() { *m = float32Value{} }
func (*float32Value) ProtoMessage() {}
func (*float32Value) String() string { return "float32<string>" }
type int64Value struct {
Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *int64Value) Reset() { *m = int64Value{} }
func (*int64Value) ProtoMessage() {}
func (*int64Value) String() string { return "int64<string>" }
type uint64Value struct {
Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *uint64Value) Reset() { *m = uint64Value{} }
func (*uint64Value) ProtoMessage() {}
func (*uint64Value) String() string { return "uint64<string>" }
type int32Value struct {
Value int32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *int32Value) Reset() { *m = int32Value{} }
func (*int32Value) ProtoMessage() {}
func (*int32Value) String() string { return "int32<string>" }
type uint32Value struct {
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *uint32Value) Reset() { *m = uint32Value{} }
func (*uint32Value) ProtoMessage() {}
func (*uint32Value) String() string { return "uint32<string>" }
type boolValue struct {
Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *boolValue) Reset() { *m = boolValue{} }
func (*boolValue) ProtoMessage() {}
func (*boolValue) String() string { return "bool<string>" }
type stringValue struct {
Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *stringValue) Reset() { *m = stringValue{} }
func (*stringValue) ProtoMessage() {}
func (*stringValue) String() string { return "string<string>" }
type bytesValue struct {
Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *bytesValue) Reset() { *m = bytesValue{} }
func (*bytesValue) ProtoMessage() {}
func (*bytesValue) String() string { return "[]byte<string>" }
func init() {
RegisterType((*float64Value)(nil), "gogo.protobuf.proto.DoubleValue")
RegisterType((*float32Value)(nil), "gogo.protobuf.proto.FloatValue")
RegisterType((*int64Value)(nil), "gogo.protobuf.proto.Int64Value")
RegisterType((*uint64Value)(nil), "gogo.protobuf.proto.UInt64Value")
RegisterType((*int32Value)(nil), "gogo.protobuf.proto.Int32Value")
RegisterType((*uint32Value)(nil), "gogo.protobuf.proto.UInt32Value")
RegisterType((*boolValue)(nil), "gogo.protobuf.proto.BoolValue")
RegisterType((*stringValue)(nil), "gogo.protobuf.proto.StringValue")
RegisterType((*bytesValue)(nil), "gogo.protobuf.proto.BytesValue")
}

View File

@ -925,13 +925,16 @@ func stripUnknownFlagValue(args []string) []string {
} }
first := args[0] first := args[0]
if first[0] == '-' { if len(first) > 0 && first[0] == '-' {
//--unknown --next-flag ... //--unknown --next-flag ...
return args return args
} }
//--unknown arg ... (args will be arg ...) //--unknown arg ... (args will be arg ...)
if len(args) > 1 {
return args[1:] return args[1:]
}
return nil
} }
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) { func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {

149
vendor/github.com/spf13/pflag/string_to_int.go generated vendored Normal file
View File

@ -0,0 +1,149 @@
package pflag
import (
"bytes"
"fmt"
"strconv"
"strings"
)
// -- stringToInt Value
type stringToIntValue struct {
value *map[string]int
changed bool
}
func newStringToIntValue(val map[string]int, p *map[string]int) *stringToIntValue {
ssv := new(stringToIntValue)
ssv.value = p
*ssv.value = val
return ssv
}
// Format: a=1,b=2
func (s *stringToIntValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make(map[string]int, len(ss))
for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return fmt.Errorf("%s must be formatted as key=value", pair)
}
var err error
out[kv[0]], err = strconv.Atoi(kv[1])
if err != nil {
return err
}
}
if !s.changed {
*s.value = out
} else {
for k, v := range out {
(*s.value)[k] = v
}
}
s.changed = true
return nil
}
func (s *stringToIntValue) Type() string {
return "stringToInt"
}
func (s *stringToIntValue) String() string {
var buf bytes.Buffer
i := 0
for k, v := range *s.value {
if i > 0 {
buf.WriteRune(',')
}
buf.WriteString(k)
buf.WriteRune('=')
buf.WriteString(strconv.Itoa(v))
i++
}
return "[" + buf.String() + "]"
}
func stringToIntConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// An empty string would cause an empty map
if len(val) == 0 {
return map[string]int{}, nil
}
ss := strings.Split(val, ",")
out := make(map[string]int, len(ss))
for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
}
var err error
out[kv[0]], err = strconv.Atoi(kv[1])
if err != nil {
return nil, err
}
}
return out, nil
}
// GetStringToInt return the map[string]int value of a flag with the given name
func (f *FlagSet) GetStringToInt(name string) (map[string]int, error) {
val, err := f.getFlagType(name, "stringToInt", stringToIntConv)
if err != nil {
return map[string]int{}, err
}
return val.(map[string]int), nil
}
// StringToIntVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a map[string]int variable in which to store the values of the multiple flags.
// The value of each argument will not try to be separated by comma
func (f *FlagSet) StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
f.VarP(newStringToIntValue(value, p), name, "", usage)
}
// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
f.VarP(newStringToIntValue(value, p), name, shorthand, usage)
}
// StringToIntVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a map[string]int variable in which to store the value of the flag.
// The value of each argument will not try to be separated by comma
func StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
CommandLine.VarP(newStringToIntValue(value, p), name, "", usage)
}
// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
func StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
CommandLine.VarP(newStringToIntValue(value, p), name, shorthand, usage)
}
// StringToInt defines a string flag with specified name, default value, and usage string.
// The return value is the address of a map[string]int variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
func (f *FlagSet) StringToInt(name string, value map[string]int, usage string) *map[string]int {
p := map[string]int{}
f.StringToIntVarP(&p, name, "", value, usage)
return &p
}
// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
p := map[string]int{}
f.StringToIntVarP(&p, name, shorthand, value, usage)
return &p
}
// StringToInt defines a string flag with specified name, default value, and usage string.
// The return value is the address of a map[string]int variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
func StringToInt(name string, value map[string]int, usage string) *map[string]int {
return CommandLine.StringToIntP(name, "", value, usage)
}
// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
func StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
return CommandLine.StringToIntP(name, shorthand, value, usage)
}

160
vendor/github.com/spf13/pflag/string_to_string.go generated vendored Normal file
View File

@ -0,0 +1,160 @@
package pflag
import (
"bytes"
"encoding/csv"
"fmt"
"strings"
)
// -- stringToString Value
type stringToStringValue struct {
value *map[string]string
changed bool
}
func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue {
ssv := new(stringToStringValue)
ssv.value = p
*ssv.value = val
return ssv
}
// Format: a=1,b=2
func (s *stringToStringValue) Set(val string) error {
var ss []string
n := strings.Count(val, "=")
switch n {
case 0:
return fmt.Errorf("%s must be formatted as key=value", val)
case 1:
ss = append(ss, strings.Trim(val, `"`))
default:
r := csv.NewReader(strings.NewReader(val))
var err error
ss, err = r.Read()
if err != nil {
return err
}
}
out := make(map[string]string, len(ss))
for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return fmt.Errorf("%s must be formatted as key=value", pair)
}
out[kv[0]] = kv[1]
}
if !s.changed {
*s.value = out
} else {
for k, v := range out {
(*s.value)[k] = v
}
}
s.changed = true
return nil
}
func (s *stringToStringValue) Type() string {
return "stringToString"
}
func (s *stringToStringValue) String() string {
records := make([]string, 0, len(*s.value)>>1)
for k, v := range *s.value {
records = append(records, k+"="+v)
}
var buf bytes.Buffer
w := csv.NewWriter(&buf)
if err := w.Write(records); err != nil {
panic(err)
}
w.Flush()
return "[" + strings.TrimSpace(buf.String()) + "]"
}
func stringToStringConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// An empty string would cause an empty map
if len(val) == 0 {
return map[string]string{}, nil
}
r := csv.NewReader(strings.NewReader(val))
ss, err := r.Read()
if err != nil {
return nil, err
}
out := make(map[string]string, len(ss))
for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
}
out[kv[0]] = kv[1]
}
return out, nil
}
// GetStringToString return the map[string]string value of a flag with the given name
func (f *FlagSet) GetStringToString(name string) (map[string]string, error) {
val, err := f.getFlagType(name, "stringToString", stringToStringConv)
if err != nil {
return map[string]string{}, err
}
return val.(map[string]string), nil
}
// StringToStringVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a map[string]string variable in which to store the values of the multiple flags.
// The value of each argument will not try to be separated by comma
func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
f.VarP(newStringToStringValue(value, p), name, "", usage)
}
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
f.VarP(newStringToStringValue(value, p), name, shorthand, usage)
}
// StringToStringVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a map[string]string variable in which to store the value of the flag.
// The value of each argument will not try to be separated by comma
func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
CommandLine.VarP(newStringToStringValue(value, p), name, "", usage)
}
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage)
}
// StringToString defines a string flag with specified name, default value, and usage string.
// The return value is the address of a map[string]string variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string {
p := map[string]string{}
f.StringToStringVarP(&p, name, "", value, usage)
return &p
}
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
p := map[string]string{}
f.StringToStringVarP(&p, name, shorthand, value, usage)
return &p
}
// StringToString defines a string flag with specified name, default value, and usage string.
// The return value is the address of a map[string]string variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
func StringToString(name string, value map[string]string, usage string) *map[string]string {
return CommandLine.StringToStringP(name, "", value, usage)
}
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
return CommandLine.StringToStringP(name, shorthand, value, usage)
}

28
vendor/gopkg.in/yaml.v2/encode.go generated vendored
View File

@ -13,6 +13,19 @@ import (
"unicode/utf8" "unicode/utf8"
) )
// jsonNumber is the interface of the encoding/json.Number datatype.
// Repeating the interface here avoids a dependency on encoding/json, and also
// supports other libraries like jsoniter, which use a similar datatype with
// the same interface. Detecting this interface is useful when dealing with
// structures containing json.Number, which is a string under the hood. The
// encoder should prefer the use of Int64(), Float64() and string(), in that
// order, when encoding this type.
type jsonNumber interface {
Float64() (float64, error)
Int64() (int64, error)
String() string
}
type encoder struct { type encoder struct {
emitter yaml_emitter_t emitter yaml_emitter_t
event yaml_event_t event yaml_event_t
@ -89,6 +102,21 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
} }
iface := in.Interface() iface := in.Interface()
switch m := iface.(type) { switch m := iface.(type) {
case jsonNumber:
integer, err := m.Int64()
if err == nil {
// In this case the json.Number is a valid int64
in = reflect.ValueOf(integer)
break
}
float, err := m.Float64()
if err == nil {
// In this case the json.Number is a valid float64
in = reflect.ValueOf(float)
break
}
// fallback case - no number could be obtained
in = reflect.ValueOf(m.String())
case time.Time, *time.Time: case time.Time, *time.Time:
// Although time.Time implements TextMarshaler, // Although time.Time implements TextMarshaler,
// we don't want to treat it as a string for YAML // we don't want to treat it as a string for YAML