Skip to content

Commit 442c558

Browse files
authored
Merge pull request #128 from jennybuckley/fix-1.0-compare
Cherrypick #126 to 1.0 - Implement equality for Values
2 parents 6149e45 + 08cde4d commit 442c558

File tree

2 files changed

+191
-51
lines changed

2 files changed

+191
-51
lines changed

value/less_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,9 @@ func TestValueLess(t *testing.T) {
296296
t.Run(table[i].name, func(t *testing.T) {
297297
tt := table[i]
298298
if tt.eq {
299+
if !tt.a.Equals(tt.b) {
300+
t.Errorf("oops, a != b: %#v, %#v", tt.a, tt.b)
301+
}
299302
if tt.a.Less(tt.b) {
300303
t.Errorf("oops, a < b: %#v, %#v", tt.a, tt.b)
301304
}
@@ -307,6 +310,19 @@ func TestValueLess(t *testing.T) {
307310
if tt.b.Less(tt.b) {
308311
t.Errorf("oops, b < a: %#v, %#v", tt.b, tt.a)
309312
}
313+
314+
if tt.eq {
315+
if tt.a.Compare(tt.b) != 0 || tt.b.Compare(tt.b) != 0 {
316+
t.Errorf("oops, a != b: %#v, %#v", tt.a, tt.b)
317+
}
318+
} else {
319+
if !(tt.a.Compare(tt.b) < 0) {
320+
t.Errorf("oops, a is not less than b: %#v, %#v", tt.a, tt.b)
321+
}
322+
if !(tt.b.Compare(tt.a) > 0) {
323+
t.Errorf("oops, b is not more than a: %#v, %#v", tt.a, tt.b)
324+
}
325+
}
310326
})
311327
}
312328

value/value.go

+175-51
Original file line numberDiff line numberDiff line change
@@ -36,93 +36,186 @@ type Value struct {
3636

3737
// Equals returns true iff the two values are equal.
3838
func (v Value) Equals(rhs Value) bool {
39-
return !v.Less(rhs) && !rhs.Less(v)
39+
if v.FloatValue != nil || rhs.FloatValue != nil {
40+
var lf float64
41+
if v.FloatValue != nil {
42+
lf = float64(*v.FloatValue)
43+
} else if v.IntValue != nil {
44+
lf = float64(*v.IntValue)
45+
} else {
46+
return false
47+
}
48+
var rf float64
49+
if rhs.FloatValue != nil {
50+
rf = float64(*rhs.FloatValue)
51+
} else if rhs.IntValue != nil {
52+
rf = float64(*rhs.IntValue)
53+
} else {
54+
return false
55+
}
56+
return lf == rf
57+
}
58+
if v.IntValue != nil {
59+
if rhs.IntValue != nil {
60+
return *v.IntValue == *rhs.IntValue
61+
}
62+
return false
63+
}
64+
if v.StringValue != nil {
65+
if rhs.StringValue != nil {
66+
return *v.StringValue == *rhs.StringValue
67+
}
68+
return false
69+
}
70+
if v.BooleanValue != nil {
71+
if rhs.BooleanValue != nil {
72+
return *v.BooleanValue == *rhs.BooleanValue
73+
}
74+
return false
75+
}
76+
if v.ListValue != nil {
77+
if rhs.ListValue != nil {
78+
return v.ListValue.Equals(rhs.ListValue)
79+
}
80+
return false
81+
}
82+
if v.MapValue != nil {
83+
if rhs.MapValue != nil {
84+
return v.MapValue.Equals(rhs.MapValue)
85+
}
86+
return false
87+
}
88+
if v.Null {
89+
if rhs.Null {
90+
return true
91+
}
92+
return false
93+
}
94+
// No field is set, on either objects.
95+
return true
4096
}
4197

4298
// Less provides a total ordering for Value (so that they can be sorted, even
4399
// if they are of different types).
44100
func (v Value) Less(rhs Value) bool {
101+
return v.Compare(rhs) == -1
102+
}
103+
104+
// Compare provides a total ordering for Value (so that they can be
105+
// sorted, even if they are of different types). The result will be 0 if
106+
// v==rhs, -1 if v < rhs, and +1 if v > rhs.
107+
func (v Value) Compare(rhs Value) int {
45108
if v.FloatValue != nil {
46109
if rhs.FloatValue == nil {
47110
// Extra: compare floats and ints numerically.
48111
if rhs.IntValue != nil {
49-
return float64(*v.FloatValue) < float64(*rhs.IntValue)
112+
return v.FloatValue.Compare(Float(*rhs.IntValue))
50113
}
51-
return true
114+
return -1
52115
}
53-
return *v.FloatValue < *rhs.FloatValue
116+
return v.FloatValue.Compare(*rhs.FloatValue)
54117
} else if rhs.FloatValue != nil {
55118
// Extra: compare floats and ints numerically.
56119
if v.IntValue != nil {
57-
return float64(*v.IntValue) < float64(*rhs.FloatValue)
120+
return Float(*v.IntValue).Compare(*rhs.FloatValue)
58121
}
59-
return false
122+
return 1
60123
}
61124

62125
if v.IntValue != nil {
63126
if rhs.IntValue == nil {
64-
return true
127+
return -1
65128
}
66-
return *v.IntValue < *rhs.IntValue
129+
return v.IntValue.Compare(*rhs.IntValue)
67130
} else if rhs.IntValue != nil {
68-
return false
131+
return 1
69132
}
70133

71134
if v.StringValue != nil {
72135
if rhs.StringValue == nil {
73-
return true
136+
return -1
74137
}
75-
return *v.StringValue < *rhs.StringValue
138+
return strings.Compare(string(*v.StringValue), string(*rhs.StringValue))
76139
} else if rhs.StringValue != nil {
77-
return false
140+
return 1
78141
}
79142

80143
if v.BooleanValue != nil {
81144
if rhs.BooleanValue == nil {
82-
return true
145+
return -1
83146
}
84-
if *v.BooleanValue == *rhs.BooleanValue {
85-
return false
86-
}
87-
return *v.BooleanValue == false
147+
return v.BooleanValue.Compare(*rhs.BooleanValue)
88148
} else if rhs.BooleanValue != nil {
89-
return false
149+
return 1
90150
}
91151

92152
if v.ListValue != nil {
93153
if rhs.ListValue == nil {
94-
return true
154+
return -1
95155
}
96-
return v.ListValue.Less(rhs.ListValue)
156+
return v.ListValue.Compare(rhs.ListValue)
97157
} else if rhs.ListValue != nil {
98-
return false
158+
return 1
99159
}
100160
if v.MapValue != nil {
101161
if rhs.MapValue == nil {
102-
return true
162+
return -1
103163
}
104-
return v.MapValue.Less(rhs.MapValue)
164+
return v.MapValue.Compare(rhs.MapValue)
105165
} else if rhs.MapValue != nil {
106-
return false
166+
return 1
107167
}
108168
if v.Null {
109169
if !rhs.Null {
110-
return true
170+
return -1
111171
}
112-
return false
172+
return 0
113173
} else if rhs.Null {
114-
return false
174+
return 1
115175
}
116176

117177
// Invalid Value-- nothing is set.
118-
return false
178+
return 0
119179
}
120180

121181
type Int int64
122182
type Float float64
123183
type String string
124184
type Boolean bool
125185

186+
// Compare compares integers. The result will be 0 if i==rhs, -1 if i <
187+
// rhs, and +1 if i > rhs.
188+
func (i Int) Compare(rhs Int) int {
189+
if i > rhs {
190+
return 1
191+
} else if i < rhs {
192+
return -1
193+
}
194+
return 0
195+
}
196+
197+
// Compare compares floats. The result will be 0 if f==rhs, -1 if f <
198+
// rhs, and +1 if f > rhs.
199+
func (f Float) Compare(rhs Float) int {
200+
if f > rhs {
201+
return 1
202+
} else if f < rhs {
203+
return -1
204+
}
205+
return 0
206+
}
207+
208+
// Compare compares booleans. The result will be 0 if b==rhs, -1 if b <
209+
// rhs, and +1 if b > rhs.
210+
func (b Boolean) Compare(rhs Boolean) int {
211+
if b == rhs {
212+
return 0
213+
} else if b == false {
214+
return -1
215+
}
216+
return 1
217+
}
218+
126219
// Field is an individual key-value pair.
127220
type Field struct {
128221
Name string
@@ -134,29 +227,44 @@ type List struct {
134227
Items []Value
135228
}
136229

230+
// Equals compares two lists lexically.
231+
func (l *List) Equals(rhs *List) bool {
232+
if len(l.Items) != len(rhs.Items) {
233+
return false
234+
}
235+
236+
for i, lv := range l.Items {
237+
if !lv.Equals(rhs.Items[i]) {
238+
return false
239+
}
240+
}
241+
return true
242+
}
243+
137244
// Less compares two lists lexically.
138245
func (l *List) Less(rhs *List) bool {
246+
return l.Compare(rhs) == -1
247+
}
248+
249+
// Compare compares two lists lexically. The result will be 0 if l==rhs, -1
250+
// if l < rhs, and +1 if l > rhs.
251+
func (l *List) Compare(rhs *List) int {
139252
i := 0
140253
for {
141254
if i >= len(l.Items) && i >= len(rhs.Items) {
142255
// Lists are the same length and all items are equal.
143-
return false
256+
return 0
144257
}
145258
if i >= len(l.Items) {
146259
// LHS is shorter.
147-
return true
260+
return -1
148261
}
149262
if i >= len(rhs.Items) {
150263
// RHS is shorter.
151-
return false
264+
return 1
152265
}
153-
if l.Items[i].Less(rhs.Items[i]) {
154-
// LHS is less; return
155-
return true
156-
}
157-
if rhs.Items[i].Less(l.Items[i]) {
158-
// RHS is less; return
159-
return false
266+
if c := l.Items[i].Compare(rhs.Items[i]); c != 0 {
267+
return c
160268
}
161269
// The items are equal; continue.
162270
i++
@@ -191,8 +299,30 @@ func (m *Map) computeOrder() []int {
191299
return m.order
192300
}
193301

302+
// Equals compares two maps lexically.
303+
func (m *Map) Equals(rhs *Map) bool {
304+
if len(m.Items) != len(rhs.Items) {
305+
return false
306+
}
307+
for _, lfield := range m.Items {
308+
rfield, ok := rhs.Get(lfield.Name)
309+
if !ok {
310+
return false
311+
}
312+
if !lfield.Value.Equals(rfield.Value) {
313+
return false
314+
}
315+
}
316+
return true
317+
}
318+
194319
// Less compares two maps lexically.
195320
func (m *Map) Less(rhs *Map) bool {
321+
return m.Compare(rhs) == -1
322+
}
323+
324+
// Compare compares two maps lexically.
325+
func (m *Map) Compare(rhs *Map) int {
196326
var noAllocL, noAllocR [2]int
197327
var morder, rorder []int
198328

@@ -238,28 +368,22 @@ func (m *Map) Less(rhs *Map) bool {
238368
for {
239369
if i >= len(morder) && i >= len(rorder) {
240370
// Maps are the same length and all items are equal.
241-
return false
371+
return 0
242372
}
243373
if i >= len(morder) {
244374
// LHS is shorter.
245-
return true
375+
return -1
246376
}
247377
if i >= len(rorder) {
248378
// RHS is shorter.
249-
return false
379+
return 1
250380
}
251381
fa, fb := &m.Items[morder[i]], &rhs.Items[rorder[i]]
252-
if fa.Name != fb.Name {
253-
// the map having the field name that sorts lexically less is "less"
254-
return fa.Name < fb.Name
382+
if c := strings.Compare(fa.Name, fb.Name); c != 0 {
383+
return c
255384
}
256-
if fa.Value.Less(fb.Value) {
257-
// LHS is less; return
258-
return true
259-
}
260-
if fb.Value.Less(fa.Value) {
261-
// RHS is less; return
262-
return false
385+
if c := fa.Value.Compare(fb.Value); c != 0 {
386+
return c
263387
}
264388
// The items are equal; continue.
265389
i++

0 commit comments

Comments
 (0)