31 // for each key is also equal. |
31 // for each key is also equal. |
32 func Equal(x, y Message) bool { |
32 func Equal(x, y Message) bool { |
33 if x == nil || y == nil { |
33 if x == nil || y == nil { |
34 return x == nil && y == nil |
34 return x == nil && y == nil |
35 } |
35 } |
|
36 if reflect.TypeOf(x).Kind() == reflect.Ptr && x == y { |
|
37 // Avoid an expensive comparison if both inputs are identical pointers. |
|
38 return true |
|
39 } |
36 mx := x.ProtoReflect() |
40 mx := x.ProtoReflect() |
37 my := y.ProtoReflect() |
41 my := y.ProtoReflect() |
38 if mx.IsValid() != my.IsValid() { |
42 if mx.IsValid() != my.IsValid() { |
39 return false |
43 return false |
40 } |
44 } |
41 return equalMessage(mx, my) |
45 return equalMessage(mx, my) |
42 } |
46 } |
43 |
47 |
44 // equalMessage compares two messages. |
48 // equalMessage compares two messages. |
45 func equalMessage(mx, my pref.Message) bool { |
49 func equalMessage(mx, my protoreflect.Message) bool { |
46 if mx.Descriptor() != my.Descriptor() { |
50 if mx.Descriptor() != my.Descriptor() { |
47 return false |
51 return false |
48 } |
52 } |
49 |
53 |
50 nx := 0 |
54 nx := 0 |
51 equal := true |
55 equal := true |
52 mx.Range(func(fd pref.FieldDescriptor, vx pref.Value) bool { |
56 mx.Range(func(fd protoreflect.FieldDescriptor, vx protoreflect.Value) bool { |
53 nx++ |
57 nx++ |
54 vy := my.Get(fd) |
58 vy := my.Get(fd) |
55 equal = my.Has(fd) && equalField(fd, vx, vy) |
59 equal = my.Has(fd) && equalField(fd, vx, vy) |
56 return equal |
60 return equal |
57 }) |
61 }) |
58 if !equal { |
62 if !equal { |
59 return false |
63 return false |
60 } |
64 } |
61 ny := 0 |
65 ny := 0 |
62 my.Range(func(fd pref.FieldDescriptor, vx pref.Value) bool { |
66 my.Range(func(fd protoreflect.FieldDescriptor, vx protoreflect.Value) bool { |
63 ny++ |
67 ny++ |
64 return true |
68 return true |
65 }) |
69 }) |
66 if nx != ny { |
70 if nx != ny { |
67 return false |
71 return false |
69 |
73 |
70 return equalUnknown(mx.GetUnknown(), my.GetUnknown()) |
74 return equalUnknown(mx.GetUnknown(), my.GetUnknown()) |
71 } |
75 } |
72 |
76 |
73 // equalField compares two fields. |
77 // equalField compares two fields. |
74 func equalField(fd pref.FieldDescriptor, x, y pref.Value) bool { |
78 func equalField(fd protoreflect.FieldDescriptor, x, y protoreflect.Value) bool { |
75 switch { |
79 switch { |
76 case fd.IsList(): |
80 case fd.IsList(): |
77 return equalList(fd, x.List(), y.List()) |
81 return equalList(fd, x.List(), y.List()) |
78 case fd.IsMap(): |
82 case fd.IsMap(): |
79 return equalMap(fd, x.Map(), y.Map()) |
83 return equalMap(fd, x.Map(), y.Map()) |
81 return equalValue(fd, x, y) |
85 return equalValue(fd, x, y) |
82 } |
86 } |
83 } |
87 } |
84 |
88 |
85 // equalMap compares two maps. |
89 // equalMap compares two maps. |
86 func equalMap(fd pref.FieldDescriptor, x, y pref.Map) bool { |
90 func equalMap(fd protoreflect.FieldDescriptor, x, y protoreflect.Map) bool { |
87 if x.Len() != y.Len() { |
91 if x.Len() != y.Len() { |
88 return false |
92 return false |
89 } |
93 } |
90 equal := true |
94 equal := true |
91 x.Range(func(k pref.MapKey, vx pref.Value) bool { |
95 x.Range(func(k protoreflect.MapKey, vx protoreflect.Value) bool { |
92 vy := y.Get(k) |
96 vy := y.Get(k) |
93 equal = y.Has(k) && equalValue(fd.MapValue(), vx, vy) |
97 equal = y.Has(k) && equalValue(fd.MapValue(), vx, vy) |
94 return equal |
98 return equal |
95 }) |
99 }) |
96 return equal |
100 return equal |
97 } |
101 } |
98 |
102 |
99 // equalList compares two lists. |
103 // equalList compares two lists. |
100 func equalList(fd pref.FieldDescriptor, x, y pref.List) bool { |
104 func equalList(fd protoreflect.FieldDescriptor, x, y protoreflect.List) bool { |
101 if x.Len() != y.Len() { |
105 if x.Len() != y.Len() { |
102 return false |
106 return false |
103 } |
107 } |
104 for i := x.Len() - 1; i >= 0; i-- { |
108 for i := x.Len() - 1; i >= 0; i-- { |
105 if !equalValue(fd, x.Get(i), y.Get(i)) { |
109 if !equalValue(fd, x.Get(i), y.Get(i)) { |
108 } |
112 } |
109 return true |
113 return true |
110 } |
114 } |
111 |
115 |
112 // equalValue compares two singular values. |
116 // equalValue compares two singular values. |
113 func equalValue(fd pref.FieldDescriptor, x, y pref.Value) bool { |
117 func equalValue(fd protoreflect.FieldDescriptor, x, y protoreflect.Value) bool { |
114 switch fd.Kind() { |
118 switch fd.Kind() { |
115 case pref.BoolKind: |
119 case protoreflect.BoolKind: |
116 return x.Bool() == y.Bool() |
120 return x.Bool() == y.Bool() |
117 case pref.EnumKind: |
121 case protoreflect.EnumKind: |
118 return x.Enum() == y.Enum() |
122 return x.Enum() == y.Enum() |
119 case pref.Int32Kind, pref.Sint32Kind, |
123 case protoreflect.Int32Kind, protoreflect.Sint32Kind, |
120 pref.Int64Kind, pref.Sint64Kind, |
124 protoreflect.Int64Kind, protoreflect.Sint64Kind, |
121 pref.Sfixed32Kind, pref.Sfixed64Kind: |
125 protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind: |
122 return x.Int() == y.Int() |
126 return x.Int() == y.Int() |
123 case pref.Uint32Kind, pref.Uint64Kind, |
127 case protoreflect.Uint32Kind, protoreflect.Uint64Kind, |
124 pref.Fixed32Kind, pref.Fixed64Kind: |
128 protoreflect.Fixed32Kind, protoreflect.Fixed64Kind: |
125 return x.Uint() == y.Uint() |
129 return x.Uint() == y.Uint() |
126 case pref.FloatKind, pref.DoubleKind: |
130 case protoreflect.FloatKind, protoreflect.DoubleKind: |
127 fx := x.Float() |
131 fx := x.Float() |
128 fy := y.Float() |
132 fy := y.Float() |
129 if math.IsNaN(fx) || math.IsNaN(fy) { |
133 if math.IsNaN(fx) || math.IsNaN(fy) { |
130 return math.IsNaN(fx) && math.IsNaN(fy) |
134 return math.IsNaN(fx) && math.IsNaN(fy) |
131 } |
135 } |
132 return fx == fy |
136 return fx == fy |
133 case pref.StringKind: |
137 case protoreflect.StringKind: |
134 return x.String() == y.String() |
138 return x.String() == y.String() |
135 case pref.BytesKind: |
139 case protoreflect.BytesKind: |
136 return bytes.Equal(x.Bytes(), y.Bytes()) |
140 return bytes.Equal(x.Bytes(), y.Bytes()) |
137 case pref.MessageKind, pref.GroupKind: |
141 case protoreflect.MessageKind, protoreflect.GroupKind: |
138 return equalMessage(x.Message(), y.Message()) |
142 return equalMessage(x.Message(), y.Message()) |
139 default: |
143 default: |
140 return x.Interface() == y.Interface() |
144 return x.Interface() == y.Interface() |
141 } |
145 } |
142 } |
146 } |
143 |
147 |
144 // equalUnknown compares unknown fields by direct comparison on the raw bytes |
148 // equalUnknown compares unknown fields by direct comparison on the raw bytes |
145 // of each individual field number. |
149 // of each individual field number. |
146 func equalUnknown(x, y pref.RawFields) bool { |
150 func equalUnknown(x, y protoreflect.RawFields) bool { |
147 if len(x) != len(y) { |
151 if len(x) != len(y) { |
148 return false |
152 return false |
149 } |
153 } |
150 if bytes.Equal([]byte(x), []byte(y)) { |
154 if bytes.Equal([]byte(x), []byte(y)) { |
151 return true |
155 return true |
152 } |
156 } |
153 |
157 |
154 mx := make(map[pref.FieldNumber]pref.RawFields) |
158 mx := make(map[protoreflect.FieldNumber]protoreflect.RawFields) |
155 my := make(map[pref.FieldNumber]pref.RawFields) |
159 my := make(map[protoreflect.FieldNumber]protoreflect.RawFields) |
156 for len(x) > 0 { |
160 for len(x) > 0 { |
157 fnum, _, n := protowire.ConsumeField(x) |
161 fnum, _, n := protowire.ConsumeField(x) |
158 mx[fnum] = append(mx[fnum], x[:n]...) |
162 mx[fnum] = append(mx[fnum], x[:n]...) |
159 x = x[n:] |
163 x = x[n:] |
160 } |
164 } |