Skip to content

Commit 30a83c3

Browse files
thecampagnardsKonstantin Sidorenko
authored andcommitted
feat: allow map key pointer
1 parent 25e5d90 commit 30a83c3

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

decode.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,14 @@ func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node
17711771
mapValue.SetMapIndex(d.createDecodableValue(keyType), dstValue)
17721772
continue
17731773
}
1774+
1775+
// transform to map key pointer
1776+
for kt := keyType; kt.Kind() == reflect.Ptr; kt = kt.Elem() {
1777+
kk := reflect.New(k.Type())
1778+
kk.Elem().Set(k)
1779+
k = kk
1780+
}
1781+
17741782
if keyType.Kind() != k.Kind() {
17751783
return errors.ErrSyntax(
17761784
fmt.Sprintf("cannot convert %q type to %q type", k.Kind(), keyType.Kind()),

decode_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ func TestDecoder(t *testing.T) {
181181
source: "v: +685_230",
182182
value: map[string]int{"v": 685230},
183183
},
184+
{
185+
source: "v: +685_230",
186+
value: map[*string]int{ptr("v"): 685230},
187+
},
188+
{
189+
source: "v: +685_230",
190+
value: map[**string]int{ptr(ptr("v")): 685230},
191+
},
184192

185193
// Bools from spec
186194
{
@@ -1241,12 +1249,46 @@ c:
12411249
actual := fmt.Sprintf("%+v", value.Elem().Interface())
12421250
expect := fmt.Sprintf("%+v", test.value)
12431251
if actual != expect {
1252+
if deepMapEqual(reflect.ValueOf(test.value), value.Elem()) {
1253+
return
1254+
}
12441255
t.Fatalf("failed to test [%s], actual=[%s], expect=[%s]", test.source, actual, expect)
12451256
}
12461257
})
12471258
}
12481259
}
12491260

1261+
// deepMapEqual recursively compares two reflect.Value objects.
1262+
// It first checks if both values are of the same kind.
1263+
// Then it compares it by checking pointers value for keys and values.
1264+
func deepMapEqual(v1, v2 reflect.Value) bool {
1265+
if v1.Kind() != v2.Kind() || v1.Kind() != reflect.Map || v1.Len() != v2.Len() {
1266+
return false
1267+
}
1268+
for _, k1 := range v1.MapKeys() {
1269+
for _, k2 := range v2.MapKeys() {
1270+
if fromPtr(k1) != fromPtr(k2) {
1271+
return false
1272+
}
1273+
if fromPtr(v1.MapIndex(k1)) != fromPtr(v2.MapIndex(k2)) {
1274+
return false
1275+
}
1276+
}
1277+
}
1278+
return true
1279+
}
1280+
1281+
func fromPtr(v reflect.Value) any {
1282+
for {
1283+
if v.Kind() == reflect.Ptr {
1284+
v = v.Elem()
1285+
continue
1286+
}
1287+
break
1288+
}
1289+
return v.Interface()
1290+
}
1291+
12501292
func TestDecoder_Invalid(t *testing.T) {
12511293
tests := []struct {
12521294
src string

0 commit comments

Comments
 (0)