github.com/matm/etcd@v0.3.1-0.20140328024009-5b4a473f1453/third_party/code.google.com/p/gogoprotobuf/proto/equal.go (about) 1 // Go support for Protocol Buffers - Google's data interchange format 2 // 3 // Copyright 2011 The Go Authors. All rights reserved. 4 // http://code.google.com/p/goprotobuf/ 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 // TODO: MessageSet. 34 35 package proto 36 37 import ( 38 "bytes" 39 "log" 40 "reflect" 41 "strings" 42 ) 43 44 /* 45 Equal returns true iff protocol buffers a and b are equal. 46 The arguments must both be pointers to protocol buffer structs. 47 48 Equality is defined in this way: 49 - Two messages are equal iff they are the same type, 50 corresponding fields are equal, unknown field sets 51 are equal, and extensions sets are equal. 52 - Two set scalar fields are equal iff their values are equal. 53 If the fields are of a floating-point type, remember that 54 NaN != x for all x, including NaN. 55 - Two repeated fields are equal iff their lengths are the same, 56 and their corresponding elements are equal (a "bytes" field, 57 although represented by []byte, is not a repeated field) 58 - Two unset fields are equal. 59 - Two unknown field sets are equal if their current 60 encoded state is equal. (TODO) 61 - Two extension sets are equal iff they have corresponding 62 elements that are pairwise equal. 63 - Every other combination of things are not equal. 64 65 The return value is undefined if a and b are not protocol buffers. 66 */ 67 func Equal(a, b Message) bool { 68 if a == nil || b == nil { 69 return a == b 70 } 71 v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b) 72 if v1.Type() != v2.Type() { 73 return false 74 } 75 if v1.Kind() == reflect.Ptr { 76 if v1.IsNil() { 77 return v2.IsNil() 78 } 79 if v2.IsNil() { 80 return false 81 } 82 v1, v2 = v1.Elem(), v2.Elem() 83 } 84 if v1.Kind() != reflect.Struct { 85 return false 86 } 87 return equalStruct(v1, v2) 88 } 89 90 // v1 and v2 are known to have the same type. 91 func equalStruct(v1, v2 reflect.Value) bool { 92 for i := 0; i < v1.NumField(); i++ { 93 f := v1.Type().Field(i) 94 if strings.HasPrefix(f.Name, "XXX_") { 95 continue 96 } 97 f1, f2 := v1.Field(i), v2.Field(i) 98 if f.Type.Kind() == reflect.Ptr { 99 if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 { 100 // both unset 101 continue 102 } else if n1 != n2 { 103 // set/unset mismatch 104 return false 105 } 106 b1, ok := f1.Interface().(raw) 107 if ok { 108 b2 := f2.Interface().(raw) 109 // RawMessage 110 if !bytes.Equal(b1.Bytes(), b2.Bytes()) { 111 return false 112 } 113 continue 114 } 115 f1, f2 = f1.Elem(), f2.Elem() 116 } 117 if !equalAny(f1, f2) { 118 return false 119 } 120 } 121 122 if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { 123 em2 := v2.FieldByName("XXX_extensions") 124 if !equalExtensions(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { 125 return false 126 } 127 } 128 129 uf := v1.FieldByName("XXX_unrecognized") 130 if !uf.IsValid() { 131 return true 132 } 133 134 u1 := uf.Bytes() 135 u2 := v2.FieldByName("XXX_unrecognized").Bytes() 136 if !bytes.Equal(u1, u2) { 137 return false 138 } 139 140 return true 141 } 142 143 // v1 and v2 are known to have the same type. 144 func equalAny(v1, v2 reflect.Value) bool { 145 if v1.Type() == protoMessageType { 146 m1, _ := v1.Interface().(Message) 147 m2, _ := v2.Interface().(Message) 148 return Equal(m1, m2) 149 } 150 switch v1.Kind() { 151 case reflect.Bool: 152 return v1.Bool() == v2.Bool() 153 case reflect.Float32, reflect.Float64: 154 return v1.Float() == v2.Float() 155 case reflect.Int32, reflect.Int64: 156 return v1.Int() == v2.Int() 157 case reflect.Ptr: 158 return equalAny(v1.Elem(), v2.Elem()) 159 case reflect.Slice: 160 if v1.Type().Elem().Kind() == reflect.Uint8 { 161 // short circuit: []byte 162 if v1.IsNil() != v2.IsNil() { 163 return false 164 } 165 return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte)) 166 } 167 168 if v1.Len() != v2.Len() { 169 return false 170 } 171 for i := 0; i < v1.Len(); i++ { 172 if !equalAny(v1.Index(i), v2.Index(i)) { 173 return false 174 } 175 } 176 return true 177 case reflect.String: 178 return v1.Interface().(string) == v2.Interface().(string) 179 case reflect.Struct: 180 return equalStruct(v1, v2) 181 case reflect.Uint32, reflect.Uint64: 182 return v1.Uint() == v2.Uint() 183 } 184 185 // unknown type, so not a protocol buffer 186 log.Printf("proto: don't know how to compare %v", v1) 187 return false 188 } 189 190 // base is the struct type that the extensions are based on. 191 // em1 and em2 are extension maps. 192 func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool { 193 if len(em1) != len(em2) { 194 return false 195 } 196 197 for extNum, e1 := range em1 { 198 e2, ok := em2[extNum] 199 if !ok { 200 return false 201 } 202 203 m1, m2 := e1.value, e2.value 204 205 if m1 != nil && m2 != nil { 206 // Both are unencoded. 207 if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2)) { 208 return false 209 } 210 continue 211 } 212 213 // At least one is encoded. To do a semantically correct comparison 214 // we need to unmarshal them first. 215 var desc *ExtensionDesc 216 if m := extensionMaps[base]; m != nil { 217 desc = m[extNum] 218 } 219 if desc == nil { 220 log.Printf("proto: don't know how to compare extension %d of %v", extNum, base) 221 continue 222 } 223 var err error 224 if m1 == nil { 225 m1, err = decodeExtension(e1.enc, desc) 226 } 227 if m2 == nil && err == nil { 228 m2, err = decodeExtension(e2.enc, desc) 229 } 230 if err != nil { 231 // The encoded form is invalid. 232 log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err) 233 return false 234 } 235 if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2)) { 236 return false 237 } 238 } 239 240 return true 241 }