Skip to content

Commit

Permalink
nits
Browse files Browse the repository at this point in the history
  • Loading branch information
containerman17 committed Oct 10, 2024
1 parent c4253e7 commit cb969a9
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 34 deletions.
39 changes: 18 additions & 21 deletions abi/dynamic/reflect_marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package dynamic

import (
"encoding/json"
"errors"
"fmt"
"reflect"
"regexp"
Expand All @@ -20,13 +21,11 @@ import (
"github.com/ava-labs/hypersdk/consts"
)

// Matches fixed-size arrays like [32]uint8
var fixedSizeArrayRegex = regexp.MustCompile(`^\[(\d+)\](.+)$`)
var ErrTypeNotFound = errors.New("type not found in ABI")

func Marshal(inputABI abi.ABI, typeName string, jsonData string) ([]byte, error) {
_, ok := findABIType(inputABI, typeName)
if !ok {
return nil, fmt.Errorf("type %s not found in ABI", typeName)
if _, ok := findABIType(inputABI, typeName); !ok {
return nil, fmt.Errorf("marshalling %s: %w", typeName, ErrTypeNotFound)
}

typeCache := make(map[string]reflect.Type)
Expand All @@ -38,52 +37,51 @@ func Marshal(inputABI abi.ABI, typeName string, jsonData string) ([]byte, error)

value := reflect.New(typ).Interface()

err = json.Unmarshal([]byte(jsonData), value)
if err != nil {
if err := json.Unmarshal([]byte(jsonData), value); err != nil {
return nil, fmt.Errorf("failed to unmarshal JSON data: %w", err)
}

writer := codec.NewWriter(0, consts.NetworkSizeLimit)
err = codec.LinearCodec.MarshalInto(value, writer.Packer)
if err != nil {
if err := codec.LinearCodec.MarshalInto(value, writer.Packer); err != nil {
return nil, fmt.Errorf("failed to marshal struct: %w", err)
}

return writer.Bytes(), nil
}

func Unmarshal(inputABI abi.ABI, typeName string, data []byte) (string, error) {
_, ok := findABIType(inputABI, typeName)
if !ok {
return "", fmt.Errorf("type %s not found in ABI", typeName)
if _, ok := findABIType(inputABI, typeName); !ok {
return "", fmt.Errorf("unmarshalling %s: %w", typeName, ErrTypeNotFound)
}

typeCache := make(map[string]reflect.Type)

dynamicType, err := getReflectType(typeName, inputABI, typeCache)
typ, err := getReflectType(typeName, inputABI, typeCache)
if err != nil {
return "", fmt.Errorf("failed to get reflect type: %w", err)
}

dynamicValue := reflect.New(dynamicType).Interface()
value := reflect.New(typ).Interface()

packer := wrappers.Packer{
Bytes: data,
MaxSize: consts.NetworkSizeLimit,
}
err = codec.LinearCodec.UnmarshalFrom(&packer, dynamicValue)
if err != nil {
if err := codec.LinearCodec.UnmarshalFrom(&packer, value); err != nil {
return "", fmt.Errorf("failed to unmarshal data: %w", err)
}

jsonData, err := json.Marshal(dynamicValue)
jsonData, err := json.Marshal(value)
if err != nil {
return "", fmt.Errorf("failed to marshal struct to JSON: %w", err)
}

return string(jsonData), nil
}

// Matches fixed-size arrays like [32]uint8
var fixedSizeArrayRegex = regexp.MustCompile(`^\[(\d+)\](.+)$`)

func getReflectType(abiTypeName string, inputABI abi.ABI, typeCache map[string]reflect.Type) (reflect.Type, error) {
switch abiTypeName {
case "string":
Expand Down Expand Up @@ -117,8 +115,8 @@ func getReflectType(abiTypeName string, inputABI abi.ABI, typeCache map[string]r
}

// golang arrays
match := fixedSizeArrayRegex.FindStringSubmatch(abiTypeName) // ^\[(\d+)\](.+)$
if match != nil {

if match := fixedSizeArrayRegex.FindStringSubmatch(abiTypeName); match != nil {
sizeStr := match[1]
size, err := strconv.Atoi(sizeStr)
if err != nil {
Expand All @@ -132,8 +130,7 @@ func getReflectType(abiTypeName string, inputABI abi.ABI, typeCache map[string]r
}

// For custom types, recursively construct the struct type
cachedType, ok := typeCache[abiTypeName]
if ok {
if cachedType, ok := typeCache[abiTypeName]; ok {
return cachedType, nil
}

Expand Down
22 changes: 9 additions & 13 deletions abi/dynamic/reflect_marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,15 @@ func TestDynamicMarshalErrors(t *testing.T) {
err := json.Unmarshal(abiJSON, &abi)
require.NoError(err)

t.Run("malformed JSON", func(t *testing.T) {
malformedJSON := `{"uint8": 42, "uint16": 1000, "uint32": 100000, "uint64": 10000000000, "int8": -42, "int16": -1000, "int32": -100000, "int64": -10000000000,`
_, err := Marshal(abi, "MockObjectAllNumbers", malformedJSON)
require.Error(err)
require.Contains(err.Error(), "unexpected end of JSON input")
})

t.Run("wrong struct name", func(t *testing.T) {
jsonData := mustReadFile(t, "../testdata/numbers.json")
_, err := Marshal(abi, "NonExistentObject", string(jsonData))
require.Error(err)
require.Contains(err.Error(), "type NonExistentObject not found in ABI")
})
// Test malformed JSON
malformedJSON := `{"uint8": 42, "uint16": 1000, "uint32": 100000, "uint64": 10000000000, "int8": -42, "int16": -1000, "int32": -100000, "int64": -10000000000,`
_, err = Marshal(abi, "MockObjectAllNumbers", malformedJSON)
require.Contains(err.Error(), "failed to unmarshal JSON data")

// Test wrong struct name
jsonData := mustReadFile(t, "../testdata/numbers.json")
_, err = Marshal(abi, "NonExistentObject", string(jsonData))
require.ErrorIs(err, ErrTypeNotFound)
}

func mustReadFile(t *testing.T, path string) []byte {
Expand Down

0 comments on commit cb969a9

Please sign in to comment.