]>
Commit | Line | Data |
---|---|---|
15c0b25d AP |
1 | // Go support for Protocol Buffers - Google's data interchange format |
2 | // | |
3 | // Copyright 2011 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 | // Protocol buffer comparison. | |
33 | ||
34 | package proto | |
35 | ||
36 | import ( | |
37 | "bytes" | |
38 | "log" | |
39 | "reflect" | |
40 | "strings" | |
41 | ) | |
42 | ||
43 | /* | |
44 | Equal returns true iff protocol buffers a and b are equal. | |
45 | The arguments must both be pointers to protocol buffer structs. | |
46 | ||
47 | Equality is defined in this way: | |
48 | - Two messages are equal iff they are the same type, | |
49 | corresponding fields are equal, unknown field sets | |
50 | are equal, and extensions sets are equal. | |
51 | - Two set scalar fields are equal iff their values are equal. | |
52 | If the fields are of a floating-point type, remember that | |
53 | NaN != x for all x, including NaN. If the message is defined | |
54 | in a proto3 .proto file, fields are not "set"; specifically, | |
55 | zero length proto3 "bytes" fields are equal (nil == {}). | |
56 | - Two repeated fields are equal iff their lengths are the same, | |
57 | and their corresponding elements are equal. Note a "bytes" field, | |
58 | although represented by []byte, is not a repeated field and the | |
59 | rule for the scalar fields described above applies. | |
60 | - Two unset fields are equal. | |
61 | - Two unknown field sets are equal if their current | |
62 | encoded state is equal. | |
63 | - Two extension sets are equal iff they have corresponding | |
64 | elements that are pairwise equal. | |
65 | - Two map fields are equal iff their lengths are the same, | |
66 | and they contain the same set of elements. Zero-length map | |
67 | fields are equal. | |
68 | - Every other combination of things are not equal. | |
69 | ||
70 | The return value is undefined if a and b are not protocol buffers. | |
71 | */ | |
72 | func Equal(a, b Message) bool { | |
73 | if a == nil || b == nil { | |
74 | return a == b | |
75 | } | |
76 | v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b) | |
77 | if v1.Type() != v2.Type() { | |
78 | return false | |
79 | } | |
80 | if v1.Kind() == reflect.Ptr { | |
81 | if v1.IsNil() { | |
82 | return v2.IsNil() | |
83 | } | |
84 | if v2.IsNil() { | |
85 | return false | |
86 | } | |
87 | v1, v2 = v1.Elem(), v2.Elem() | |
88 | } | |
89 | if v1.Kind() != reflect.Struct { | |
90 | return false | |
91 | } | |
92 | return equalStruct(v1, v2) | |
93 | } | |
94 | ||
95 | // v1 and v2 are known to have the same type. | |
96 | func equalStruct(v1, v2 reflect.Value) bool { | |
97 | sprop := GetProperties(v1.Type()) | |
98 | for i := 0; i < v1.NumField(); i++ { | |
99 | f := v1.Type().Field(i) | |
100 | if strings.HasPrefix(f.Name, "XXX_") { | |
101 | continue | |
102 | } | |
103 | f1, f2 := v1.Field(i), v2.Field(i) | |
104 | if f.Type.Kind() == reflect.Ptr { | |
105 | if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 { | |
106 | // both unset | |
107 | continue | |
108 | } else if n1 != n2 { | |
109 | // set/unset mismatch | |
110 | return false | |
111 | } | |
112 | f1, f2 = f1.Elem(), f2.Elem() | |
113 | } | |
114 | if !equalAny(f1, f2, sprop.Prop[i]) { | |
115 | return false | |
116 | } | |
117 | } | |
118 | ||
119 | if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() { | |
120 | em2 := v2.FieldByName("XXX_InternalExtensions") | |
121 | if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) { | |
122 | return false | |
123 | } | |
124 | } | |
125 | ||
126 | if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { | |
127 | em2 := v2.FieldByName("XXX_extensions") | |
128 | if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { | |
129 | return false | |
130 | } | |
131 | } | |
132 | ||
133 | uf := v1.FieldByName("XXX_unrecognized") | |
134 | if !uf.IsValid() { | |
135 | return true | |
136 | } | |
137 | ||
138 | u1 := uf.Bytes() | |
139 | u2 := v2.FieldByName("XXX_unrecognized").Bytes() | |
140 | return bytes.Equal(u1, u2) | |
141 | } | |
142 | ||
143 | // v1 and v2 are known to have the same type. | |
144 | // prop may be nil. | |
145 | func equalAny(v1, v2 reflect.Value, prop *Properties) bool { | |
146 | if v1.Type() == protoMessageType { | |
147 | m1, _ := v1.Interface().(Message) | |
148 | m2, _ := v2.Interface().(Message) | |
149 | return Equal(m1, m2) | |
150 | } | |
151 | switch v1.Kind() { | |
152 | case reflect.Bool: | |
153 | return v1.Bool() == v2.Bool() | |
154 | case reflect.Float32, reflect.Float64: | |
155 | return v1.Float() == v2.Float() | |
156 | case reflect.Int32, reflect.Int64: | |
157 | return v1.Int() == v2.Int() | |
158 | case reflect.Interface: | |
159 | // Probably a oneof field; compare the inner values. | |
160 | n1, n2 := v1.IsNil(), v2.IsNil() | |
161 | if n1 || n2 { | |
162 | return n1 == n2 | |
163 | } | |
164 | e1, e2 := v1.Elem(), v2.Elem() | |
165 | if e1.Type() != e2.Type() { | |
166 | return false | |
167 | } | |
168 | return equalAny(e1, e2, nil) | |
169 | case reflect.Map: | |
170 | if v1.Len() != v2.Len() { | |
171 | return false | |
172 | } | |
173 | for _, key := range v1.MapKeys() { | |
174 | val2 := v2.MapIndex(key) | |
175 | if !val2.IsValid() { | |
176 | // This key was not found in the second map. | |
177 | return false | |
178 | } | |
179 | if !equalAny(v1.MapIndex(key), val2, nil) { | |
180 | return false | |
181 | } | |
182 | } | |
183 | return true | |
184 | case reflect.Ptr: | |
185 | // Maps may have nil values in them, so check for nil. | |
186 | if v1.IsNil() && v2.IsNil() { | |
187 | return true | |
188 | } | |
189 | if v1.IsNil() != v2.IsNil() { | |
190 | return false | |
191 | } | |
192 | return equalAny(v1.Elem(), v2.Elem(), prop) | |
193 | case reflect.Slice: | |
194 | if v1.Type().Elem().Kind() == reflect.Uint8 { | |
195 | // short circuit: []byte | |
196 | ||
197 | // Edge case: if this is in a proto3 message, a zero length | |
198 | // bytes field is considered the zero value. | |
199 | if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 { | |
200 | return true | |
201 | } | |
202 | if v1.IsNil() != v2.IsNil() { | |
203 | return false | |
204 | } | |
205 | return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte)) | |
206 | } | |
207 | ||
208 | if v1.Len() != v2.Len() { | |
209 | return false | |
210 | } | |
211 | for i := 0; i < v1.Len(); i++ { | |
212 | if !equalAny(v1.Index(i), v2.Index(i), prop) { | |
213 | return false | |
214 | } | |
215 | } | |
216 | return true | |
217 | case reflect.String: | |
218 | return v1.Interface().(string) == v2.Interface().(string) | |
219 | case reflect.Struct: | |
220 | return equalStruct(v1, v2) | |
221 | case reflect.Uint32, reflect.Uint64: | |
222 | return v1.Uint() == v2.Uint() | |
223 | } | |
224 | ||
225 | // unknown type, so not a protocol buffer | |
226 | log.Printf("proto: don't know how to compare %v", v1) | |
227 | return false | |
228 | } | |
229 | ||
230 | // base is the struct type that the extensions are based on. | |
231 | // x1 and x2 are InternalExtensions. | |
232 | func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool { | |
233 | em1, _ := x1.extensionsRead() | |
234 | em2, _ := x2.extensionsRead() | |
235 | return equalExtMap(base, em1, em2) | |
236 | } | |
237 | ||
238 | func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { | |
239 | if len(em1) != len(em2) { | |
240 | return false | |
241 | } | |
242 | ||
243 | for extNum, e1 := range em1 { | |
244 | e2, ok := em2[extNum] | |
245 | if !ok { | |
246 | return false | |
247 | } | |
248 | ||
107c1cdb ND |
249 | m1 := extensionAsLegacyType(e1.value) |
250 | m2 := extensionAsLegacyType(e2.value) | |
15c0b25d AP |
251 | |
252 | if m1 == nil && m2 == nil { | |
253 | // Both have only encoded form. | |
254 | if bytes.Equal(e1.enc, e2.enc) { | |
255 | continue | |
256 | } | |
257 | // The bytes are different, but the extensions might still be | |
258 | // equal. We need to decode them to compare. | |
259 | } | |
260 | ||
261 | if m1 != nil && m2 != nil { | |
262 | // Both are unencoded. | |
263 | if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { | |
264 | return false | |
265 | } | |
266 | continue | |
267 | } | |
268 | ||
269 | // At least one is encoded. To do a semantically correct comparison | |
270 | // we need to unmarshal them first. | |
271 | var desc *ExtensionDesc | |
272 | if m := extensionMaps[base]; m != nil { | |
273 | desc = m[extNum] | |
274 | } | |
275 | if desc == nil { | |
276 | // If both have only encoded form and the bytes are the same, | |
277 | // it is handled above. We get here when the bytes are different. | |
278 | // We don't know how to decode it, so just compare them as byte | |
279 | // slices. | |
280 | log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) | |
281 | return false | |
282 | } | |
283 | var err error | |
284 | if m1 == nil { | |
285 | m1, err = decodeExtension(e1.enc, desc) | |
286 | } | |
287 | if m2 == nil && err == nil { | |
288 | m2, err = decodeExtension(e2.enc, desc) | |
289 | } | |
290 | if err != nil { | |
291 | // The encoded form is invalid. | |
292 | log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err) | |
293 | return false | |
294 | } | |
295 | if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { | |
296 | return false | |
297 | } | |
298 | } | |
299 | ||
300 | return true | |
301 | } |