github.com/ontio/ontology@v1.14.4/vm/crossvm_codec/codec.go (about) 1 /* 2 * Copyright (C) 2018 The ontology Authors 3 * This file is part of The ontology library. 4 * 5 * The ontology is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * The ontology is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with The ontology. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 package crossvm_codec 20 21 import ( 22 "fmt" 23 "math/big" 24 "reflect" 25 26 "github.com/ontio/ontology/common" 27 "github.com/ontio/ontology/common/log" 28 ) 29 30 const ( 31 ByteArrayType byte = 0x00 32 StringType byte = 0x01 33 AddressType byte = 0x02 34 BooleanType byte = 0x03 35 IntType byte = 0x04 36 H256Type byte = 0x05 37 38 //reserved for other types 39 ListType byte = 0x10 40 41 MAX_PARAM_LENGTH = 1024 42 VERSION byte = 0 43 ) 44 45 var ERROR_PARAM_FORMAT = fmt.Errorf("error param format") 46 var ERROR_PARAM_NOT_SUPPORTED_TYPE = fmt.Errorf("error param format:not supported type") 47 48 // currently only used by test case 49 func EncodeValue(value interface{}) ([]byte, error) { 50 sink := common.NewZeroCopySink(nil) 51 switch val := value.(type) { 52 case []byte: 53 EncodeBytes(sink, val) 54 case string: 55 EncodeString(sink, val) 56 case common.Address: 57 EncodeAddress(sink, val) 58 case bool: 59 EncodeBool(sink, val) 60 case common.Uint256: 61 EncodeH256(sink, val) 62 case *big.Int: 63 err := EncodeBigInt(sink, val) 64 if err != nil { 65 return nil, err 66 } 67 case int: 68 EncodeInt128(sink, common.I128FromInt64(int64(val))) 69 case int64: 70 EncodeInt128(sink, common.I128FromInt64(val)) 71 case []interface{}: 72 err := EncodeList(sink, val) 73 if err != nil { 74 return nil, err 75 } 76 default: 77 log.Warn("encode value: unsupported type:", reflect.TypeOf(val).String()) 78 } 79 80 return sink.Bytes(), nil 81 } 82 83 func DecodeValue(source *common.ZeroCopySource) (interface{}, error) { 84 ty, eof := source.NextByte() 85 if eof { 86 return nil, ERROR_PARAM_FORMAT 87 } 88 89 switch ty { 90 case ByteArrayType: 91 size, eof := source.NextUint32() 92 if eof { 93 return nil, ERROR_PARAM_FORMAT 94 } 95 96 buf, eof := source.NextBytes(uint64(size)) 97 if eof { 98 return nil, ERROR_PARAM_FORMAT 99 } 100 101 return buf, nil 102 case StringType: 103 size, eof := source.NextUint32() 104 if eof { 105 return nil, ERROR_PARAM_FORMAT 106 } 107 108 buf, eof := source.NextBytes(uint64(size)) 109 if eof { 110 return nil, ERROR_PARAM_FORMAT 111 } 112 113 return string(buf), nil 114 case AddressType: 115 addr, eof := source.NextAddress() 116 if eof { 117 return nil, ERROR_PARAM_FORMAT 118 } 119 120 return addr, nil 121 case BooleanType: 122 by, irr, eof := source.NextBool() 123 if eof { 124 return nil, ERROR_PARAM_FORMAT 125 } 126 127 if irr { 128 return nil, ERROR_PARAM_FORMAT 129 } 130 131 return by, nil 132 case IntType: 133 val, eof := source.NextI128() 134 if eof { 135 return nil, ERROR_PARAM_FORMAT 136 } 137 138 return val.ToBigInt(), nil 139 case H256Type: 140 hash, eof := source.NextHash() 141 if eof { 142 return nil, ERROR_PARAM_FORMAT 143 } 144 145 return hash, nil 146 case ListType: 147 size, eof := source.NextUint32() 148 if eof { 149 return nil, ERROR_PARAM_FORMAT 150 } 151 152 list := make([]interface{}, 0) 153 for i := uint32(0); i < size; i++ { 154 val, err := DecodeValue(source) 155 if err != nil { 156 return nil, err 157 } 158 list = append(list, val) 159 } 160 161 return list, nil 162 default: 163 return nil, ERROR_PARAM_NOT_SUPPORTED_TYPE 164 } 165 } 166 167 func EncodeBytes(sink *common.ZeroCopySink, buf []byte) { 168 sink.WriteByte(ByteArrayType) 169 sink.WriteUint32(uint32(len(buf))) 170 sink.WriteBytes(buf) 171 } 172 173 func EncodeString(sink *common.ZeroCopySink, buf string) { 174 sink.WriteByte(StringType) 175 sink.WriteUint32(uint32(len(buf))) 176 sink.WriteBytes([]byte(buf)) 177 } 178 179 func EncodeAddress(sink *common.ZeroCopySink, addr common.Address) { 180 sink.WriteByte(AddressType) 181 sink.WriteBytes(addr[:]) 182 } 183 184 func EncodeBool(sink *common.ZeroCopySink, b bool) { 185 sink.WriteByte(BooleanType) 186 if b { 187 sink.WriteByte(byte(1)) 188 } else { 189 sink.WriteByte(byte(0)) 190 } 191 } 192 193 func EncodeH256(sink *common.ZeroCopySink, hash common.Uint256) { 194 sink.WriteByte(H256Type) 195 sink.WriteBytes(hash[:]) 196 } 197 198 func EncodeInt128(sink *common.ZeroCopySink, val common.I128) { 199 sink.WriteByte(IntType) 200 sink.WriteBytes(val[:]) 201 } 202 203 func EncodeBigInt(sink *common.ZeroCopySink, intval *big.Int) error { 204 val, err := common.I128FromBigInt(intval) 205 if err != nil { 206 return err 207 } 208 EncodeInt128(sink, val) 209 return nil 210 } 211 212 func EncodeList(sink *common.ZeroCopySink, list []interface{}) error { 213 sink.WriteByte(ListType) 214 sink.WriteUint32(uint32(len(list))) 215 for _, elem := range list { 216 switch val := elem.(type) { 217 case []byte: 218 EncodeBytes(sink, val) 219 case string: 220 EncodeString(sink, val) 221 case bool: 222 EncodeBool(sink, val) 223 case int: 224 EncodeInt128(sink, common.I128FromInt64(int64(val))) 225 case int64: 226 EncodeInt128(sink, common.I128FromInt64(val)) 227 case int32: 228 EncodeInt128(sink, common.I128FromInt64(int64(val))) 229 case uint32: 230 EncodeInt128(sink, common.I128FromInt64(int64(val))) 231 case *big.Int: 232 err := EncodeBigInt(sink, val) 233 if err != nil { 234 return err 235 } 236 case common.Address: 237 EncodeAddress(sink, val) 238 case common.Uint256: 239 EncodeH256(sink, val) 240 case []interface{}: 241 err := EncodeList(sink, val) 242 if err != nil { 243 return err 244 } 245 default: 246 return fmt.Errorf("encode list: unsupported type: %v", reflect.TypeOf(val).String()) 247 } 248 } 249 return nil 250 }