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"
|
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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
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]
|
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) {
|
||||||
|
|
|
||||||
|
|
@ -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"
|
"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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue