github.com/chain5j/chain5j-pkg@v1.0.7/collection/maps/hashmap/hashmap_rlp.go (about)

     1  // Package hashmap
     2  //
     3  // @author: xwc1125
     4  package hashmap
     5  
     6  import (
     7  	"io"
     8  	"math/big"
     9  	"reflect"
    10  
    11  	"github.com/chain5j/chain5j-pkg/codec/rlp"
    12  	"github.com/chain5j/chain5j-pkg/math"
    13  	"github.com/chain5j/chain5j-pkg/types"
    14  	"github.com/chain5j/chain5j-pkg/util/convutil"
    15  	"github.com/chain5j/chain5j-pkg/util/hexutil"
    16  	"github.com/mitchellh/mapstructure"
    17  )
    18  
    19  func (m *HashMap) EncodeRLP(w io.Writer) error {
    20  	data := m.Sort()
    21  	for i, kv := range data {
    22  		switch vv := kv.Value.(type) {
    23  		case int, int8, int16, int32, int64, float32, float64:
    24  			data[i] = KV{
    25  				Key:   kv.Key,
    26  				Value: convutil.ToUint64(vv),
    27  			}
    28  		}
    29  	}
    30  	return rlp.Encode(w, data)
    31  }
    32  
    33  func (m *HashMap) DecodeRLP(s *rlp.Stream) error {
    34  	var data []KV
    35  	if err := s.Decode(&data); err != nil {
    36  		return err
    37  	}
    38  	for _, kv := range data {
    39  		m.data[kv.Key] = kv.Value
    40  	}
    41  	return nil
    42  }
    43  
    44  // ToStruct 用map填充结构
    45  func (m *HashMap) ToStruct(out interface{}) error {
    46  	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
    47  		DecodeHook:       StringToByteSizesHookFunc,
    48  		Metadata:         nil,
    49  		Result:           out,
    50  		WeaklyTypedInput: true,
    51  	})
    52  	if err != nil {
    53  		return err
    54  	}
    55  	return decoder.Decode(m.data)
    56  }
    57  
    58  func StringToByteSizesHookFunc(
    59  	f reflect.Type,
    60  	des reflect.Type,
    61  	data interface{}) (interface{}, error) {
    62  	dataVal := reflect.Indirect(reflect.ValueOf(data))
    63  	dataKind := getKind(dataVal)
    64  	// dataType := dataVal.Type()
    65  	desKind := getKindByKind(des.Kind())
    66  
    67  	switch {
    68  	case dataKind == reflect.String:
    69  		if i, ok := parseStr(des, data.(string)); ok {
    70  			return i, nil
    71  		}
    72  	case dataKind == reflect.Slice,
    73  		dataKind == reflect.Array:
    74  		// todo xwc1125 []byte转换
    75  		dataType := dataVal.Type()
    76  		elemKind := dataType.Elem().Kind()
    77  		switch elemKind {
    78  		case reflect.Uint8:
    79  			var uints []uint8
    80  			if dataKind == reflect.Array {
    81  				uints = make([]uint8, dataVal.Len(), dataVal.Len())
    82  				for i := range uints {
    83  					uints[i] = dataVal.Index(i).Interface().(uint8)
    84  				}
    85  			} else {
    86  				uints = dataVal.Interface().([]uint8)
    87  			}
    88  			switch {
    89  			case desKind == reflect.Uint:
    90  				return convutil.BytesToUint64(uints), nil
    91  			case desKind == reflect.Int:
    92  				return convutil.BytesToInt64(uints), nil
    93  			case desKind == reflect.Bool:
    94  				return convutil.BytesToBool(uints)
    95  			default:
    96  				if i, ok := parseBytes(des, uints); ok {
    97  					return i, nil
    98  				}
    99  			}
   100  		}
   101  	}
   102  	return data, nil
   103  }
   104  
   105  func parseStr(des reflect.Type, data string) (interface{}, bool) {
   106  	switch des {
   107  	case reflect.TypeOf(types.Address{}):
   108  		address := types.HexToAddress(data)
   109  		return address, true
   110  	case reflect.TypeOf(types.Hash{}):
   111  		hash := types.HexToHash(data)
   112  		return hash, true
   113  	case reflect.TypeOf(math.HexOrDecimal256{}):
   114  		result := new(math.HexOrDecimal256)
   115  		result.UnmarshalText([]byte(data))
   116  		return result, true
   117  	case reflect.TypeOf(big.Int{}):
   118  		result := new(big.Int)
   119  		result.UnmarshalText([]byte(data))
   120  		return result, true
   121  	case reflect.TypeOf(hexutil.Bytes{}):
   122  		result := hexutil.MustDecode(data)
   123  		return result, true
   124  	}
   125  	return data, false
   126  }
   127  func parseBytes(des reflect.Type, data []byte) (interface{}, bool) {
   128  	switch des {
   129  	case reflect.TypeOf(types.Address{}):
   130  		if len(data) == types.AddressLength {
   131  			return types.BytesToAddress(data), true
   132  		}
   133  		return types.HexToAddress(string(data)), true
   134  	case reflect.TypeOf(types.Hash{}):
   135  		if len(data) == types.HashLength {
   136  			return types.BytesToHash(data), true
   137  		}
   138  		return types.HexToHash(string(data)), true
   139  	case reflect.TypeOf(math.HexOrDecimal256{}):
   140  		result := new(math.HexOrDecimal256)
   141  		result.UnmarshalText(data)
   142  		return result, true
   143  	case reflect.TypeOf(big.Int{}):
   144  		result := new(big.Int)
   145  		result.UnmarshalText(data)
   146  		return result, true
   147  	case reflect.TypeOf(hexutil.Bytes{}):
   148  		return data, true
   149  	}
   150  	return data, false
   151  }
   152  
   153  func getKind(val reflect.Value) reflect.Kind {
   154  	kind := val.Kind()
   155  	return getKindByKind(kind)
   156  }
   157  func getKindByKind(kind reflect.Kind) reflect.Kind {
   158  	switch {
   159  	case kind >= reflect.Int && kind <= reflect.Int64:
   160  		return reflect.Int
   161  	case kind >= reflect.Uint && kind <= reflect.Uint64:
   162  		return reflect.Uint
   163  	case kind >= reflect.Float32 && kind <= reflect.Float64:
   164  		return reflect.Float32
   165  	default:
   166  		return kind
   167  	}
   168  }