...

Source file src/github.com/gogo/protobuf/proto/equal.go

Documentation: github.com/gogo/protobuf/proto

     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  
   249  		m1, m2 := e1.value, e2.value
   250  
   251  		if m1 == nil && m2 == nil {
   252  			// Both have only encoded form.
   253  			if bytes.Equal(e1.enc, e2.enc) {
   254  				continue
   255  			}
   256  			// The bytes are different, but the extensions might still be
   257  			// equal. We need to decode them to compare.
   258  		}
   259  
   260  		if m1 != nil && m2 != nil {
   261  			// Both are unencoded.
   262  			if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
   263  				return false
   264  			}
   265  			continue
   266  		}
   267  
   268  		// At least one is encoded. To do a semantically correct comparison
   269  		// we need to unmarshal them first.
   270  		var desc *ExtensionDesc
   271  		if m := extensionMaps[base]; m != nil {
   272  			desc = m[extNum]
   273  		}
   274  		if desc == nil {
   275  			// If both have only encoded form and the bytes are the same,
   276  			// it is handled above. We get here when the bytes are different.
   277  			// We don't know how to decode it, so just compare them as byte
   278  			// slices.
   279  			log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
   280  			return false
   281  		}
   282  		var err error
   283  		if m1 == nil {
   284  			m1, err = decodeExtension(e1.enc, desc)
   285  		}
   286  		if m2 == nil && err == nil {
   287  			m2, err = decodeExtension(e2.enc, desc)
   288  		}
   289  		if err != nil {
   290  			// The encoded form is invalid.
   291  			log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
   292  			return false
   293  		}
   294  		if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
   295  			return false
   296  		}
   297  	}
   298  
   299  	return true
   300  }
   301  

View as plain text