github.com/enmand/kubernetes@v1.2.0-alpha.0/third_party/forked/reflect/deep_equal.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package reflect is a fork of go's standard library reflection package, which 6 // allows for deep equal with equality functions defined. 7 package reflect 8 9 import ( 10 "fmt" 11 "reflect" 12 "strings" 13 ) 14 15 // Equalities is a map from type to a function comparing two values of 16 // that type. 17 type Equalities map[reflect.Type]reflect.Value 18 19 // For convenience, panics on errrors 20 func EqualitiesOrDie(funcs ...interface{}) Equalities { 21 e := Equalities{} 22 if err := e.AddFuncs(funcs...); err != nil { 23 panic(err) 24 } 25 return e 26 } 27 28 // AddFuncs is a shortcut for multiple calls to AddFunc. 29 func (e Equalities) AddFuncs(funcs ...interface{}) error { 30 for _, f := range funcs { 31 if err := e.AddFunc(f); err != nil { 32 return err 33 } 34 } 35 return nil 36 } 37 38 // AddFunc uses func as an equality function: it must take 39 // two parameters of the same type, and return a boolean. 40 func (e Equalities) AddFunc(eqFunc interface{}) error { 41 fv := reflect.ValueOf(eqFunc) 42 ft := fv.Type() 43 if ft.Kind() != reflect.Func { 44 return fmt.Errorf("expected func, got: %v", ft) 45 } 46 if ft.NumIn() != 2 { 47 return fmt.Errorf("expected three 'in' params, got: %v", ft) 48 } 49 if ft.NumOut() != 1 { 50 return fmt.Errorf("expected one 'out' param, got: %v", ft) 51 } 52 if ft.In(0) != ft.In(1) { 53 return fmt.Errorf("expected arg 1 and 2 to have same type, but got %v", ft) 54 } 55 var forReturnType bool 56 boolType := reflect.TypeOf(forReturnType) 57 if ft.Out(0) != boolType { 58 return fmt.Errorf("expected bool return, got: %v", ft) 59 } 60 e[ft.In(0)] = fv 61 return nil 62 } 63 64 // Below here is forked from go's reflect/deepequal.go 65 66 // During deepValueEqual, must keep track of checks that are 67 // in progress. The comparison algorithm assumes that all 68 // checks in progress are true when it reencounters them. 69 // Visited comparisons are stored in a map indexed by visit. 70 type visit struct { 71 a1 uintptr 72 a2 uintptr 73 typ reflect.Type 74 } 75 76 // unexportedTypePanic is thrown when you use this DeepEqual on something that has an 77 // unexported type. It indicates a programmer error, so should not occur at runtime, 78 // which is why it's not public and thus impossible to catch. 79 type unexportedTypePanic []reflect.Type 80 81 func (u unexportedTypePanic) Error() string { return u.String() } 82 func (u unexportedTypePanic) String() string { 83 strs := make([]string, len(u)) 84 for i, t := range u { 85 strs[i] = fmt.Sprintf("%v", t) 86 } 87 return "an unexported field was encountered, nested like this: " + strings.Join(strs, " -> ") 88 } 89 90 func makeUsefulPanic(v reflect.Value) { 91 if x := recover(); x != nil { 92 if u, ok := x.(unexportedTypePanic); ok { 93 u = append(unexportedTypePanic{v.Type()}, u...) 94 x = u 95 } 96 panic(x) 97 } 98 } 99 100 // Tests for deep equality using reflected types. The map argument tracks 101 // comparisons that have already been seen, which allows short circuiting on 102 // recursive types. 103 func (e Equalities) deepValueEqual(v1, v2 reflect.Value, visited map[visit]bool, depth int) bool { 104 defer makeUsefulPanic(v1) 105 106 if !v1.IsValid() || !v2.IsValid() { 107 return v1.IsValid() == v2.IsValid() 108 } 109 if v1.Type() != v2.Type() { 110 return false 111 } 112 if fv, ok := e[v1.Type()]; ok { 113 return fv.Call([]reflect.Value{v1, v2})[0].Bool() 114 } 115 116 hard := func(k reflect.Kind) bool { 117 switch k { 118 case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct: 119 return true 120 } 121 return false 122 } 123 124 if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) { 125 addr1 := v1.UnsafeAddr() 126 addr2 := v2.UnsafeAddr() 127 if addr1 > addr2 { 128 // Canonicalize order to reduce number of entries in visited. 129 addr1, addr2 = addr2, addr1 130 } 131 132 // Short circuit if references are identical ... 133 if addr1 == addr2 { 134 return true 135 } 136 137 // ... or already seen 138 typ := v1.Type() 139 v := visit{addr1, addr2, typ} 140 if visited[v] { 141 return true 142 } 143 144 // Remember for later. 145 visited[v] = true 146 } 147 148 switch v1.Kind() { 149 case reflect.Array: 150 // We don't need to check length here because length is part of 151 // an array's type, which has already been filtered for. 152 for i := 0; i < v1.Len(); i++ { 153 if !e.deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) { 154 return false 155 } 156 } 157 return true 158 case reflect.Slice: 159 if (v1.IsNil() || v1.Len() == 0) != (v2.IsNil() || v2.Len() == 0) { 160 return false 161 } 162 if v1.IsNil() || v1.Len() == 0 { 163 return true 164 } 165 if v1.Len() != v2.Len() { 166 return false 167 } 168 if v1.Pointer() == v2.Pointer() { 169 return true 170 } 171 for i := 0; i < v1.Len(); i++ { 172 if !e.deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) { 173 return false 174 } 175 } 176 return true 177 case reflect.Interface: 178 if v1.IsNil() || v2.IsNil() { 179 return v1.IsNil() == v2.IsNil() 180 } 181 return e.deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1) 182 case reflect.Ptr: 183 return e.deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1) 184 case reflect.Struct: 185 for i, n := 0, v1.NumField(); i < n; i++ { 186 if !e.deepValueEqual(v1.Field(i), v2.Field(i), visited, depth+1) { 187 return false 188 } 189 } 190 return true 191 case reflect.Map: 192 if (v1.IsNil() || v1.Len() == 0) != (v2.IsNil() || v2.Len() == 0) { 193 return false 194 } 195 if v1.IsNil() || v1.Len() == 0 { 196 return true 197 } 198 if v1.Len() != v2.Len() { 199 return false 200 } 201 if v1.Pointer() == v2.Pointer() { 202 return true 203 } 204 for _, k := range v1.MapKeys() { 205 if !e.deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) { 206 return false 207 } 208 } 209 return true 210 case reflect.Func: 211 if v1.IsNil() && v2.IsNil() { 212 return true 213 } 214 // Can't do better than this: 215 return false 216 default: 217 // Normal equality suffices 218 if !v1.CanInterface() || !v2.CanInterface() { 219 panic(unexportedTypePanic{}) 220 } 221 return v1.Interface() == v2.Interface() 222 } 223 } 224 225 // DeepEqual is like reflect.DeepEqual, but focused on semantic equality 226 // instead of memory equality. 227 // 228 // It will use e's equality functions if it finds types that match. 229 // 230 // An empty slice *is* equal to a nil slice for our purposes; same for maps. 231 // 232 // Unexported field members cannot be compared and will cause an imformative panic; you must add an Equality 233 // function for these types. 234 func (e Equalities) DeepEqual(a1, a2 interface{}) bool { 235 if a1 == nil || a2 == nil { 236 return a1 == a2 237 } 238 v1 := reflect.ValueOf(a1) 239 v2 := reflect.ValueOf(a2) 240 if v1.Type() != v2.Type() { 241 return false 242 } 243 return e.deepValueEqual(v1, v2, make(map[visit]bool), 0) 244 } 245 246 func (e Equalities) deepValueDerive(v1, v2 reflect.Value, visited map[visit]bool, depth int) bool { 247 defer makeUsefulPanic(v1) 248 249 if !v1.IsValid() || !v2.IsValid() { 250 return v1.IsValid() == v2.IsValid() 251 } 252 if v1.Type() != v2.Type() { 253 return false 254 } 255 if fv, ok := e[v1.Type()]; ok { 256 return fv.Call([]reflect.Value{v1, v2})[0].Bool() 257 } 258 259 hard := func(k reflect.Kind) bool { 260 switch k { 261 case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct: 262 return true 263 } 264 return false 265 } 266 267 if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) { 268 addr1 := v1.UnsafeAddr() 269 addr2 := v2.UnsafeAddr() 270 if addr1 > addr2 { 271 // Canonicalize order to reduce number of entries in visited. 272 addr1, addr2 = addr2, addr1 273 } 274 275 // Short circuit if references are identical ... 276 if addr1 == addr2 { 277 return true 278 } 279 280 // ... or already seen 281 typ := v1.Type() 282 v := visit{addr1, addr2, typ} 283 if visited[v] { 284 return true 285 } 286 287 // Remember for later. 288 visited[v] = true 289 } 290 291 switch v1.Kind() { 292 case reflect.Array: 293 // We don't need to check length here because length is part of 294 // an array's type, which has already been filtered for. 295 for i := 0; i < v1.Len(); i++ { 296 if !e.deepValueDerive(v1.Index(i), v2.Index(i), visited, depth+1) { 297 return false 298 } 299 } 300 return true 301 case reflect.Slice: 302 if v1.IsNil() || v1.Len() == 0 { 303 return true 304 } 305 if v1.Len() > v2.Len() { 306 return false 307 } 308 if v1.Pointer() == v2.Pointer() { 309 return true 310 } 311 for i := 0; i < v1.Len(); i++ { 312 if !e.deepValueDerive(v1.Index(i), v2.Index(i), visited, depth+1) { 313 return false 314 } 315 } 316 return true 317 case reflect.String: 318 if v1.Len() == 0 { 319 return true 320 } 321 if v1.Len() > v2.Len() { 322 return false 323 } 324 return v1.String() == v2.String() 325 case reflect.Interface: 326 if v1.IsNil() { 327 return true 328 } 329 return e.deepValueDerive(v1.Elem(), v2.Elem(), visited, depth+1) 330 case reflect.Ptr: 331 if v1.IsNil() { 332 return true 333 } 334 return e.deepValueDerive(v1.Elem(), v2.Elem(), visited, depth+1) 335 case reflect.Struct: 336 for i, n := 0, v1.NumField(); i < n; i++ { 337 if !e.deepValueDerive(v1.Field(i), v2.Field(i), visited, depth+1) { 338 return false 339 } 340 } 341 return true 342 case reflect.Map: 343 if v1.IsNil() || v1.Len() == 0 { 344 return true 345 } 346 if v1.Len() > v2.Len() { 347 return false 348 } 349 if v1.Pointer() == v2.Pointer() { 350 return true 351 } 352 for _, k := range v1.MapKeys() { 353 if !e.deepValueDerive(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) { 354 return false 355 } 356 } 357 return true 358 case reflect.Func: 359 if v1.IsNil() && v2.IsNil() { 360 return true 361 } 362 // Can't do better than this: 363 return false 364 default: 365 // Normal equality suffices 366 if !v1.CanInterface() || !v2.CanInterface() { 367 panic(unexportedTypePanic{}) 368 } 369 return v1.Interface() == v2.Interface() 370 } 371 } 372 373 // DeepDerivative is similar to DeepEqual except that unset fields in a1 are 374 // ignored (not compared). This allows us to focus on the fields that matter to 375 // the semantic comparison. 376 // 377 // The unset fields include a nil pointer and an empty string. 378 func (e Equalities) DeepDerivative(a1, a2 interface{}) bool { 379 if a1 == nil { 380 return true 381 } 382 v1 := reflect.ValueOf(a1) 383 v2 := reflect.ValueOf(a2) 384 if v1.Type() != v2.Type() { 385 return false 386 } 387 return e.deepValueDerive(v1, v2, make(map[visit]bool), 0) 388 }