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 }