| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- //协议序列化
- package util
- import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "math"
- "reflect"
- "runtime/debug"
- "sync"
- )
- //协议转为二进制
- func Pack(v interface{}) ([]byte, error) {
- e := newEncodeState()
- err := e.marshal(v)
- if err != nil {
- return nil, err
- }
- buf := append([]byte(nil), e.Bytes()...)
- encodeStatePool.Put(e)
- return buf, nil
- }
- var encodeStatePool sync.Pool
- type encodeState struct {
- bytes.Buffer
- }
- //写入数字类型(v需要明确数字类型,不能为int,uint)
- func (e *encodeState) WriteInt(v interface{}) {
- err := binary.Write(e, binary.BigEndian, v)
- if err != nil {
- panic(err)
- }
- }
- func (e *encodeState) reflectValue(v reflect.Value) {
- typeEncoder(v.Type())(e, v)
- }
- func (e *encodeState) marshal(v interface{}) (err error) {
- defer func() {
- if r := recover(); r != nil {
- if je, ok := r.(error); ok {
- err = je
- } else {
- err = errors.New("pack error:" + fmt.Sprint(r) + " debug:" + string(debug.Stack()))
- }
- }
- }()
- rv := reflect.ValueOf(v)
- if rv.Kind() == reflect.Ptr {
- rv = rv.Elem()
- }
- e.reflectValue(rv)
- return
- }
- func newEncodeState() *encodeState {
- if v := encodeStatePool.Get(); v != nil {
- e := v.(*encodeState)
- e.Reset()
- return e
- }
- return &encodeState{}
- }
- type protoError struct{ error }
- type encoderFunc func(e *encodeState, v reflect.Value)
- var encoderCache sync.Map // map[reflect.Type]encoderFunc
- func typeEncoder(t reflect.Type) encoderFunc {
- if fi, ok := encoderCache.Load(t); ok {
- return fi.(encoderFunc)
- }
- var (
- wg sync.WaitGroup
- f encoderFunc
- )
- wg.Add(1)
- fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value) {
- wg.Wait()
- f(e, v)
- }))
- if loaded {
- return fi.(encoderFunc)
- }
- f = newTypeEncoder(t)
- wg.Done()
- encoderCache.Store(t, f)
- return f
- }
- func newTypeEncoder(t reflect.Type) encoderFunc {
- switch t.Kind() {
- case reflect.Bool:
- return boolEncoder
- case reflect.Int:
- return intEncoder
- case reflect.Uint:
- return uintEncoder
- case reflect.Int32, reflect.Int8, reflect.Int16, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- return intComEncoder
- case reflect.Float32:
- return float32Encoder
- case reflect.Float64:
- return float64Encoder
- case reflect.String:
- return stringEncoder
- case reflect.Struct:
- return newStructEncoder(t)
- case reflect.Slice:
- return newSliceEncoder(t)
- case reflect.Array:
- return newArrayEncoder(t)
- default:
- panic(errors.New("proto: unsupported type: " + t.String()))
- }
- }
- func boolEncoder(e *encodeState, v reflect.Value) {
- if v.Bool() {
- e.WriteByte(1)
- } else {
- e.WriteByte(0)
- }
- }
- //通用
- func intComEncoder(e *encodeState, v reflect.Value) {
- e.WriteInt(v.Interface())
- }
- //4字节
- func intEncoder(e *encodeState, v reflect.Value) {
- e.WriteInt(int32(v.Int()))
- }
- //4字节
- func uintEncoder(e *encodeState, v reflect.Value) {
- e.WriteInt(uint32(v.Uint()))
- }
- //float32
- func float32Encoder(e *encodeState, v reflect.Value) {
- e.WriteInt(math.Float32bits((float32)(v.Float())))
- }
- //float64
- func float64Encoder(e *encodeState, v reflect.Value) {
- e.WriteInt(math.Float64bits((v.Float())))
- }
- //string
- func stringEncoder(e *encodeState, v reflect.Value) {
- buf := []byte(v.String())
- l := len(buf)
- if l > 70000 {
- panic(errors.New(fmt.Sprint("proto: stringLen len > 70000 l:", l)))
- }
- e.WriteInt(uint32(l))
- e.Write(buf)
- }
- func encodeByteSlice(e *encodeState, v reflect.Value) {
- res := v.Bytes()
- l := len(res)
- if l >= 5000000 {
- panic(errors.New(fmt.Sprint("proto: []uint8 len > 5000000 l:", l)))
- }
- e.WriteInt(uint32(l))
- e.Write(res)
- }
- type sliceEncoder struct {
- arrayEnc encoderFunc
- }
- func (se sliceEncoder) encode(e *encodeState, v reflect.Value) {
- if v.IsNil() {
- e.WriteInt(uint32(0))
- return
- }
- se.arrayEnc(e, v)
- }
- func newSliceEncoder(t reflect.Type) encoderFunc {
- // Byte slices get special treatment; arrays don't.
- if t.Elem().Kind() == reflect.Uint8 {
- return encodeByteSlice
- }
- enc := sliceEncoder{newArrayEncoder(t)}
- return enc.encode
- }
- type arrayEncoder struct {
- elemEnc encoderFunc
- }
- func (ae arrayEncoder) encode(e *encodeState, v reflect.Value) {
- l := v.Len()
- if l > 5000000 {
- panic(errors.New("proto: not support arrLen> 5000000 type:" + v.Type().String()))
- }
- e.WriteInt(uint32(l))
- for i := 0; i < l; i++ {
- ae.elemEnc(e, v.Index(i))
- }
- }
- func newArrayEncoder(t reflect.Type) encoderFunc {
- enc := arrayEncoder{typeEncoder(t.Elem())}
- return enc.encode
- }
- type structEncoder struct {
- fields []field
- }
- func (se structEncoder) encode(e *encodeState, v reflect.Value) {
- for i := range se.fields {
- f := &se.fields[i]
- f.encoder(e, v.Field(i))
- }
- }
- func newStructEncoder(t reflect.Type) encoderFunc {
- return cachedTypeFields(t).encode
- }
- type field struct {
- encoder encoderFunc
- }
- func typeFields(t reflect.Type) structEncoder {
- var fields []field
- for i := 0; i < t.NumField(); i++ {
- sf := t.Field(i)
- st := sf.Type
- if st == t {
- panic("proto:not support recursive type:" + st.String())
- }
- if sf.PkgPath != "" {
- panic("proto:not support type:" + t.String() + ",name:" + sf.Name)
- }
- fields = append(fields, field{encoder: typeEncoder(st)})
- }
- return structEncoder{fields}
- }
- var fieldCache sync.Map // map[reflect.Type]structEncoder
- func cachedTypeFields(t reflect.Type) structEncoder {
- if f, ok := fieldCache.Load(t); ok {
- return f.(structEncoder)
- }
- f, _ := fieldCache.LoadOrStore(t, typeFields(t))
- return f.(structEncoder)
- }
|