"refactor(common): 重构序列化工具包,将serialize重命名为utils并添加bitset组件"
This commit is contained in:
122
common/utils/sturc/struc.go
Normal file
122
common/utils/sturc/struc.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package struc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
ByteAlign int
|
||||
PtrSize int
|
||||
Order binary.ByteOrder
|
||||
}
|
||||
|
||||
func (o *Options) Validate() error {
|
||||
if o.PtrSize == 0 {
|
||||
o.PtrSize = 32
|
||||
} else {
|
||||
switch o.PtrSize {
|
||||
case 8, 16, 32, 64:
|
||||
default:
|
||||
return fmt.Errorf("Invalid Options.PtrSize: %d. Must be in (8, 16, 32, 64)", o.PtrSize)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var emptyOptions = &Options{}
|
||||
|
||||
func init() {
|
||||
// fill default values to avoid data race to be reported by race detector.
|
||||
emptyOptions.Validate()
|
||||
}
|
||||
|
||||
func prep(data interface{}) (reflect.Value, Packer, error) {
|
||||
value := reflect.ValueOf(data)
|
||||
for value.Kind() == reflect.Ptr {
|
||||
next := value.Elem().Kind()
|
||||
if next == reflect.Struct || next == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
switch value.Kind() {
|
||||
case reflect.Struct:
|
||||
fields, err := parseFields(value)
|
||||
return value, fields, err
|
||||
default:
|
||||
if !value.IsValid() {
|
||||
return reflect.Value{}, nil, fmt.Errorf("Invalid reflect.Value for %+v", data)
|
||||
}
|
||||
if c, ok := data.(Custom); ok {
|
||||
return value, customFallback{c}, nil
|
||||
}
|
||||
return value, binaryFallback(value), nil
|
||||
}
|
||||
}
|
||||
|
||||
func Pack(w io.Writer, data interface{}) error {
|
||||
return PackWithOptions(w, data, nil)
|
||||
}
|
||||
|
||||
func PackWithOptions(w io.Writer, data interface{}, options *Options) error {
|
||||
if options == nil {
|
||||
options = emptyOptions
|
||||
}
|
||||
if err := options.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
val, packer, err := prep(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if val.Type().Kind() == reflect.String {
|
||||
val = val.Convert(reflect.TypeOf([]byte{}))
|
||||
}
|
||||
size := packer.Sizeof(val, options)
|
||||
buf := make([]byte, size)
|
||||
if _, err := packer.Pack(buf, val, options); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
func Unpack(r io.Reader, data interface{}) error {
|
||||
return UnpackWithOptions(r, data, nil)
|
||||
}
|
||||
|
||||
func UnpackWithOptions(r io.Reader, data interface{}, options *Options) error {
|
||||
if options == nil {
|
||||
options = emptyOptions
|
||||
}
|
||||
if err := options.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
val, packer, err := prep(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return packer.Unpack(r, val, options)
|
||||
}
|
||||
|
||||
func Sizeof(data interface{}) (int, error) {
|
||||
return SizeofWithOptions(data, nil)
|
||||
}
|
||||
|
||||
func SizeofWithOptions(data interface{}, options *Options) (int, error) {
|
||||
if options == nil {
|
||||
options = emptyOptions
|
||||
}
|
||||
if err := options.Validate(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
val, packer, err := prep(data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return packer.Sizeof(val, options), nil
|
||||
}
|
||||
Reference in New Issue
Block a user