diff options
Diffstat (limited to 'vendor/github.com/golang/protobuf/ptypes/any.go')
-rw-r--r-- | vendor/github.com/golang/protobuf/ptypes/any.go | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/vendor/github.com/golang/protobuf/ptypes/any.go b/vendor/github.com/golang/protobuf/ptypes/any.go new file mode 100644 index 0000000..70276e8 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/any.go | |||
@@ -0,0 +1,141 @@ | |||
1 | // Go support for Protocol Buffers - Google's data interchange format | ||
2 | // | ||
3 | // Copyright 2016 The Go Authors. All rights reserved. | ||
4 | // https://github.com/golang/protobuf | ||
5 | // | ||
6 | // Redistribution and use in source and binary forms, with or without | ||
7 | // modification, are permitted provided that the following conditions are | ||
8 | // met: | ||
9 | // | ||
10 | // * Redistributions of source code must retain the above copyright | ||
11 | // notice, this list of conditions and the following disclaimer. | ||
12 | // * Redistributions in binary form must reproduce the above | ||
13 | // copyright notice, this list of conditions and the following disclaimer | ||
14 | // in the documentation and/or other materials provided with the | ||
15 | // distribution. | ||
16 | // * Neither the name of Google Inc. nor the names of its | ||
17 | // contributors may be used to endorse or promote products derived from | ||
18 | // this software without specific prior written permission. | ||
19 | // | ||
20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | |||
32 | package ptypes | ||
33 | |||
34 | // This file implements functions to marshal proto.Message to/from | ||
35 | // google.protobuf.Any message. | ||
36 | |||
37 | import ( | ||
38 | "fmt" | ||
39 | "reflect" | ||
40 | "strings" | ||
41 | |||
42 | "github.com/golang/protobuf/proto" | ||
43 | "github.com/golang/protobuf/ptypes/any" | ||
44 | ) | ||
45 | |||
46 | const googleApis = "type.googleapis.com/" | ||
47 | |||
48 | // AnyMessageName returns the name of the message contained in a google.protobuf.Any message. | ||
49 | // | ||
50 | // Note that regular type assertions should be done using the Is | ||
51 | // function. AnyMessageName is provided for less common use cases like filtering a | ||
52 | // sequence of Any messages based on a set of allowed message type names. | ||
53 | func AnyMessageName(any *any.Any) (string, error) { | ||
54 | if any == nil { | ||
55 | return "", fmt.Errorf("message is nil") | ||
56 | } | ||
57 | slash := strings.LastIndex(any.TypeUrl, "/") | ||
58 | if slash < 0 { | ||
59 | return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl) | ||
60 | } | ||
61 | return any.TypeUrl[slash+1:], nil | ||
62 | } | ||
63 | |||
64 | // MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any. | ||
65 | func MarshalAny(pb proto.Message) (*any.Any, error) { | ||
66 | value, err := proto.Marshal(pb) | ||
67 | if err != nil { | ||
68 | return nil, err | ||
69 | } | ||
70 | return &any.Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil | ||
71 | } | ||
72 | |||
73 | // DynamicAny is a value that can be passed to UnmarshalAny to automatically | ||
74 | // allocate a proto.Message for the type specified in a google.protobuf.Any | ||
75 | // message. The allocated message is stored in the embedded proto.Message. | ||
76 | // | ||
77 | // Example: | ||
78 | // | ||
79 | // var x ptypes.DynamicAny | ||
80 | // if err := ptypes.UnmarshalAny(a, &x); err != nil { ... } | ||
81 | // fmt.Printf("unmarshaled message: %v", x.Message) | ||
82 | type DynamicAny struct { | ||
83 | proto.Message | ||
84 | } | ||
85 | |||
86 | // Empty returns a new proto.Message of the type specified in a | ||
87 | // google.protobuf.Any message. It returns an error if corresponding message | ||
88 | // type isn't linked in. | ||
89 | func Empty(any *any.Any) (proto.Message, error) { | ||
90 | aname, err := AnyMessageName(any) | ||
91 | if err != nil { | ||
92 | return nil, err | ||
93 | } | ||
94 | |||
95 | t := proto.MessageType(aname) | ||
96 | if t == nil { | ||
97 | return nil, fmt.Errorf("any: message type %q isn't linked in", aname) | ||
98 | } | ||
99 | return reflect.New(t.Elem()).Interface().(proto.Message), nil | ||
100 | } | ||
101 | |||
102 | // UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any | ||
103 | // message and places the decoded result in pb. It returns an error if type of | ||
104 | // contents of Any message does not match type of pb message. | ||
105 | // | ||
106 | // pb can be a proto.Message, or a *DynamicAny. | ||
107 | func UnmarshalAny(any *any.Any, pb proto.Message) error { | ||
108 | if d, ok := pb.(*DynamicAny); ok { | ||
109 | if d.Message == nil { | ||
110 | var err error | ||
111 | d.Message, err = Empty(any) | ||
112 | if err != nil { | ||
113 | return err | ||
114 | } | ||
115 | } | ||
116 | return UnmarshalAny(any, d.Message) | ||
117 | } | ||
118 | |||
119 | aname, err := AnyMessageName(any) | ||
120 | if err != nil { | ||
121 | return err | ||
122 | } | ||
123 | |||
124 | mname := proto.MessageName(pb) | ||
125 | if aname != mname { | ||
126 | return fmt.Errorf("mismatched message type: got %q want %q", aname, mname) | ||
127 | } | ||
128 | return proto.Unmarshal(any.Value, pb) | ||
129 | } | ||
130 | |||
131 | // Is returns true if any value contains a given message type. | ||
132 | func Is(any *any.Any, pb proto.Message) bool { | ||
133 | // The following is equivalent to AnyMessageName(any) == proto.MessageName(pb), | ||
134 | // but it avoids scanning TypeUrl for the slash. | ||
135 | if any == nil { | ||
136 | return false | ||
137 | } | ||
138 | name := proto.MessageName(pb) | ||
139 | prefix := len(any.TypeUrl) - len(name) | ||
140 | return prefix >= 1 && any.TypeUrl[prefix-1] == '/' && any.TypeUrl[prefix:] == name | ||
141 | } | ||