summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2017-06-21 19:06:17 -0700
committerCorey Hulen <corey@hulen.com>2017-06-21 19:06:17 -0700
commit42f28ab8e374137fe3f5d25424489d879d4724f8 (patch)
tree20353f2446b506d32e6d353b72a57bf48f070389 /vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
parent6b39c308d882a0aeac533f8ab1d90b48a2ae4b5a (diff)
downloadchat-42f28ab8e374137fe3f5d25424489d879d4724f8.tar.gz
chat-42f28ab8e374137fe3f5d25424489d879d4724f8.tar.bz2
chat-42f28ab8e374137fe3f5d25424489d879d4724f8.zip
Updating server dependancies (#6712)
Diffstat (limited to 'vendor/github.com/golang/protobuf/jsonpb/jsonpb.go')
-rw-r--r--vendor/github.com/golang/protobuf/jsonpb/jsonpb.go117
1 files changed, 101 insertions, 16 deletions
diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
index eff41c2e6..c7a45d6f0 100644
--- a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
+++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
@@ -44,6 +44,7 @@ import (
"errors"
"fmt"
"io"
+ "math"
"reflect"
"sort"
"strconv"
@@ -74,6 +75,22 @@ type Marshaler struct {
OrigName bool
}
+// JSONPBMarshaler is implemented by protobuf messages that customize the
+// way they are marshaled to JSON. Messages that implement this should
+// also implement JSONPBUnmarshaler so that the custom format can be
+// parsed.
+type JSONPBMarshaler interface {
+ MarshalJSONPB(*Marshaler) ([]byte, error)
+}
+
+// JSONPBUnmarshaler is implemented by protobuf messages that customize
+// the way they are unmarshaled from JSON. Messages that implement this
+// should also implement JSONPBMarshaler so that the custom format can be
+// produced.
+type JSONPBUnmarshaler interface {
+ UnmarshalJSONPB(*Unmarshaler, []byte) error
+}
+
// Marshal marshals a protocol buffer into JSON.
func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error {
writer := &errWriter{writer: out}
@@ -91,6 +108,12 @@ func (m *Marshaler) MarshalToString(pb proto.Message) (string, error) {
type int32Slice []int32
+var nonFinite = map[string]float64{
+ `"NaN"`: math.NaN(),
+ `"Infinity"`: math.Inf(1),
+ `"-Infinity"`: math.Inf(-1),
+}
+
// For sorting extensions ids to ensure stable output.
func (s int32Slice) Len() int { return len(s) }
func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
@@ -102,6 +125,31 @@ type wkt interface {
// marshalObject writes a struct to the Writer.
func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeURL string) error {
+ if jsm, ok := v.(JSONPBMarshaler); ok {
+ b, err := jsm.MarshalJSONPB(m)
+ if err != nil {
+ return err
+ }
+ if typeURL != "" {
+ // we are marshaling this object to an Any type
+ var js map[string]*json.RawMessage
+ if err = json.Unmarshal(b, &js); err != nil {
+ return fmt.Errorf("type %T produced invalid JSON: %v", v, err)
+ }
+ turl, err := json.Marshal(typeURL)
+ if err != nil {
+ return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
+ }
+ js["@type"] = (*json.RawMessage)(&turl)
+ if b, err = json.Marshal(js); err != nil {
+ return err
+ }
+ }
+
+ out.write(string(b))
+ return out.err
+ }
+
s := reflect.ValueOf(v).Elem()
// Handle well-known types.
@@ -182,7 +230,7 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
// IsNil will panic on most value kinds.
switch value.Kind() {
- case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+ case reflect.Chan, reflect.Func, reflect.Interface:
if value.IsNil() {
continue
}
@@ -210,6 +258,10 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
if value.Len() == 0 {
continue
}
+ case reflect.Map, reflect.Ptr, reflect.Slice:
+ if value.IsNil() {
+ continue
+ }
}
}
@@ -373,10 +425,15 @@ func (m *Marshaler) marshalField(out *errWriter, prop *proto.Properties, v refle
// marshalValue writes the value to the Writer.
func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error {
-
var err error
v = reflect.Indirect(v)
+ // Handle nil pointer
+ if v.Kind() == reflect.Invalid {
+ out.write("null")
+ return out.err
+ }
+
// Handle repeated elements.
if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
out.write("[")
@@ -406,9 +463,6 @@ func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v refle
// Handle well-known types.
// Most are handled up in marshalObject (because 99% are messages).
- type wkt interface {
- XXX_WellKnownType() string
- }
if wkt, ok := v.Interface().(wkt); ok {
switch wkt.XXX_WellKnownType() {
case "NullValue":
@@ -496,6 +550,24 @@ func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v refle
return out.err
}
+ // Handle non-finite floats, e.g. NaN, Infinity and -Infinity.
+ if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
+ f := v.Float()
+ var sval string
+ switch {
+ case math.IsInf(f, 1):
+ sval = `"Infinity"`
+ case math.IsInf(f, -1):
+ sval = `"-Infinity"`
+ case math.IsNaN(f):
+ sval = `"NaN"`
+ }
+ if sval != "" {
+ out.write(sval)
+ return out.err
+ }
+ }
+
// Default handling defers to the encoding/json library.
b, err := json.Marshal(v.Interface())
if err != nil {
@@ -571,10 +643,11 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
return u.unmarshalValue(target.Elem(), inputValue, prop)
}
- // Handle well-known types.
- type wkt interface {
- XXX_WellKnownType() string
+ if jsu, ok := target.Addr().Interface().(JSONPBUnmarshaler); ok {
+ return jsu.UnmarshalJSONPB(u, []byte(inputValue))
}
+
+ // Handle well-known types.
if w, ok := target.Addr().Interface().(wkt); ok {
switch w.XXX_WellKnownType() {
case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
@@ -585,19 +658,22 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
// so we don't have to do any extra work.
return u.unmarshalValue(target.Field(0), inputValue, prop)
case "Any":
- var jsonFields map[string]json.RawMessage
+ // Use json.RawMessage pointer type instead of value to support pre-1.8 version.
+ // 1.8 changed RawMessage.MarshalJSON from pointer type to value type, see
+ // https://github.com/golang/go/issues/14493
+ var jsonFields map[string]*json.RawMessage
if err := json.Unmarshal(inputValue, &jsonFields); err != nil {
return err
}
val, ok := jsonFields["@type"]
- if !ok {
+ if !ok || val == nil {
return errors.New("Any JSON doesn't have '@type'")
}
var turl string
- if err := json.Unmarshal([]byte(val), &turl); err != nil {
- return fmt.Errorf("can't unmarshal Any's '@type': %q", val)
+ if err := json.Unmarshal([]byte(*val), &turl); err != nil {
+ return fmt.Errorf("can't unmarshal Any's '@type': %q", *val)
}
target.Field(0).SetString(turl)
@@ -617,8 +693,8 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
return errors.New("Any JSON doesn't have 'value'")
}
- if err := u.unmarshalValue(reflect.ValueOf(m).Elem(), val, nil); err != nil {
- return fmt.Errorf("can't unmarshal Any's WKT: %v", err)
+ if err := u.unmarshalValue(reflect.ValueOf(m).Elem(), *val, nil); err != nil {
+ return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err)
}
} else {
delete(jsonFields, "@type")
@@ -628,13 +704,13 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
}
if err = u.unmarshalValue(reflect.ValueOf(m).Elem(), nestedProto, nil); err != nil {
- return fmt.Errorf("can't unmarshal nested Any proto: %v", err)
+ return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err)
}
}
b, err := proto.Marshal(m)
if err != nil {
- return fmt.Errorf("can't marshal proto into Any.Value: %v", err)
+ return fmt.Errorf("can't marshal proto %T into Any.Value: %v", m, err)
}
target.Field(1).SetBytes(b)
@@ -911,6 +987,15 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
inputValue = inputValue[1 : len(inputValue)-1]
}
+ // Non-finite numbers can be encoded as strings.
+ isFloat := targetType.Kind() == reflect.Float32 || targetType.Kind() == reflect.Float64
+ if isFloat {
+ if num, ok := nonFinite[string(inputValue)]; ok {
+ target.SetFloat(num)
+ return nil
+ }
+ }
+
// Use the encoding/json for parsing other value types.
return json.Unmarshal(inputValue, target.Addr().Interface())
}