mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 03:41:34 +00:00
smartcontract: process slices via reflection in NewParameterFromValue
Pros: * less code * handles more types Cons: * slow This code is not likely to be on the hot path and it is exactly the one used by actors for making calls of various kinds. Supporting more types is more important here than raw speed. Signed-off-by: Roman Khimov <roman@nspcc.ru>
This commit is contained in:
parent
a123b75fd9
commit
22c6ab4de9
1 changed files with 18 additions and 56 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
@ -265,7 +266,7 @@ func NewParameterFromString(in string) (*Parameter, error) {
|
||||||
// NewParameterFromValue infers Parameter type from the value given and adjusts
|
// NewParameterFromValue infers Parameter type from the value given and adjusts
|
||||||
// the value if needed. It does not copy the value if it can avoid doing so. All
|
// the value if needed. It does not copy the value if it can avoid doing so. All
|
||||||
// regular integers, util.*, keys.PublicKey*, string and bool types are supported,
|
// regular integers, util.*, keys.PublicKey*, string and bool types are supported,
|
||||||
// slice of byte slices is accepted and converted as well. [errors.ErrUnsupported]
|
// slices of various kinds are converted as well. [errors.ErrUnsupported]
|
||||||
// will be returned for types that can't be used now.
|
// will be returned for types that can't be used now.
|
||||||
func NewParameterFromValue(value any) (Parameter, error) {
|
func NewParameterFromValue(value any) (Parameter, error) {
|
||||||
var result = Parameter{
|
var result = Parameter{
|
||||||
|
@ -345,69 +346,30 @@ func NewParameterFromValue(value any) (Parameter, error) {
|
||||||
case []Parameter:
|
case []Parameter:
|
||||||
result.Type = ArrayType
|
result.Type = ArrayType
|
||||||
result.Value = slices.Clone(v)
|
result.Value = slices.Clone(v)
|
||||||
case [][]byte:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []string:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []bool:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []*big.Int:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []int8:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []int16:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []uint16:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []int32:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []uint32:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []int:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []uint:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []int64:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []uint64:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []*Parameter:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []Convertible:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []util.Uint160:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []util.Uint256:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []*util.Uint160:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []*util.Uint256:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []keys.PublicKey:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []*keys.PublicKey:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case keys.PublicKeys:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case []any:
|
|
||||||
return newArrayParameter(v)
|
|
||||||
case nil:
|
case nil:
|
||||||
result.Type = AnyType
|
result.Type = AnyType
|
||||||
default:
|
default:
|
||||||
return result, fmt.Errorf("%w: %T type", errors.ErrUnsupported, value)
|
rv := reflect.ValueOf(value)
|
||||||
|
switch rv.Kind() {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
res := make([]Parameter, 0, rv.Len())
|
||||||
|
for i := range rv.Len() {
|
||||||
|
elem, err := NewParameterFromValue(rv.Index(i).Interface())
|
||||||
|
if err != nil {
|
||||||
|
return result, fmt.Errorf("array index %d: %w", i, err)
|
||||||
|
}
|
||||||
|
res = append(res, elem)
|
||||||
|
}
|
||||||
|
result.Type = ArrayType
|
||||||
|
result.Value = res
|
||||||
|
default:
|
||||||
|
return result, fmt.Errorf("%w: %T type", errors.ErrUnsupported, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArrayParameter[E any, S ~[]E](values S) (Parameter, error) {
|
|
||||||
arr, err := newArrayOfParameters(values)
|
|
||||||
if err != nil {
|
|
||||||
return Parameter{}, err
|
|
||||||
}
|
|
||||||
return Parameter{Type: ArrayType, Value: arr}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newArrayOfParameters[E any, S ~[]E](values S) ([]Parameter, error) {
|
func newArrayOfParameters[E any, S ~[]E](values S) ([]Parameter, error) {
|
||||||
res := make([]Parameter, 0, len(values))
|
res := make([]Parameter, 0, len(values))
|
||||||
for i := range values {
|
for i := range values {
|
||||||
|
|
Loading…
Reference in a new issue