mirror of https://github.com/knative/caching.git
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:
parent
6be7c335a2
commit
5e0d1e671f
|
@ -18,15 +18,15 @@
|
|||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8679b8a64f3613e9749c5640c3535c83399b8e69f67ce54d91dc73f6d77373af"
|
||||
digest = "1:abea725bcf0210887f5da19d804fffa1dd45a42a56bdf5f02322345e3fee4f0d"
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"sortkeys",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "636bf0302bc95575d69441b25a2603156ffdddf1"
|
||||
version = "v1.1.1"
|
||||
revision = "4cbf7e384e768b4e01799441fdf2a706a5635ae7"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -172,12 +172,12 @@
|
|||
version = "v2.0.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:e3707aeaccd2adc89eba6c062fec72116fe1fc1ba71097da85b4d8ae1668a675"
|
||||
digest = "1:9d8420bbf131d1618bde6530af37c3799340d3762cc47210c1d9532a4c3a2779"
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
pruneopts = "NUT"
|
||||
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5"
|
||||
version = "v1.0.2"
|
||||
revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
|
||||
version = "v1.0.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -264,12 +264,12 @@
|
|||
version = "v0.9.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:7c95b35057a0ff2e19f707173cc1a947fa43a6eb5c4d300d196ece0334046082"
|
||||
digest = "1:18108594151654e9e696b27b181b953f9a90b16bf14d253dd1b397b025a1487f"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
pruneopts = "NUT"
|
||||
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||
version = "v2.2.1"
|
||||
revision = "51d6538a90f86fe93ac480b35f37b2be17fef232"
|
||||
version = "v2.2.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8960ef753a87391086a307122d23cd5007cee93c28189437e4f1b6ed72bffc50"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
Protocol Buffers for Go with Gadgets
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -37,27 +37,9 @@ package proto
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"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 (
|
||||
// errRepeatedHasNil is the error returned if Marshal is called with
|
||||
// a struct with a repeated field containing a nil element.
|
||||
|
|
|
@ -265,7 +265,6 @@ package proto
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
|
@ -274,7 +273,66 @@ import (
|
|||
"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.
|
||||
type Message interface {
|
||||
|
@ -570,9 +628,11 @@ func SetDefaults(pb Message) {
|
|||
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) {
|
||||
v = v.Elem()
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
defaultMu.RLock()
|
||||
dm, ok := defaults[v.Type()]
|
||||
|
@ -674,8 +734,11 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
|
|||
|
||||
for _, ni := range dm.nested {
|
||||
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() {
|
||||
case reflect.Struct:
|
||||
setDefaults(f, recur, zeros)
|
||||
|
||||
case reflect.Ptr:
|
||||
if f.IsNil() {
|
||||
continue
|
||||
|
@ -685,7 +748,7 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
|
|||
case reflect.Slice:
|
||||
for i := 0; i < f.Len(); i++ {
|
||||
e := f.Index(i)
|
||||
if e.IsNil() {
|
||||
if e.Kind() == reflect.Ptr && e.IsNil() {
|
||||
continue
|
||||
}
|
||||
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) {
|
||||
var canHaveDefault bool
|
||||
switch ft.Kind() {
|
||||
case reflect.Struct:
|
||||
nestedMessage = true // non-nullable
|
||||
|
||||
case reflect.Ptr:
|
||||
if ft.Elem().Kind() == reflect.Struct {
|
||||
nestedMessage = true
|
||||
|
@ -766,7 +832,7 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes
|
|||
|
||||
case reflect.Slice:
|
||||
switch ft.Elem().Kind() {
|
||||
case reflect.Ptr:
|
||||
case reflect.Ptr, reflect.Struct:
|
||||
nestedMessage = true // repeated message
|
||||
case reflect.Uint8:
|
||||
canHaveDefault = true // bytes field
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// 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.
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ type Properties struct {
|
|||
Repeated bool
|
||||
Packed bool // relevant for repeated primitives 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
|
||||
|
||||
Default string // default value
|
||||
|
@ -153,14 +153,15 @@ type Properties struct {
|
|||
CastType string
|
||||
StdTime bool
|
||||
StdDuration bool
|
||||
WktPointer bool
|
||||
|
||||
stype reflect.Type // set for struct types only
|
||||
ctype reflect.Type // set for custom types only
|
||||
sprop *StructProperties // set for struct types only
|
||||
|
||||
mtype reflect.Type // set for map types only
|
||||
mkeyprop *Properties // set for map types only
|
||||
mvalprop *Properties // set for map types only
|
||||
mtype reflect.Type // set for map types only
|
||||
MapKeyProp *Properties // set for map types only
|
||||
MapValProp *Properties // set for map types only
|
||||
}
|
||||
|
||||
// String formats the properties in the protobuf struct field tag style.
|
||||
|
@ -274,6 +275,8 @@ outer:
|
|||
p.StdTime = true
|
||||
case f == "stdduration":
|
||||
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)
|
||||
return
|
||||
}
|
||||
if p.WktPointer && !isMap {
|
||||
p.setTag(lockGetProp)
|
||||
return
|
||||
}
|
||||
switch t1 := typ; t1.Kind() {
|
||||
case reflect.Struct:
|
||||
p.stype = typ
|
||||
|
@ -317,9 +324,9 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
|
|||
case reflect.Map:
|
||||
|
||||
p.mtype = t1
|
||||
p.mkeyprop = &Properties{}
|
||||
p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
|
||||
p.mvalprop = &Properties{}
|
||||
p.MapKeyProp = &Properties{}
|
||||
p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
|
||||
p.MapValProp = &Properties{}
|
||||
vtype := p.mtype.Elem()
|
||||
if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
|
||||
// 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)
|
||||
}
|
||||
|
||||
p.mvalprop.CustomType = p.CustomType
|
||||
p.mvalprop.StdDuration = p.StdDuration
|
||||
p.mvalprop.StdTime = p.StdTime
|
||||
p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
|
||||
p.MapValProp.CustomType = p.CustomType
|
||||
p.MapValProp.StdDuration = p.StdDuration
|
||||
p.MapValProp.StdTime = p.StdTime
|
||||
p.MapValProp.WktPointer = p.WktPointer
|
||||
p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
|
||||
}
|
||||
p.setTag(lockGetProp)
|
||||
}
|
||||
|
|
|
@ -97,6 +97,8 @@ type marshalElemInfo struct {
|
|||
var (
|
||||
marshalInfoMap = map[reflect.Type]*marshalInfo{}
|
||||
marshalInfoLock sync.Mutex
|
||||
|
||||
uint8SliceType = reflect.TypeOf(([]uint8)(nil)).Kind()
|
||||
)
|
||||
|
||||
// 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.
|
||||
// NOTE: This is not efficient.
|
||||
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)
|
||||
b1, err := m.Marshal()
|
||||
b = append(b, b1...)
|
||||
return b, err
|
||||
}
|
||||
|
||||
var err, errreq error
|
||||
var err, errLater error
|
||||
// The old marshaler encodes extensions at beginning.
|
||||
if u.extensions.IsValid() {
|
||||
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...)
|
||||
}
|
||||
for _, f := range u.fields {
|
||||
if f.required && errreq == nil {
|
||||
if ptr.offset(f.field).getPointer().isNil() {
|
||||
if f.required {
|
||||
if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
|
||||
// Required field is not set.
|
||||
// We record the error but keep going, to give a complete marshaling.
|
||||
errreq = &RequiredNotSetError{f.name}
|
||||
if errLater == nil {
|
||||
errLater = &RequiredNotSetError{f.name}
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -297,14 +298,21 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
|
|||
if err1, 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 = &RequiredNotSetError{f.name + "." + err1.field}
|
||||
if errLater == nil {
|
||||
errLater = &RequiredNotSetError{f.name + "." + err1.field}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err == errRepeatedHasNil {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -312,7 +320,7 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
|
|||
s := *ptr.offset(u.unrecognized).toBytes()
|
||||
b = append(b, s...)
|
||||
}
|
||||
return b, errreq
|
||||
return b, errLater
|
||||
}
|
||||
|
||||
// computeMarshalInfo initializes the marshal info.
|
||||
|
@ -577,6 +585,8 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
|
|||
ctype := false
|
||||
isTime := false
|
||||
isDuration := false
|
||||
isWktPointer := false
|
||||
validateUTF8 := true
|
||||
for i := 2; i < len(tags); i++ {
|
||||
if tags[i] == "packed" {
|
||||
packed = true
|
||||
|
@ -593,7 +603,11 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
|
|||
if tags[i] == "stdduration" {
|
||||
isDuration = true
|
||||
}
|
||||
if tags[i] == "wktptr" {
|
||||
isWktPointer = true
|
||||
}
|
||||
}
|
||||
validateUTF8 = validateUTF8 && proto3
|
||||
if !proto3 && !pointer && !slice {
|
||||
nozero = false
|
||||
}
|
||||
|
@ -638,6 +652,112 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
|
|||
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() {
|
||||
case reflect.Bool:
|
||||
if pointer {
|
||||
|
@ -834,6 +954,18 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
|
|||
}
|
||||
return sizeFloat64Value, appendFloat64Value
|
||||
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 {
|
||||
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) {
|
||||
v := *ptr.toString()
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
|
@ -2103,9 +2232,6 @@ func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]b
|
|||
if v == "" {
|
||||
return b, nil
|
||||
}
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
|
@ -2117,24 +2243,83 @@ func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, err
|
|||
return b, nil
|
||||
}
|
||||
v := *p
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
return b, nil
|
||||
}
|
||||
func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
||||
s := *ptr.toStringSlice()
|
||||
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) {
|
||||
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 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) {
|
||||
return nil, errInvalidUTF8
|
||||
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 appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
||||
|
@ -2213,7 +2398,8 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|||
},
|
||||
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
|
||||
s := ptr.getPointerSlice()
|
||||
var err, errreq error
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
for _, v := range s {
|
||||
if v.isNil() {
|
||||
return b, errRepeatedHasNil
|
||||
|
@ -2221,22 +2407,14 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|||
b = appendVarint(b, wiretag) // start group
|
||||
b, err = u.marshal(b, v, deterministic)
|
||||
b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
|
||||
if err != nil {
|
||||
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 !nerr.Merge(err) {
|
||||
if err == ErrNil {
|
||||
err = errRepeatedHasNil
|
||||
}
|
||||
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) {
|
||||
s := ptr.getPointerSlice()
|
||||
var err, errreq error
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
for _, v := range s {
|
||||
if v.isNil() {
|
||||
return b, errRepeatedHasNil
|
||||
|
@ -2289,22 +2468,15 @@ func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|||
siz := u.cachedsize(v)
|
||||
b = appendVarint(b, uint64(siz))
|
||||
b, err = u.marshal(b, v, deterministic)
|
||||
if err != nil {
|
||||
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 !nerr.Merge(err) {
|
||||
if err == ErrNil {
|
||||
err = errRepeatedHasNil
|
||||
}
|
||||
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"), ",")
|
||||
keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",")
|
||||
valTags := strings.Split(f.Tag.Get("protobuf_val"), ",")
|
||||
stdOptions := false
|
||||
for _, t := range tags {
|
||||
if strings.HasPrefix(t, "customtype=") {
|
||||
valTags = append(valTags, t)
|
||||
}
|
||||
if t == "stdtime" {
|
||||
valTags = append(valTags, t)
|
||||
stdOptions = true
|
||||
}
|
||||
if t == "stdduration" {
|
||||
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
|
||||
|
@ -2340,6 +2518,25 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
|
|||
// value.
|
||||
// Key cannot be pointer-typed.
|
||||
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 {
|
||||
m := ptr.asPointerTo(t).Elem() // the map
|
||||
n := 0
|
||||
|
@ -2360,24 +2557,26 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
|
|||
if len(keys) > 1 && deterministic {
|
||||
sort.Sort(mapKeys(keys))
|
||||
}
|
||||
|
||||
var nerr nonFatal
|
||||
for _, k := range keys {
|
||||
ki := k.Interface()
|
||||
vi := m.MapIndex(k).Interface()
|
||||
kaddr := toAddrPointer(&ki, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
|
||||
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, err = keyMarshaler(b, kaddr, keyWireTag, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
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, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2450,6 +2649,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
|
|||
defer mu.Unlock()
|
||||
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
|
||||
// Fast-path for common cases: zero or one extensions.
|
||||
// Don't bother sorting the keys.
|
||||
|
@ -2469,11 +2669,11 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
|
|||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// 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
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// message set format is:
|
||||
|
@ -2561,6 +2761,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
|
|||
defer mu.Unlock()
|
||||
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
|
||||
// Fast-path for common cases: zero or one extensions.
|
||||
// Don't bother sorting the keys.
|
||||
|
@ -2587,12 +2788,12 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
|
|||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
b = append(b, 1<<3|WireEndGroup)
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// 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)
|
||||
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
|
||||
b = append(b, 1<<3|WireEndGroup)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
for _, k := range keys {
|
||||
e := m[int32(k)]
|
||||
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
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (p *Buffer) Marshal(pb Message) 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 {
|
||||
siz := m.XXX_Size()
|
||||
p.grow(siz) // make sure buf has enough capacity
|
||||
|
|
|
@ -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.
|
||||
reqMask uint64
|
||||
|
||||
name string // name of the field, for error reporting
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -138,8 +140,8 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
|
|||
if u.isMessageSet {
|
||||
return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
|
||||
}
|
||||
var reqMask uint64 // bitmask of required fields we've seen.
|
||||
var rnse *RequiredNotSetError // an instance of a RequiredNotSetError returned by a submessage.
|
||||
var reqMask uint64 // bitmask of required fields we've seen.
|
||||
var errLater error
|
||||
for len(b) > 0 {
|
||||
// Read tag and wire type.
|
||||
// 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 {
|
||||
// Remember this error, but keep parsing. We need to produce
|
||||
// a full parse even if a required field is missing.
|
||||
rnse = r
|
||||
if errLater == nil {
|
||||
errLater = r
|
||||
}
|
||||
reqMask |= f.reqMask
|
||||
continue
|
||||
}
|
||||
if err != errInternalBadWireType {
|
||||
if err == errInvalidUTF8 {
|
||||
if errLater == nil {
|
||||
fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
|
||||
errLater = &invalidUTF8Error{fullName}
|
||||
}
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
// 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
|
||||
}
|
||||
}
|
||||
if rnse != nil {
|
||||
// A required field of a submessage/group is missing. Return that error.
|
||||
return rnse
|
||||
}
|
||||
if reqMask != u.reqMask {
|
||||
if reqMask != u.reqMask && errLater == nil {
|
||||
// A required field of this message is missing.
|
||||
for _, n := range u.reqFields {
|
||||
if reqMask&1 == 0 {
|
||||
return &RequiredNotSetError{n}
|
||||
errLater = &RequiredNotSetError{n}
|
||||
}
|
||||
reqMask >>= 1
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return errLater
|
||||
}
|
||||
|
||||
// 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.
|
||||
u.setTag(tag, toField(&f), unmarshal, reqMask)
|
||||
u.setTag(tag, toField(&f), unmarshal, reqMask, name)
|
||||
}
|
||||
|
||||
// Find any types associated with oneof fields.
|
||||
|
@ -376,10 +383,17 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
|
|||
|
||||
f := typ.Field(0) // oneof implementers have one field
|
||||
baseUnmarshal := fieldUnmarshaler(&f)
|
||||
tagstr := strings.Split(f.Tag.Get("protobuf"), ",")[1]
|
||||
tag, err := strconv.Atoi(tagstr)
|
||||
tags := strings.Split(f.Tag.Get("protobuf"), ",")
|
||||
fieldNum, err := strconv.Atoi(tags[1])
|
||||
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.
|
||||
|
@ -390,7 +404,7 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
|
|||
// That lets us know where this struct should be stored
|
||||
// when we encounter it during unmarshaling.
|
||||
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].
|
||||
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)
|
||||
}, 0)
|
||||
}, 0, "")
|
||||
|
||||
// Set mask for required field check.
|
||||
u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1
|
||||
|
@ -423,8 +437,9 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
|
|||
// tag = tag # for field
|
||||
// field/unmarshal = unmarshal info for that field.
|
||||
// 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) {
|
||||
i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask}
|
||||
// name = short name of the field.
|
||||
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()
|
||||
if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here?
|
||||
for len(u.dense) <= tag {
|
||||
|
@ -455,10 +470,16 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
|
|||
ctype := false
|
||||
isTime := false
|
||||
isDuration := false
|
||||
isWktPointer := false
|
||||
proto3 := false
|
||||
validateUTF8 := true
|
||||
for _, tag := range tagArray[3:] {
|
||||
if strings.HasPrefix(tag, "name=") {
|
||||
name = tag[5:]
|
||||
}
|
||||
if tag == "proto3" {
|
||||
proto3 = true
|
||||
}
|
||||
if strings.HasPrefix(tag, "customtype=") {
|
||||
ctype = true
|
||||
}
|
||||
|
@ -468,7 +489,11 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
|
|||
if tag == "stdduration" {
|
||||
isDuration = true
|
||||
}
|
||||
if tag == "wktptr" {
|
||||
isWktPointer = true
|
||||
}
|
||||
}
|
||||
validateUTF8 = validateUTF8 && proto3
|
||||
|
||||
// Figure out packaging (pointer, slice, or both)
|
||||
slice := false
|
||||
|
@ -522,6 +547,112 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
|
|||
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.
|
||||
if pointer && slice && t.Kind() != reflect.Struct {
|
||||
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
|
||||
case reflect.String:
|
||||
if validateUTF8 {
|
||||
if pointer {
|
||||
return unmarshalUTF8StringPtr
|
||||
}
|
||||
if slice {
|
||||
return unmarshalUTF8StringSlice
|
||||
}
|
||||
return unmarshalUTF8StringValue
|
||||
}
|
||||
if pointer {
|
||||
return unmarshalStringPtr
|
||||
}
|
||||
|
@ -1516,9 +1656,6 @@ func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) {
|
|||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
v := string(b[:x])
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
*f.toString() = v
|
||||
return b[x:], nil
|
||||
}
|
||||
|
@ -1536,9 +1673,6 @@ func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) {
|
|||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
v := string(b[:x])
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
*f.toStringPtr() = &v
|
||||
return b[x:], nil
|
||||
}
|
||||
|
@ -1556,14 +1690,72 @@ func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) {
|
|||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
v := string(b[:x])
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
s := f.toStringSlice()
|
||||
*s = append(*s, v)
|
||||
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
|
||||
|
||||
func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) {
|
||||
|
@ -1731,6 +1923,9 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
|
|||
if t == "stdduration" {
|
||||
valTags = append(valTags, t)
|
||||
}
|
||||
if t == "wktptr" {
|
||||
valTags = append(valTags, t)
|
||||
}
|
||||
}
|
||||
unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key"))
|
||||
unmarshalVal := typeUnmarshaler(vt, strings.Join(valTags, ","))
|
||||
|
@ -1755,6 +1950,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
|
|||
// Maps will be somewhat slow. Oh well.
|
||||
|
||||
// Read key and value from data.
|
||||
var nerr nonFatal
|
||||
k := reflect.New(kt)
|
||||
v := reflect.New(vt)
|
||||
for len(b) > 0 {
|
||||
|
@ -1775,7 +1971,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
|
|||
err = errInternalBadWireType // skip unknown tag
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
if nerr.Merge(err) {
|
||||
continue
|
||||
}
|
||||
if err != errInternalBadWireType {
|
||||
|
@ -1798,7 +1994,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
|
|||
// Insert into map.
|
||||
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.
|
||||
// We unmarshal into the first field of the holder object.
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
b, err = unmarshal(b, valToPointer(v).offset(field0), w)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Write pointer to holder into target field.
|
||||
f.asPointerTo(ityp).Elem().Set(v)
|
||||
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
|
||||
if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte('\n'); err != nil {
|
||||
|
@ -381,7 +381,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if err := tm.writeAny(w, val, props.mvalprop); err != nil {
|
||||
if err := tm.writeAny(w, val, props.MapValProp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte('\n'); err != nil {
|
||||
|
|
|
@ -636,17 +636,17 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
|||
if err := p.consumeToken(":"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.readAny(key, props.mkeyprop); err != nil {
|
||||
if err := p.readAny(key, props.MapKeyProp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
return err
|
||||
}
|
||||
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
|
||||
}
|
||||
if err := p.readAny(val, props.mvalprop); err != nil {
|
||||
if err := p.readAny(val, props.MapValProp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
|
@ -923,6 +923,16 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
|
|||
fv.SetFloat(f)
|
||||
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:
|
||||
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
|
||||
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.
|
||||
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:
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||
fv.SetUint(uint64(x))
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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")
|
||||
}
|
|
@ -925,13 +925,16 @@ func stripUnknownFlagValue(args []string) []string {
|
|||
}
|
||||
|
||||
first := args[0]
|
||||
if first[0] == '-' {
|
||||
if len(first) > 0 && first[0] == '-' {
|
||||
//--unknown --next-flag ...
|
||||
return args
|
||||
}
|
||||
|
||||
//--unknown arg ... (args will be arg ...)
|
||||
return args[1:]
|
||||
if len(args) > 1 {
|
||||
return args[1:]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -13,6 +13,19 @@ import (
|
|||
"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 {
|
||||
emitter yaml_emitter_t
|
||||
event yaml_event_t
|
||||
|
@ -89,6 +102,21 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
|
|||
}
|
||||
iface := in.Interface()
|
||||
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:
|
||||
// Although time.Time implements TextMarshaler,
|
||||
// we don't want to treat it as a string for YAML
|
||||
|
|
Loading…
Reference in New Issue