|
@@ -47,14 +47,14 @@ func Register(v interface{}, args ...string) {
|
|
defer mu.Unlock()
|
|
defer mu.Unlock()
|
|
if et, ok := registry[t]; ok {
|
|
if et, ok := registry[t]; ok {
|
|
if et != p {
|
|
if et != p {
|
|
- panic(errors.Errorf("type registred with alternate path %q != %q", et, p))
|
|
|
|
|
|
+ panic(errors.Errorf("type registered with alternate path %q != %q", et, p))
|
|
}
|
|
}
|
|
return
|
|
return
|
|
}
|
|
}
|
|
registry[t] = p
|
|
registry[t] = p
|
|
}
|
|
}
|
|
|
|
|
|
-// TypeURL returns the type url for a registred type.
|
|
|
|
|
|
+// TypeURL returns the type url for a registered type.
|
|
func TypeURL(v interface{}) (string, error) {
|
|
func TypeURL(v interface{}) (string, error) {
|
|
mu.Lock()
|
|
mu.Lock()
|
|
u, ok := registry[tryDereference(v)]
|
|
u, ok := registry[tryDereference(v)]
|
|
@@ -120,16 +120,43 @@ func UnmarshalAny(any *types.Any) (interface{}, error) {
|
|
}
|
|
}
|
|
|
|
|
|
func UnmarshalByTypeURL(typeURL string, value []byte) (interface{}, error) {
|
|
func UnmarshalByTypeURL(typeURL string, value []byte) (interface{}, error) {
|
|
|
|
+ return unmarshal(typeURL, value, nil)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func UnmarshalTo(any *types.Any, out interface{}) error {
|
|
|
|
+ return UnmarshalToByTypeURL(any.TypeUrl, any.Value, out)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func UnmarshalToByTypeURL(typeURL string, value []byte, out interface{}) error {
|
|
|
|
+ _, err := unmarshal(typeURL, value, out)
|
|
|
|
+ return err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func unmarshal(typeURL string, value []byte, v interface{}) (interface{}, error) {
|
|
t, err := getTypeByUrl(typeURL)
|
|
t, err := getTypeByUrl(typeURL)
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
- v := reflect.New(t.t).Interface()
|
|
|
|
|
|
+
|
|
|
|
+ if v == nil {
|
|
|
|
+ v = reflect.New(t.t).Interface()
|
|
|
|
+ } else {
|
|
|
|
+ // Validate interface type provided by client
|
|
|
|
+ vURL, err := TypeURL(v)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ if typeURL != vURL {
|
|
|
|
+ return nil, errors.Errorf("can't unmarshal type %q to output %q", typeURL, vURL)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if t.isProto {
|
|
if t.isProto {
|
|
err = proto.Unmarshal(value, v.(proto.Message))
|
|
err = proto.Unmarshal(value, v.(proto.Message))
|
|
} else {
|
|
} else {
|
|
err = json.Unmarshal(value, v)
|
|
err = json.Unmarshal(value, v)
|
|
}
|
|
}
|
|
|
|
+
|
|
return v, err
|
|
return v, err
|
|
}
|
|
}
|
|
|
|
|