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  }