github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/protobuf/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  // https://yougam/libraries/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 (a "bytes" field,
    58      although represented by []byte, is not a repeated field)
    59    - Two unset fields are equal.
    60    - Two unknown field sets are equal if their current
    61      encoded state is equal.
    62    - Two extension sets are equal iff they have corresponding
    63      elements that are pairwise equal.
    64    - Every other combination of things are not equal.
    65  
    66  The return value is undefined if a and b are not protocol buffers.
    67  */
    68  func Equal(a, b Message) bool {
    69  	if a == nil || b == nil {
    70  		return a == b
    71  	}
    72  	v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
    73  	if v1.Type() != v2.Type() {
    74  		return false
    75  	}
    76  	if v1.Kind() == reflect.Ptr {
    77  		if v1.IsNil() {
    78  			return v2.IsNil()
    79  		}
    80  		if v2.IsNil() {
    81  			return false
    82  		}
    83  		v1, v2 = v1.Elem(), v2.Elem()
    84  	}
    85  	if v1.Kind() != reflect.Struct {
    86  		return false
    87  	}
    88  	return equalStruct(v1, v2)
    89  }
    90  
    91  // v1 and v2 are known to have the same type.
    92  func equalStruct(v1, v2 reflect.Value) bool {
    93  	sprop := GetProperties(v1.Type())
    94  	for i := 0; i < v1.NumField(); i++ {
    95  		f := v1.Type().Field(i)
    96  		if strings.HasPrefix(f.Name, "XXX_") {
    97  			continue
    98  		}
    99  		f1, f2 := v1.Field(i), v2.Field(i)
   100  		if f.Type.Kind() == reflect.Ptr {
   101  			if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
   102  				// both unset
   103  				continue
   104  			} else if n1 != n2 {
   105  				// set/unset mismatch
   106  				return false
   107  			}
   108  			b1, ok := f1.Interface().(raw)
   109  			if ok {
   110  				b2 := f2.Interface().(raw)
   111  				// RawMessage
   112  				if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
   113  					return false
   114  				}
   115  				continue
   116  			}
   117  			f1, f2 = f1.Elem(), f2.Elem()
   118  		}
   119  		if !equalAny(f1, f2, sprop.Prop[i]) {
   120  			return false
   121  		}
   122  	}
   123  
   124  	if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
   125  		em2 := v2.FieldByName("XXX_extensions")
   126  		if !equalExtensions(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
   127  			return false
   128  		}
   129  	}
   130  
   131  	uf := v1.FieldByName("XXX_unrecognized")
   132  	if !uf.IsValid() {
   133  		return true
   134  	}
   135  
   136  	u1 := uf.Bytes()
   137  	u2 := v2.FieldByName("XXX_unrecognized").Bytes()
   138  	if !bytes.Equal(u1, u2) {
   139  		return false
   140  	}
   141  
   142  	return true
   143  }
   144  
   145  // v1 and v2 are known to have the same type.
   146  // prop may be nil.
   147  func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
   148  	if v1.Type() == protoMessageType {
   149  		m1, _ := v1.Interface().(Message)
   150  		m2, _ := v2.Interface().(Message)
   151  		return Equal(m1, m2)
   152  	}
   153  	switch v1.Kind() {
   154  	case reflect.Bool:
   155  		return v1.Bool() == v2.Bool()
   156  	case reflect.Float32, reflect.Float64:
   157  		return v1.Float() == v2.Float()
   158  	case reflect.Int32, reflect.Int64:
   159  		return v1.Int() == v2.Int()
   160  	case reflect.Interface:
   161  		// Probably a oneof field; compare the inner values.
   162  		n1, n2 := v1.IsNil(), v2.IsNil()
   163  		if n1 || n2 {
   164  			return n1 == n2
   165  		}
   166  		e1, e2 := v1.Elem(), v2.Elem()
   167  		if e1.Type() != e2.Type() {
   168  			return false
   169  		}
   170  		return equalAny(e1, e2, nil)
   171  	case reflect.Map:
   172  		if v1.Len() != v2.Len() {
   173  			return false
   174  		}
   175  		for _, key := range v1.MapKeys() {
   176  			val2 := v2.MapIndex(key)
   177  			if !val2.IsValid() {
   178  				// This key was not found in the second map.
   179  				return false
   180  			}
   181  			if !equalAny(v1.MapIndex(key), val2, nil) {
   182  				return false
   183  			}
   184  		}
   185  		return true
   186  	case reflect.Ptr:
   187  		return equalAny(v1.Elem(), v2.Elem(), prop)
   188  	case reflect.Slice:
   189  		if v1.Type().Elem().Kind() == reflect.Uint8 {
   190  			// short circuit: []byte
   191  
   192  			// Edge case: if this is in a proto3 message, a zero length
   193  			// bytes field is considered the zero value.
   194  			if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
   195  				return true
   196  			}
   197  			if v1.IsNil() != v2.IsNil() {
   198  				return false
   199  			}
   200  			return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
   201  		}
   202  
   203  		if v1.Len() != v2.Len() {
   204  			return false
   205  		}
   206  		for i := 0; i < v1.Len(); i++ {
   207  			if !equalAny(v1.Index(i), v2.Index(i), prop) {
   208  				return false
   209  			}
   210  		}
   211  		return true
   212  	case reflect.String:
   213  		return v1.Interface().(string) == v2.Interface().(string)
   214  	case reflect.Struct:
   215  		return equalStruct(v1, v2)
   216  	case reflect.Uint32, reflect.Uint64:
   217  		return v1.Uint() == v2.Uint()
   218  	}
   219  
   220  	// unknown type, so not a protocol buffer
   221  	log.Printf("proto: don't know how to compare %v", v1)
   222  	return false
   223  }
   224  
   225  // base is the struct type that the extensions are based on.
   226  // em1 and em2 are extension maps.
   227  func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
   228  	if len(em1) != len(em2) {
   229  		return false
   230  	}
   231  
   232  	for extNum, e1 := range em1 {
   233  		e2, ok := em2[extNum]
   234  		if !ok {
   235  			return false
   236  		}
   237  
   238  		m1, m2 := e1.value, e2.value
   239  
   240  		if m1 != nil && m2 != nil {
   241  			// Both are unencoded.
   242  			if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
   243  				return false
   244  			}
   245  			continue
   246  		}
   247  
   248  		// At least one is encoded. To do a semantically correct comparison
   249  		// we need to unmarshal them first.
   250  		var desc *ExtensionDesc
   251  		if m := extensionMaps[base]; m != nil {
   252  			desc = m[extNum]
   253  		}
   254  		if desc == nil {
   255  			log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
   256  			continue
   257  		}
   258  		var err error
   259  		if m1 == nil {
   260  			m1, err = decodeExtension(e1.enc, desc)
   261  		}
   262  		if m2 == nil && err == nil {
   263  			m2, err = decodeExtension(e2.enc, desc)
   264  		}
   265  		if err != nil {
   266  			// The encoded form is invalid.
   267  			log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
   268  			return false
   269  		}
   270  		if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
   271  			return false
   272  		}
   273  	}
   274  
   275  	return true
   276  }