mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-25 03:47:18 +00:00
smartcontract: add support for maps in NewParameterFromValue
It's just not possible to use maps in invokers/actors without this. And maps have too many combinations to try pushing them into a type switch, that's where reflection kicks in and solves it easily. Signed-off-by: Roman Khimov <roman@nspcc.ru>
This commit is contained in:
parent
22c6ab4de9
commit
db2956f1af
3 changed files with 70 additions and 8 deletions
|
@ -83,17 +83,17 @@ func TestInvoker(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, resExp, res)
|
||||
|
||||
_, err = inv.Verify(util.Uint160{}, nil, make(map[int]int))
|
||||
_, err = inv.Verify(util.Uint160{}, nil, make(chan struct{}))
|
||||
require.Error(t, err)
|
||||
|
||||
_, err = inv.Call(util.Uint160{}, "method", make(map[int]int))
|
||||
_, err = inv.Call(util.Uint160{}, "method", make(chan struct{}))
|
||||
require.Error(t, err)
|
||||
|
||||
res, err = inv.CallAndExpandIterator(util.Uint160{}, "method", 10, 42)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, resExp, res)
|
||||
|
||||
_, err = inv.CallAndExpandIterator(util.Uint160{}, "method", 10, make(map[int]int))
|
||||
_, err = inv.CallAndExpandIterator(util.Uint160{}, "method", 10, make(chan struct{}))
|
||||
require.Error(t, err)
|
||||
}
|
||||
t.Run("standard", func(t *testing.T) {
|
||||
|
|
|
@ -362,6 +362,22 @@ func NewParameterFromValue(value any) (Parameter, error) {
|
|||
}
|
||||
result.Type = ArrayType
|
||||
result.Value = res
|
||||
case reflect.Map:
|
||||
res := make([]ParameterPair, 0, rv.Len())
|
||||
iter := rv.MapRange()
|
||||
for iter.Next() {
|
||||
k, err := NewParameterFromValue(iter.Key().Interface())
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("map key: %w", err)
|
||||
}
|
||||
v, err := NewParameterFromValue(iter.Value().Interface())
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("map value: %w", err)
|
||||
}
|
||||
res = append(res, ParameterPair{Key: k, Value: v})
|
||||
}
|
||||
result.Type = MapType
|
||||
result.Value = res
|
||||
default:
|
||||
return result, fmt.Errorf("%w: %T type", errors.ErrUnsupported, value)
|
||||
}
|
||||
|
|
|
@ -887,12 +887,58 @@ func TestParameterFromValue(t *testing.T) {
|
|||
err: "invalid i value",
|
||||
},
|
||||
{
|
||||
value: make(map[string]int),
|
||||
err: "unsupported operation: map[string]int type",
|
||||
value: make(map[string]int),
|
||||
expType: MapType,
|
||||
expVal: []ParameterPair{},
|
||||
},
|
||||
{
|
||||
value: []any{1, 2, make(map[string]int)},
|
||||
err: "unsupported operation: map[string]int type",
|
||||
value: make(map[string]int),
|
||||
expType: MapType,
|
||||
expVal: []ParameterPair{},
|
||||
},
|
||||
{
|
||||
value: map[string]string{"key": "value"},
|
||||
expType: MapType,
|
||||
expVal: []ParameterPair{{
|
||||
Key: Parameter{
|
||||
Type: StringType,
|
||||
Value: "key",
|
||||
},
|
||||
Value: Parameter{
|
||||
Type: StringType,
|
||||
Value: "value",
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
value: map[int]int64{42: 100500},
|
||||
expType: MapType,
|
||||
expVal: []ParameterPair{{
|
||||
Key: Parameter{
|
||||
Type: IntegerType,
|
||||
Value: big.NewInt(42),
|
||||
},
|
||||
Value: Parameter{
|
||||
Type: IntegerType,
|
||||
Value: big.NewInt(100500),
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
value: make(chan int),
|
||||
err: "unsupported operation: chan int type",
|
||||
},
|
||||
{
|
||||
value: []any{1, 2, make(chan int)},
|
||||
err: "unsupported operation: chan int type",
|
||||
},
|
||||
{
|
||||
value: map[string]chan int{"aaa": make(chan int)},
|
||||
err: "unsupported operation: chan int type",
|
||||
},
|
||||
{
|
||||
value: map[error]string{errors.New("some"): "value"},
|
||||
err: "unsupported operation: *errors.errorString type",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -924,6 +970,6 @@ func TestParametersFromValues(t *testing.T) {
|
|||
Type: ByteArrayType,
|
||||
Value: []byte{3, 2, 1},
|
||||
}}, res)
|
||||
_, err = NewParametersFromValues(42, make(map[int]int), []byte{3, 2, 1})
|
||||
_, err = NewParametersFromValues(42, make(chan int), []byte{3, 2, 1})
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue