gitee.com/lh-her-team/common@v1.5.1/serialize/easycodec.go (about)

     1  /*
     2  herbt contract serialization of data interaction
     3  serialization format :
     4      magicNum + ecVersion + reserved + itemCount + (keyType + keyLen + key + valType + valLen + val)*
     5  
     6   	magicNum: 	byte[4], is the identity easycodec serialized, is []byte("hec") []byte{99, 109, 101, 99},
     7  		"hec" mean herbt easycodec,
     8   	ecVersion: 	byte[4]	easycodec version, []byte("v1.0") []byte{118, 49, 46, 48}
     9  	reserved:  	byte[4]	reserved field, 8 byte, []byte{255, 255, 255, 255,255, 255, 255, 255}
    10  	itemCount:  byte[4] number of kvPair, le int32
    11  	keyType:  	byte[4], le int32
    12  	keyLen:  	byte[4], le int32
    13  	keyType:  	byte[keyLen]
    14  	valType:  	byte[4], le int32
    15  	valLen:  	byte[4], le int32
    16  	val:  		byte[valLen]
    17  */
    18  
    19  package serialize
    20  
    21  import (
    22  	"bytes"
    23  	"encoding/base64"
    24  	"errors"
    25  	"sort"
    26  	"strconv"
    27  	"strings"
    28  )
    29  
    30  var ecMagicNum = []byte{99, 109, 101, 99} // "cmec"
    31  var ecVersion = []byte{118, 49, 46, 48}   // "v1.0"
    32  var ecReserved = []byte{255, 255, 255, 255, 255, 255, 255, 255}
    33  
    34  //var ecHeader = []byte{99, 109, 101, 99, 118, 49, 46, 48, 255, 255, 255, 255, 255, 255, 255, 255}
    35  //
    36  type EasyKeyType int32
    37  type EasyValueType int32
    38  
    39  const (
    40  	EasyKeyType_SYSTEM EasyKeyType = 0
    41  	EasyKeyType_USER   EasyKeyType = 1
    42  
    43  	EasyValueType_INT32  EasyValueType = 0
    44  	EasyValueType_STRING EasyValueType = 1
    45  	EasyValueType_BYTES  EasyValueType = 2
    46  
    47  	MAX_KEY_COUNT    = 128
    48  	MAX_KEY_LEN      = 64
    49  	MAX_VALUE_LEN    = 1024 * 1024
    50  	MIN_LEN          = 20
    51  	EC_MAGIC_NUM_LEN = 4
    52  	EC_VERSION_LEN   = 4
    53  	EC_RESERVED_LEN  = 8
    54  )
    55  
    56  type EasyCodec struct {
    57  	items []*EasyCodecItem
    58  }
    59  
    60  func NewEasyCodec() *EasyCodec {
    61  	items := make([]*EasyCodecItem, 0)
    62  	return &EasyCodec{items}
    63  }
    64  
    65  func NewEasyCodecWithMap(value map[string][]byte) *EasyCodec {
    66  	items := ParamsMapToEasyCodecItem(value)
    67  	return &EasyCodec{items}
    68  }
    69  
    70  func NewEasyCodecWithBytes(value []byte) *EasyCodec {
    71  	return &EasyCodec{EasyUnmarshal(value)}
    72  }
    73  
    74  func NewEasyCodecWithItems(items []*EasyCodecItem) *EasyCodec {
    75  	return &EasyCodec{items: items}
    76  }
    77  
    78  func (e *EasyCodec) AddInt32(key string, value int32) {
    79  	e.items = append(e.items, newEasyCodecItemWithInt32(key, value))
    80  }
    81  
    82  func (e *EasyCodec) AddString(key string, value string) {
    83  	e.items = append(e.items, newEasyCodecItemWithString(key, value))
    84  }
    85  
    86  func (e *EasyCodec) AddBytes(key string, value []byte) {
    87  	e.items = append(e.items, newEasyCodecItemWithBytes(key, value))
    88  }
    89  
    90  func (e *EasyCodec) AddMap(value map[string][]byte) {
    91  	items := ParamsMapToEasyCodecItem(value)
    92  	e.items = append(e.items, items...)
    93  }
    94  
    95  func (e *EasyCodec) AddValue(keyType EasyKeyType, key string, valueType EasyValueType, value interface{}) {
    96  	e.items = append(e.items, newEasyCodecItem(keyType, key, valueType, value))
    97  }
    98  
    99  func (e *EasyCodec) AddItem(item *EasyCodecItem) {
   100  	e.items = append(e.items, item)
   101  }
   102  
   103  func (e *EasyCodec) RemoveKey(key string) {
   104  	for i, item := range e.items {
   105  		if item.Key == key {
   106  			e.items = append(e.items[:i], e.items[i+1:]...)
   107  			return
   108  		}
   109  	}
   110  }
   111  
   112  // toJson simple json, no nesting, rule: int32->strconv.itoa(val) []byte->string([]byte)
   113  func (e *EasyCodec) ToJson() string {
   114  	return EasyCodecItemToJsonStr(e.items)
   115  }
   116  
   117  func (e *EasyCodec) ToMap() map[string][]byte {
   118  	return EasyCodecItemToParamsMap(e.items)
   119  }
   120  
   121  func (e *EasyCodec) GetItems() []*EasyCodecItem {
   122  	return e.items
   123  }
   124  
   125  func (e *EasyCodec) GetItem(key string, keyType EasyKeyType) (*EasyCodecItem, error) {
   126  	for _, item := range e.items {
   127  		if item.Key == key && item.KeyType == keyType {
   128  			return item, nil
   129  		}
   130  	}
   131  	return nil, errors.New("not found key with keyType")
   132  }
   133  
   134  func (e *EasyCodec) GetValue(key string, keyType EasyKeyType) (interface{}, error) {
   135  	for _, item := range e.items {
   136  		if item.Key == key && item.KeyType == keyType {
   137  			return item.Value, nil
   138  		}
   139  	}
   140  	return nil, errors.New("not found key with keyType")
   141  }
   142  
   143  func (e *EasyCodec) GetInt32(key string) (int32, error) {
   144  	item, err := e.GetItem(key, EasyKeyType_USER)
   145  	if err == nil && item.ValueType == EasyValueType_INT32 {
   146  		return item.Value.(int32), nil
   147  	}
   148  	return 0, errors.New("not found key or value type not int32")
   149  }
   150  
   151  func (e *EasyCodec) GetString(key string) (string, error) {
   152  	item, err := e.GetItem(key, EasyKeyType_USER)
   153  	if err == nil && item.ValueType == EasyValueType_STRING {
   154  		return item.Value.(string), nil
   155  	}
   156  	return "", errors.New("not found key or value type not string")
   157  }
   158  
   159  func (e *EasyCodec) GetBytes(key string) ([]byte, error) {
   160  	item, err := e.GetItem(key, EasyKeyType_USER)
   161  	if err == nil && item.ValueType == EasyValueType_BYTES {
   162  		return item.Value.([]byte), nil
   163  	}
   164  	return nil, errors.New("not found key or value type not bytes")
   165  }
   166  
   167  func (e *EasyCodec) Marshal() []byte {
   168  	return EasyMarshal(e.items)
   169  }
   170  
   171  type EasyCodecItem struct {
   172  	KeyType EasyKeyType
   173  	Key     string
   174  
   175  	ValueType EasyValueType
   176  	Value     interface{}
   177  }
   178  
   179  func newEasyCodecItem(keyType EasyKeyType, key string, valueType EasyValueType, value interface{}) *EasyCodecItem {
   180  	return &EasyCodecItem{
   181  		KeyType:   keyType,
   182  		Key:       key,
   183  		ValueType: valueType,
   184  		Value:     value,
   185  	}
   186  }
   187  
   188  func newEasyCodecItemWithInt32(key string, value int32) *EasyCodecItem {
   189  	return newEasyCodecItem(EasyKeyType_USER, key, EasyValueType_INT32, value)
   190  }
   191  
   192  func newEasyCodecItemWithString(key string, value string) *EasyCodecItem {
   193  	return newEasyCodecItem(EasyKeyType_USER, key, EasyValueType_STRING, value)
   194  }
   195  
   196  func newEasyCodecItemWithBytes(key string, value []byte) *EasyCodecItem {
   197  	return newEasyCodecItem(EasyKeyType_USER, key, EasyValueType_BYTES, value)
   198  }
   199  
   200  // ParamsMapToEasyCodecItem Params map converter
   201  func ParamsMapToEasyCodecItem(params map[string][]byte) []*EasyCodecItem {
   202  	items := make([]*EasyCodecItem, 0)
   203  	if len(params) == 0 {
   204  		return items
   205  	}
   206  	keys := make([]string, 0)
   207  	for key := range params {
   208  		keys = append(keys, key)
   209  	}
   210  	sort.Strings(keys)
   211  	for _, key := range keys {
   212  		items = append(items, newEasyCodecItemWithBytes(key, params[key]))
   213  	}
   214  	return items
   215  }
   216  
   217  // EasyCodecItemToParamsMap easyCodecItem converter
   218  func EasyCodecItemToParamsMap(items []*EasyCodecItem) map[string][]byte {
   219  	params := make(map[string][]byte)
   220  	for _, item := range items {
   221  		switch item.ValueType {
   222  		case EasyValueType_BYTES:
   223  			params[item.Key], _ = item.Value.([]byte)
   224  		case EasyValueType_INT32:
   225  			params[item.Key] = []byte(strconv.Itoa(int(item.Value.(int32))))
   226  		case EasyValueType_STRING:
   227  			params[item.Key] = []byte(item.Value.(string))
   228  		}
   229  	}
   230  	return params
   231  }
   232  
   233  // EasyCodecItemToJsonStr simple json, no nesting, rule: int32->strconv.itoa(val) []byte->string([]byte)
   234  func EasyCodecItemToJsonStr(items []*EasyCodecItem) string {
   235  	if items == nil {
   236  		return "{}"
   237  	}
   238  	var build strings.Builder
   239  	build.WriteString("{")
   240  	total := len(items)
   241  	for i, item := range items {
   242  		key := item.Key
   243  		build.WriteString("\"")
   244  		build.WriteString(key)
   245  		build.WriteString("\":")
   246  		var val string
   247  		switch item.ValueType {
   248  		case EasyValueType_INT32:
   249  			val = strconv.Itoa(int(item.Value.(int32)))
   250  			build.WriteString(val)
   251  		case EasyValueType_STRING:
   252  			val, _ = item.Value.(string)
   253  			val = strings.ReplaceAll(val, "\"", "\\\"")
   254  			build.WriteString("\"")
   255  			build.WriteString(val)
   256  			build.WriteString("\"")
   257  		case EasyValueType_BYTES:
   258  			val = base64.StdEncoding.EncodeToString(item.Value.([]byte))
   259  			build.WriteString("\"")
   260  			build.WriteString(val)
   261  			build.WriteString("\"")
   262  		}
   263  		if i != total-1 {
   264  			build.WriteString(",")
   265  		}
   266  	}
   267  	build.WriteString("}")
   268  	return build.String()
   269  }
   270  
   271  // GetValue get value from item
   272  func (e *EasyCodecItem) GetValue(key string, keyType EasyKeyType) (interface{}, bool) {
   273  	if e.KeyType == keyType && e.Key == key {
   274  		return e.Value, true
   275  	}
   276  	return "", false
   277  }
   278  
   279  // EasyMarshal serialize item into binary
   280  func EasyMarshal(items []*EasyCodecItem) []byte {
   281  	buf := new(bytes.Buffer)
   282  	uint32DataBytes := make([]byte, 4)
   283  	//buf.Write(ecMagicNum)
   284  	//buf.Write(ecVersion)
   285  	//buf.Write(ecReserved)
   286  	binaryUint32Marshal(buf, uint32(len(items)), uint32DataBytes)
   287  	for _, item := range items {
   288  		if item.KeyType != EasyKeyType_SYSTEM && item.KeyType != EasyKeyType_USER {
   289  			continue
   290  		}
   291  		binaryUint32Marshal(buf, uint32(item.KeyType), uint32DataBytes)
   292  		binaryUint32Marshal(buf, uint32(len(item.Key)), uint32DataBytes)
   293  		buf.Write([]byte(item.Key))
   294  		switch item.ValueType {
   295  		case EasyValueType_INT32:
   296  			binaryUint32Marshal(buf, uint32(item.ValueType), uint32DataBytes)
   297  			binaryUint32Marshal(buf, uint32(4), uint32DataBytes)
   298  			binaryUint32Marshal(buf, uint32(item.Value.(int32)), uint32DataBytes)
   299  		case EasyValueType_STRING:
   300  			binaryUint32Marshal(buf, uint32(item.ValueType), uint32DataBytes)
   301  			binaryUint32Marshal(buf, uint32(len(item.Value.(string))), uint32DataBytes)
   302  			buf.Write([]byte(item.Value.(string)))
   303  		case EasyValueType_BYTES:
   304  			binaryUint32Marshal(buf, uint32(item.ValueType), uint32DataBytes)
   305  			binaryUint32Marshal(buf, uint32(len(item.Value.([]byte))), uint32DataBytes)
   306  			buf.Write(item.Value.([]byte))
   307  		}
   308  	}
   309  	return buf.Bytes()
   310  }
   311  
   312  // EasyUnmarshal Deserialized from binary to item
   313  func EasyUnmarshal(data []byte) []*EasyCodecItem {
   314  	var (
   315  		items         []*EasyCodecItem
   316  		easyKeyType   EasyKeyType
   317  		keyLength     int32
   318  		keyContent    []byte
   319  		easyValueType EasyValueType
   320  		valueLength   int32
   321  	)
   322  	if len(data) <= MIN_LEN {
   323  		return items
   324  	}
   325  	buf := bytes.NewBuffer(data)
   326  	uint32DataBytes := make([]byte, 4)
   327  	var count uint32
   328  	magicNum := make([]byte, EC_MAGIC_NUM_LEN)
   329  	_, _ = buf.Read(magicNum)
   330  	if bytes.Equal(magicNum, ecMagicNum) {
   331  		version := make([]byte, EC_VERSION_LEN)
   332  		reserved := make([]byte, EC_RESERVED_LEN)
   333  		_, _ = buf.Read(version)
   334  		_, _ = buf.Read(reserved)
   335  		if !(bytes.Equal(magicNum, ecMagicNum) && bytes.Equal(version, ecVersion) && bytes.Equal(reserved, ecReserved)) {
   336  			return items
   337  		}
   338  		count = binaryUint32Unmarshal(buf, uint32DataBytes)
   339  	} else {
   340  		count = binaryUint32Unmarshal(bytes.NewBuffer(magicNum), uint32DataBytes)
   341  	}
   342  	if count > MAX_KEY_COUNT {
   343  		return nil
   344  	}
   345  	for i := 0; i < int(count); i++ {
   346  		// Key Part
   347  		easyKeyType = EasyKeyType(binaryUint32Unmarshal(buf, uint32DataBytes))
   348  		keyLength = int32(binaryUint32Unmarshal(buf, uint32DataBytes))
   349  		if keyLength > MAX_KEY_LEN {
   350  			return items
   351  		}
   352  		keyContent = make([]byte, keyLength)
   353  		_, _ = buf.Read(keyContent)
   354  		// Value Part
   355  		easyValueType = EasyValueType((binaryUint32Unmarshal(buf, uint32DataBytes)))
   356  		valueLength = int32(binaryUint32Unmarshal(buf, uint32DataBytes))
   357  		// move 'length verify' from sdk to vm
   358  		//if valueLength > MAX_VALUE_LEN {
   359  		//	return items
   360  		//}
   361  		var easyCodecItem EasyCodecItem
   362  		switch easyValueType {
   363  		case EasyValueType_INT32:
   364  			valueContent := int32(binaryUint32Unmarshal(buf, uint32DataBytes))
   365  			easyCodecItem.Value = valueContent
   366  		case EasyValueType_STRING:
   367  			valueContent := make([]byte, valueLength)
   368  			_, _ = buf.Read(valueContent)
   369  			easyCodecItem.Value = string(valueContent)
   370  		case EasyValueType_BYTES:
   371  			valueContent := make([]byte, valueLength)
   372  			_, _ = buf.Read(valueContent)
   373  			easyCodecItem.Value = valueContent
   374  		}
   375  		easyCodecItem.KeyType = easyKeyType
   376  		easyCodecItem.Key = string(keyContent)
   377  		easyCodecItem.ValueType = easyValueType
   378  		items = append(items, &easyCodecItem)
   379  	}
   380  	return items
   381  }
   382  
   383  func binaryUint32Marshal(buf *bytes.Buffer, data uint32, dataBytes []byte) {
   384  	_ = dataBytes[3]
   385  	dataBytes[0] = byte(data)
   386  	dataBytes[1] = byte(data >> 8)
   387  	dataBytes[2] = byte(data >> 16)
   388  	dataBytes[3] = byte(data >> 24)
   389  	buf.Write(dataBytes)
   390  }
   391  
   392  func binaryUint32Unmarshal(buf *bytes.Buffer, bs []byte) uint32 {
   393  	_, _ = buf.Read(bs)
   394  	_ = bs[3]
   395  	return uint32(bs[0]) | uint32(bs[1])<<8 | uint32(bs[2])<<16 | uint32(bs[3])<<24
   396  }