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 }