Skip to content

Commit 045fe57

Browse files
authored
fix: support for list/map as map key in PlutusData (#112)
Fixes #111 Signed-off-by: Aurora Gaffney <[email protected]>
1 parent 02249d2 commit 045fe57

File tree

3 files changed

+87
-27
lines changed

3 files changed

+87
-27
lines changed

data/data_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,53 @@ var testDefs = []struct {
107107
// 102([999, [_ 6, 7]])
108108
CborHex: "d866821903e79f0607ff",
109109
},
110+
{
111+
Data: NewMap(
112+
[][2]PlutusData{
113+
{
114+
NewList(
115+
NewInteger(big.NewInt(1)),
116+
NewInteger(big.NewInt(2)),
117+
),
118+
NewMap(
119+
[][2]PlutusData{
120+
{
121+
NewList(
122+
NewByteString(nil),
123+
),
124+
NewConstr(
125+
0,
126+
NewInteger(big.NewInt(2)),
127+
NewInteger(big.NewInt(1)),
128+
),
129+
},
130+
},
131+
),
132+
},
133+
},
134+
),
135+
// {[_ 1, 2]: {[_ h'']: 121_0([_ 2, 1])}}
136+
CborHex: "a19f0102ffa19f40ffd8799f0201ff",
137+
},
138+
{
139+
Data: NewMap(
140+
[][2]PlutusData{
141+
{
142+
NewMap(
143+
[][2]PlutusData{
144+
{
145+
NewInteger(big.NewInt(1)),
146+
NewInteger(big.NewInt(2)),
147+
},
148+
},
149+
),
150+
NewInteger(big.NewInt(3)),
151+
},
152+
},
153+
),
154+
// {{1: 2}: 3}
155+
CborHex: "a1a1010203",
156+
},
110157
}
111158

112159
func TestPlutusDataEncode(t *testing.T) {

data/decode.go

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,40 +60,58 @@ func decodeCborRaw(data []byte) (any, error) {
6060
}
6161
}
6262

63-
func decodeCborRawList(data []byte) ([]any, error) {
63+
func decodeCborRawList(data []byte) (any, error) {
6464
var tmpData []cbor.RawMessage
6565
if err := cbor.Unmarshal(data, &tmpData); err != nil {
6666
return nil, err
6767
}
68-
ret := make([]any, len(tmpData))
68+
tmpItems := make([]PlutusData, len(tmpData))
6969
for i, item := range tmpData {
7070
tmp, err := decodeCborRaw(item)
7171
if err != nil {
7272
return nil, err
7373
}
74-
ret[i] = tmp
74+
tmpPd, err := decodeRaw(tmp)
75+
if err != nil {
76+
return nil, err
77+
}
78+
tmpItems[i] = tmpPd
7579
}
76-
return ret, nil
80+
return NewList(tmpItems...), nil
7781
}
7882

79-
func decodeCborRawMap(data []byte) (map[any]any, error) {
83+
func decodeCborRawMap(data []byte) (any, error) {
8084
var tmpData map[RawMessageStr]RawMessageStr
8185
if err := cbor.Unmarshal(data, &tmpData); err != nil {
8286
return nil, err
8387
}
84-
ret := make(map[any]any, len(tmpData))
88+
pairs := make([][2]PlutusData, 0, len(tmpData))
8589
for k, v := range tmpData {
8690
tmpKey, err := decodeCborRaw(k.Bytes())
8791
if err != nil {
8892
return nil, err
8993
}
94+
tmpKeyPd, err := decodeRaw(tmpKey)
95+
if err != nil {
96+
return nil, err
97+
}
9098
tmpVal, err := decodeCborRaw(v.Bytes())
9199
if err != nil {
92100
return nil, err
93101
}
94-
ret[tmpKey] = tmpVal
102+
tmpValPd, err := decodeRaw(tmpVal)
103+
if err != nil {
104+
return nil, err
105+
}
106+
pairs = append(
107+
pairs,
108+
[2]PlutusData{
109+
tmpKeyPd,
110+
tmpValPd,
111+
},
112+
)
95113
}
96-
return ret, nil
114+
return NewMap(pairs), nil
97115
}
98116

99117
// decodeRaw converts a raw CBOR-decoded value into PlutusData.
@@ -154,6 +172,12 @@ func decodeRaw(v any) (PlutusData, error) {
154172
case *Integer:
155173
return x, nil
156174

175+
case *List:
176+
return x, nil
177+
178+
case *Map:
179+
return x, nil
180+
157181
default:
158182
return nil, fmt.Errorf("unsupported CBOR type for PlutusData: %T", x)
159183
}
@@ -217,29 +241,16 @@ func decodeConstr(tag uint64, content cbor.RawMessage) (PlutusData, error) {
217241
if err != nil {
218242
return nil, err
219243
}
220-
arr, ok := tmpData.([]any)
244+
tmpList, ok := tmpData.(*List)
221245
if !ok {
222246
return nil, fmt.Errorf(
223247
"expected array for Constr tag %d, got %T",
224248
tag,
225-
content,
249+
tmpData,
226250
)
227251
}
228252

229-
fields := make([]PlutusData, len(arr))
230-
231-
for i, item := range arr {
232-
pd, err := decodeRaw(item)
233-
if err != nil {
234-
return nil, fmt.Errorf(
235-
"failed to decode Constr field %d: %w",
236-
i,
237-
err,
238-
)
239-
}
240-
241-
fields[i] = pd
242-
}
253+
fields := tmpList.Items
243254

244255
return NewConstr(uint(tag), fields...), nil
245256
}

data/encode.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,15 @@ func encodeMap(m *Map) (any, error) {
100100
if err != nil {
101101
return nil, fmt.Errorf("failed to encode map key: %w", err)
102102
}
103-
103+
keyRaw, err := cbor.Marshal(key)
104+
if err != nil {
105+
return nil, fmt.Errorf("encode map key: %w", err)
106+
}
104107
value, err := encodeToRaw(pair[1])
105108
if err != nil {
106109
return nil, fmt.Errorf("failed to encode map value: %w", err)
107110
}
108-
109-
result[key] = value
111+
result[RawMessageStr(string(keyRaw))] = value
110112
}
111113

112114
return result, nil

0 commit comments

Comments
 (0)