github.com/polarismesh/polaris@v1.17.8/store/boltdb/codec.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package boltdb
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/binary"
    23  	"fmt"
    24  	"reflect"
    25  	"strings"
    26  	"time"
    27  
    28  	"github.com/golang/protobuf/proto"
    29  	bolt "go.etcd.io/bbolt"
    30  )
    31  
    32  const (
    33  	typeUnknown byte = iota
    34  	typeString
    35  	typeBool
    36  	typeTime
    37  	typeProtobuf
    38  	typeInt
    39  	typeInt8
    40  	typeInt16
    41  	typeInt32
    42  	typeInt64
    43  	typeUint
    44  	typeUint8
    45  	typeUint16
    46  	typeUint32
    47  	typeUint64
    48  )
    49  
    50  var (
    51  	timeType         = reflect.TypeOf(time.Now())
    52  	messageType      = reflect.TypeOf((*proto.Message)(nil)).Elem()
    53  	numberKindToType = buildNumberKindToType()
    54  )
    55  
    56  func buildNumberKindToType() map[reflect.Kind]byte {
    57  	values := make(map[reflect.Kind]byte)
    58  	values[reflect.Int] = typeInt
    59  	values[reflect.Int8] = typeInt8
    60  	values[reflect.Int16] = typeInt16
    61  	values[reflect.Int32] = typeInt32
    62  	values[reflect.Int64] = typeInt64
    63  	values[reflect.Uint] = typeUint
    64  	values[reflect.Uint8] = typeUint8
    65  	values[reflect.Uint16] = typeUint16
    66  	values[reflect.Uint32] = typeUint32
    67  	values[reflect.Uint64] = typeUint64
    68  	return values
    69  }
    70  
    71  func encodeStringBuffer(strValue string) []byte {
    72  	buf := bytes.NewBuffer(make([]byte, 0, len(strValue)+1))
    73  	buf.WriteByte(typeString)
    74  	buf.WriteString(strValue)
    75  	return buf.Bytes()
    76  }
    77  
    78  func decodeStringBuffer(name string, buf []byte) (string, error) {
    79  	if len(buf) == 0 {
    80  		return "", nil
    81  	}
    82  	byteType := buf[0]
    83  	if byteType != typeString {
    84  		return "",
    85  			fmt.Errorf("invalid type field %s, want string(%v), actual is %v", name, typeString, byteType)
    86  	}
    87  	strBytes := buf[1:]
    88  	return string(strBytes), nil
    89  }
    90  
    91  func encodeIntBuffer(intValue int64, typeByte byte) []byte {
    92  	buf := bytes.NewBuffer(make([]byte, 0, 9))
    93  	buf.WriteByte(typeByte)
    94  	b := make([]byte, 8)
    95  	binary.LittleEndian.PutUint64(b, uint64(intValue))
    96  	buf.Write(b)
    97  	return buf.Bytes()
    98  }
    99  
   100  func encodeUintBuffer(intValue uint64, typeByte byte) []byte {
   101  	buf := bytes.NewBuffer(make([]byte, 0, 9))
   102  	buf.WriteByte(typeByte)
   103  	b := make([]byte, 8)
   104  	binary.LittleEndian.PutUint64(b, intValue)
   105  	buf.Write(b)
   106  	return buf.Bytes()
   107  }
   108  
   109  func decodeIntBuffer(name string, buf []byte, typeByte byte) (int64, error) {
   110  	if len(buf) == 0 {
   111  		return 0, nil
   112  	}
   113  	byteType := buf[0]
   114  	if byteType != typeByte {
   115  		return 0, fmt.Errorf("invalid type field %s, want int(%v), actual is %v", name, typeByte, byteType)
   116  	}
   117  	intBytes := buf[1:]
   118  	value := binary.LittleEndian.Uint64(intBytes)
   119  	return int64(value), nil
   120  }
   121  
   122  func decodeUintBuffer(name string, buf []byte, typeByte byte) (uint64, error) {
   123  	if len(buf) == 0 {
   124  		return 0, nil
   125  	}
   126  	byteType := buf[0]
   127  	if byteType != typeByte {
   128  		return 0, fmt.Errorf("invalid type field %s, want uint(%v), actual is %v", name, typeByte, byteType)
   129  	}
   130  	intBytes := buf[1:]
   131  	value := binary.LittleEndian.Uint64(intBytes)
   132  	return value, nil
   133  }
   134  
   135  func encodeBoolBuffer(boolValue bool) []byte {
   136  	buf := bytes.NewBuffer(make([]byte, 0, 2))
   137  	buf.WriteByte(typeBool)
   138  	if boolValue {
   139  		buf.WriteByte(1)
   140  	} else {
   141  		buf.WriteByte(0)
   142  	}
   143  	return buf.Bytes()
   144  }
   145  
   146  func decodeBoolBuffer(name string, buf []byte) (bool, error) {
   147  	if len(buf) == 0 {
   148  		return false, nil
   149  	}
   150  	byteType := buf[0]
   151  	if byteType != typeBool {
   152  		return false,
   153  			fmt.Errorf("invalid type field %s, want bool(%v), actual is %v", name, typeBool, byteType)
   154  	}
   155  	boolByte := buf[1]
   156  	return boolByte > 0, nil
   157  }
   158  
   159  func encodeRawMap(parent *bolt.Bucket, name string, values map[string]string) error {
   160  	nameByte := []byte(name)
   161  	var bucket *bolt.Bucket
   162  	var err error
   163  	if bucket = parent.Bucket(nameByte); bucket != nil {
   164  		err = parent.DeleteBucket(nameByte)
   165  		if err != nil {
   166  			return err
   167  		}
   168  	}
   169  	bucket, err = parent.CreateBucket(nameByte)
   170  	if err != nil {
   171  		return err
   172  	}
   173  	if len(values) == 0 {
   174  		return nil
   175  	}
   176  	for mapKey, mapValue := range values {
   177  		if err = bucket.Put([]byte(mapKey), []byte(mapValue)); err != nil {
   178  			return err
   179  		}
   180  	}
   181  	return nil
   182  }
   183  
   184  func encodeMapBuffer(parent *bolt.Bucket, name string, mapKeys []reflect.Value, fieldValue *reflect.Value) error {
   185  	nameByte := []byte(name)
   186  	var bucket *bolt.Bucket
   187  	var err error
   188  	if bucket = parent.Bucket(nameByte); bucket != nil {
   189  		err = parent.DeleteBucket(nameByte)
   190  		if err != nil {
   191  			return err
   192  		}
   193  	}
   194  	bucket, err = parent.CreateBucket(nameByte)
   195  	if err != nil {
   196  		return err
   197  	}
   198  	if len(mapKeys) == 0 {
   199  		return nil
   200  	}
   201  	for _, mapKey := range mapKeys {
   202  		keyStr := mapKey.String()
   203  		mapValue := fieldValue.MapIndex(mapKey)
   204  		valueStr := mapValue.String()
   205  		if err = bucket.Put([]byte(keyStr), []byte(valueStr)); err != nil {
   206  			return err
   207  		}
   208  	}
   209  	return nil
   210  }
   211  
   212  func decodeMapBuffer(bucket *bolt.Bucket) (map[string]string, error) {
   213  	values := make(map[string]string)
   214  	if bucket == nil {
   215  		return values, nil
   216  	}
   217  	err := bucket.ForEach(func(k, v []byte) error {
   218  		values[string(k)] = string(v)
   219  		return nil
   220  	})
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  	return values, nil
   225  }
   226  
   227  func encodeTimeBuffer(timeValue time.Time) []byte {
   228  	intValue := timeValue.UnixNano()
   229  	buf := bytes.NewBuffer(make([]byte, 0, 9))
   230  	buf.WriteByte(typeTime)
   231  	b := make([]byte, 8)
   232  	binary.LittleEndian.PutUint64(b, uint64(intValue))
   233  	buf.Write(b)
   234  	return buf.Bytes()
   235  }
   236  
   237  func decodeTimeBuffer(name string, buf []byte) (time.Time, error) {
   238  	if len(buf) == 0 {
   239  		return time.Unix(0, 0), nil
   240  	}
   241  	byteType := buf[0]
   242  	if byteType != typeTime {
   243  		return time.Unix(0, 0),
   244  			fmt.Errorf("invalid type field %s, want time(%v), actual is %v", name, typeTime, byteType)
   245  	}
   246  	intBytes := buf[1:]
   247  	value := binary.LittleEndian.Uint64(intBytes)
   248  	return time.Unix(0, int64(value)), nil
   249  }
   250  
   251  func encodeMessageBuffer(msg proto.Message) ([]byte, error) {
   252  	protoBuf, err := proto.Marshal(msg)
   253  	if err != nil {
   254  		return nil, err
   255  	}
   256  	buf := bytes.NewBuffer(make([]byte, 0, len(protoBuf)+1))
   257  	buf.WriteByte(typeProtobuf)
   258  	buf.Write(protoBuf)
   259  	return buf.Bytes(), nil
   260  }
   261  
   262  func decodeMessageBuffer(msg proto.Message, name string, buf []byte) (proto.Message, error) {
   263  	if len(buf) == 0 {
   264  		return nil, nil
   265  	}
   266  	byteType := buf[0]
   267  	if byteType != typeProtobuf {
   268  		return nil, fmt.Errorf("invalid type field %s, want protoBuf(%v), actual is %v", name, typeProtobuf, byteType)
   269  	}
   270  	protoBytes := buf[1:]
   271  	err := proto.Unmarshal(protoBytes, msg)
   272  	if err != nil {
   273  		return nil, err
   274  	}
   275  	return msg, nil
   276  }
   277  
   278  func serializeObject(parent *bolt.Bucket, value interface{}) (map[string][]byte, error) {
   279  	rawValue := reflect.ValueOf(value)
   280  	into := indirect(rawValue)
   281  	if !into.IsValid() {
   282  		// nil object
   283  		return nil, nil
   284  	}
   285  	values := make(map[string][]byte)
   286  	intoType := indirectType(into.Type())
   287  	nums := intoType.NumField()
   288  	var err error
   289  	for i := 0; i < nums; i++ {
   290  		field := intoType.Field(i)
   291  		rawFieldType := field.Type
   292  		name := toBucketField(field.Name)
   293  		if field.Anonymous {
   294  			// 不处理匿名属性
   295  			log.Warnf("[BlobStore] anonymous field %s, type is %v", name, rawFieldType)
   296  			continue
   297  		}
   298  		fieldValue := into.FieldByName(field.Name)
   299  		if !fieldValue.CanAddr() {
   300  			log.Warnf("[BlobStore] addressable field %s, type is %v", name, rawFieldType)
   301  			continue
   302  		}
   303  		if !fieldValue.IsValid() {
   304  			log.Warnf("[BlobStore] invalid field %s, type is %v", name, rawFieldType)
   305  			continue
   306  		}
   307  		if !fieldValue.CanInterface() {
   308  			log.Warnf("[BlobStore] private field %s, type is %v", name, rawFieldType)
   309  			continue
   310  		}
   311  		kind := rawFieldType.Kind()
   312  		switch kind {
   313  		case reflect.String:
   314  			strValue := fieldValue.String()
   315  			values[name] = encodeStringBuffer(strValue)
   316  		case reflect.Bool:
   317  			boolValue := fieldValue.Bool()
   318  			values[name] = encodeBoolBuffer(boolValue)
   319  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   320  			intValue := fieldValue.Int()
   321  			values[name] = encodeIntBuffer(intValue, numberKindToType[kind])
   322  		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   323  			intValue := fieldValue.Uint()
   324  			values[name] = encodeUintBuffer(intValue, numberKindToType[kind])
   325  		case reflect.Map:
   326  			mapKeys := fieldValue.MapKeys()
   327  			err := encodeMapBuffer(parent, name, mapKeys, &fieldValue)
   328  			if err != nil {
   329  				return nil, err
   330  			}
   331  		case reflect.Ptr:
   332  			if rawFieldType.Implements(messageType) {
   333  				// protobuf类型
   334  				elem := fieldValue.Addr().Elem()
   335  				if elem.IsNil() {
   336  					continue
   337  				}
   338  				msgValue := elem.Interface().(proto.Message)
   339  				values[name], err = encodeMessageBuffer(msgValue)
   340  				if err != nil {
   341  					return nil, err
   342  				}
   343  			}
   344  		case reflect.Struct:
   345  			if rawFieldType.AssignableTo(timeType) {
   346  				// 时间类型
   347  				timeValue := fieldValue.Addr().Elem().Interface().(time.Time)
   348  				values[name] = encodeTimeBuffer(timeValue)
   349  			}
   350  		default:
   351  			log.Warnf(
   352  				"[BlobStore] serialize unrecognized field %s, type is %v, kind is %s", name, rawFieldType, kind)
   353  			continue
   354  		}
   355  	}
   356  	return values, nil
   357  }
   358  
   359  func toBucketField(field string) string {
   360  	return strings.ToLower(field)
   361  }
   362  
   363  func deserializeObject(bucket *bolt.Bucket, value interface{}) (interface{}, error) {
   364  	fromObj := indirect(reflect.ValueOf(value))
   365  	if !fromObj.IsValid() {
   366  		// nil object
   367  		return nil, nil
   368  	}
   369  	toValue := reflect.New(reflect.TypeOf(value).Elem()).Interface()
   370  	toObj := indirect(reflect.ValueOf(toValue))
   371  	intoType := indirectType(toObj.Type())
   372  	nums := intoType.NumField()
   373  	for i := 0; i < nums; i++ {
   374  		field := intoType.Field(i)
   375  		rawFieldType := field.Type
   376  		name := toBucketField(field.Name)
   377  		if field.Anonymous {
   378  			// 不处理匿名属性
   379  			log.Warnf("[BlobStore] anonymous field %s, type is %v", name, rawFieldType)
   380  			continue
   381  		}
   382  		fieldValue := toObj.FieldByName(field.Name)
   383  		if !fieldValue.CanAddr() {
   384  			log.Warnf("[BlobStore] addressable field %s, type is %v", name, rawFieldType)
   385  			continue
   386  		}
   387  		if !fieldValue.IsValid() {
   388  			log.Warnf("[BlobStore] invalid field %s, type is %v", name, rawFieldType)
   389  			continue
   390  		}
   391  		if !fieldValue.CanSet() {
   392  			log.Warnf("[BlobStore] private field %s, type is %v", name, rawFieldType)
   393  			continue
   394  		}
   395  		kind := rawFieldType.Kind()
   396  		switch kind {
   397  		case reflect.String:
   398  			buf := bucket.Get([]byte(name))
   399  			value, err := decodeStringBuffer(name, buf)
   400  			if err != nil {
   401  				return nil, err
   402  			}
   403  			fieldValue.Set(reflect.ValueOf(value))
   404  		case reflect.Bool:
   405  			buf := bucket.Get([]byte(name))
   406  			value, err := decodeBoolBuffer(name, buf)
   407  			if err != nil {
   408  				return nil, err
   409  			}
   410  			fieldValue.Set(reflect.ValueOf(value))
   411  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   412  			buf := bucket.Get([]byte(name))
   413  			value, err := decodeIntBuffer(name, buf, numberKindToType[kind])
   414  			if err != nil {
   415  				return nil, err
   416  			}
   417  			setIntValue(value, &fieldValue, kind)
   418  		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   419  			buf := bucket.Get([]byte(name))
   420  			value, err := decodeUintBuffer(name, buf, numberKindToType[kind])
   421  			if err != nil {
   422  				return nil, err
   423  			}
   424  			setUintValue(value, &fieldValue, kind)
   425  		case reflect.Map:
   426  			subBucket := bucket.Bucket([]byte(name))
   427  			values, err := decodeMapBuffer(subBucket)
   428  			if err != nil {
   429  				return nil, err
   430  			}
   431  			fieldValue.Set(reflect.ValueOf(values))
   432  		case reflect.Ptr:
   433  			if rawFieldType.Implements(messageType) {
   434  				// protobuf类型
   435  				buf := bucket.Get([]byte(name))
   436  				if nil == buf {
   437  					continue
   438  				}
   439  				toMsgValue := reflect.New(rawFieldType.Elem()).Interface().(proto.Message)
   440  				msg, err := decodeMessageBuffer(toMsgValue, name, buf)
   441  				if err != nil {
   442  					return nil, err
   443  				}
   444  				fieldValue.Set(reflect.ValueOf(msg))
   445  			}
   446  		case reflect.Struct:
   447  			if rawFieldType.AssignableTo(timeType) {
   448  				// 时间类型
   449  				buf := bucket.Get([]byte(name))
   450  				value, err := decodeTimeBuffer(name, buf)
   451  				if err != nil {
   452  					return nil, err
   453  				}
   454  				fieldValue.Set(reflect.ValueOf(value))
   455  			}
   456  		default:
   457  			log.Warnf("[BlobStore] deserialize unrecognized field %s, type is %v", name, rawFieldType)
   458  			continue
   459  		}
   460  	}
   461  	return toValue, nil
   462  }
   463  
   464  func setIntValue(value int64, fieldValue *reflect.Value, kind reflect.Kind) {
   465  	switch kind {
   466  	case reflect.Int:
   467  		fieldValue.Set(reflect.ValueOf(int(value)))
   468  	case reflect.Int8:
   469  		fieldValue.Set(reflect.ValueOf(int8(value)))
   470  	case reflect.Int16:
   471  		fieldValue.Set(reflect.ValueOf(int16(value)))
   472  	case reflect.Int32:
   473  		fieldValue.Set(reflect.ValueOf(int32(value)))
   474  	case reflect.Int64:
   475  		fieldValue.Set(reflect.ValueOf(value))
   476  	default:
   477  		// do nothing
   478  	}
   479  }
   480  
   481  func setUintValue(value uint64, fieldValue *reflect.Value, kind reflect.Kind) {
   482  	switch kind {
   483  	case reflect.Uint:
   484  		fieldValue.Set(reflect.ValueOf(uint(value)))
   485  	case reflect.Uint8:
   486  		fieldValue.Set(reflect.ValueOf(uint8(value)))
   487  	case reflect.Uint16:
   488  		fieldValue.Set(reflect.ValueOf(uint16(value)))
   489  	case reflect.Uint32:
   490  		fieldValue.Set(reflect.ValueOf(uint32(value)))
   491  	case reflect.Uint64:
   492  		fieldValue.Set(reflect.ValueOf(value))
   493  	default:
   494  		// do nothing
   495  	}
   496  }
   497  
   498  func indirect(reflectValue reflect.Value) reflect.Value {
   499  	for reflectValue.Kind() == reflect.Ptr {
   500  		reflectValue = reflectValue.Elem()
   501  	}
   502  	return reflectValue
   503  }
   504  
   505  func indirectType(reflectType reflect.Type) reflect.Type {
   506  	for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {
   507  		reflectType = reflectType.Elem()
   508  	}
   509  	return reflectType
   510  }