123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- package yu_proto_old
- import (
- "bytes"
- "encoding"
- "encoding/binary"
- "fmt"
- "math"
- "reflect"
- "time"
- )
- // Ufixed32 Message fields declared to have exactly this type
- // will be transmitted as fixed-size 32-bit unsigned integers.
- type Ufixed32 uint32
- // Ufixed64 Message fields declared to have exactly this type
- // will be transmitted as fixed-size 64-bit unsigned integers.
- type Ufixed64 uint64
- // Sfixed32 Message fields declared to have exactly this type
- // will be transmitted as fixed-size 32-bit signed integers.
- type Sfixed32 int32
- // Sfixed64 Message fields declared to have exactly this type
- // will be transmitted as fixed-size 64-bit signed integers.
- type Sfixed64 int64
- // Enum Protobufs enums are transmitted as unsigned varints;
- // using this type alias is optional but recommended
- // to ensure they get the correct type.
- type Enum uint32
- type encoder struct {
- bytes.Buffer
- }
- // Encode a Go struct into protocol buffer format.
- // The caller must pass a pointer to the struct to encode.
- func Encode(structPtr interface{}) (bytes []byte) {
- defer func() {
- if e := recover(); e != nil {
- bytes = nil
- }
- }()
- if structPtr == nil {
- return
- }
- if bu, ok := structPtr.(encoding.BinaryMarshaler); ok {
- bytes, _ = bu.MarshalBinary()
- return
- }
- en := encoder{}
- val := reflect.ValueOf(structPtr)
- if val.Kind() != reflect.Ptr {
- return nil
- }
- en.message(val.Elem())
- return en.Bytes()
- }
- /*
- func Encode(structPtr interface{}) (bytes []byte, err error) {
- defer func() {
- if e := recover(); e != nil {
- err = fmt.Errorf("%v", e)
- bytes = nil
- }
- }()
- if structPtr == nil {
- return nil, nil
- }
- if bu, ok := structPtr.(encoding.BinaryMarshaler); ok {
- return bu.MarshalBinary()
- }
- en := encoder{}
- val := reflect.ValueOf(structPtr)
- if val.Kind() != reflect.Ptr {
- return nil, errors.New("encode takes a pointer to struct")
- }
- en.message(val.Elem())
- return en.Bytes(), nil
- }
- */
- func (en *encoder) message(sval reflect.Value) {
- var index *ProtoField
- defer func() {
- if r := recover(); r != nil {
- if index != nil {
- panic(fmt.Sprintf("%s (field %s)", r, index.Field.Name))
- } else {
- panic(r)
- }
- }
- }()
- // Encode all fields in-order
- protoFields := ProtoFields(sval.Type())
- if len(protoFields) == 0 {
- return
- }
- noPublicFields := true
- for _, index = range protoFields {
- field := sval.FieldByIndex(index.Index)
- key := uint64(index.ID) << 3
- if field.CanSet() { // Skip blank/padding fields
- en.value(key, field, index.Prefix)
- noPublicFields = false
- }
- }
- if noPublicFields {
- panic("struct has no serializable fields")
- }
- }
- var timeType = reflect.TypeOf(time.Time{})
- var durationType = reflect.TypeOf(time.Duration(0))
- func (en *encoder) value(key uint64, val reflect.Value, prefix TagPrefix) {
- // Non-reflectively handle some of the fixed types
- switch v := val.Interface().(type) {
- case bool:
- en.uvarint(key | 0)
- vi := uint64(0)
- if v {
- vi = 1
- }
- en.uvarint(vi)
- return
- case int:
- en.uvarint(key | 0)
- en.svarint(int64(v))
- return
- case int32:
- en.uvarint(key | 0)
- en.svarint(int64(v))
- return
- case time.Time: // Encode time.Time as sfixed64
- t := v.UnixNano()
- en.uvarint(key | 1)
- en.u64(uint64(t))
- return
- case int64:
- en.uvarint(key | 0)
- en.svarint(v)
- return
- case uint32:
- en.uvarint(key | 0)
- en.uvarint(uint64(v))
- return
- case uint64:
- en.uvarint(key | 0)
- en.uvarint(v)
- return
- case Sfixed32:
- en.uvarint(key | 5)
- en.u32(uint32(v))
- return
- case Sfixed64:
- en.uvarint(key | 1)
- en.u64(uint64(v))
- return
- case Ufixed32:
- en.uvarint(key | 5)
- en.u32(uint32(v))
- return
- case Ufixed64:
- en.uvarint(key | 1)
- en.u64(uint64(v))
- return
- case float32:
- en.uvarint(key | 5)
- en.u32(math.Float32bits(v))
- return
- case float64:
- en.uvarint(key | 1)
- en.u64(math.Float64bits(v))
- return
- case string:
- en.uvarint(key | 2)
- b := []byte(v)
- en.uvarint(uint64(len(b)))
- en.Write(b)
- return
- }
- // Handle pointer or interface values (possibly within slices).
- // Note that this switch has to handle all the cases,
- // because custom type aliases will fail the above typeswitch.
- switch val.Kind() {
- case reflect.Bool:
- en.uvarint(key | 0)
- v := uint64(0)
- if val.Bool() {
- v = 1
- }
- en.uvarint(v)
- case reflect.Int, reflect.Int32, reflect.Int64:
- // Varint-encoded 32-bit and 64-bit signed integers.
- // Note that protobufs don't support 8- or 16-bit ints.
- en.uvarint(key | 0)
- en.svarint(val.Int())
- case reflect.Uint32, reflect.Uint64:
- // Varint-encoded 32-bit and 64-bit unsigned integers.
- en.uvarint(key | 0)
- en.uvarint(val.Uint())
- case reflect.Float32:
- // Fixed-length 32-bit floats.
- en.uvarint(key | 5)
- en.u32(math.Float32bits(float32(val.Float())))
- case reflect.Float64:
- // Fixed-length 64-bit floats.
- en.uvarint(key | 1)
- en.u64(math.Float64bits(val.Float()))
- case reflect.String:
- // Length-delimited string.
- en.uvarint(key | 2)
- b := []byte(val.String())
- en.uvarint(uint64(len(b)))
- en.Write(b)
- case reflect.Struct:
- var b []byte
- if enc, ok := val.Interface().(encoding.BinaryMarshaler); ok {
- en.uvarint(key | 2)
- var err error
- b, err = enc.MarshalBinary()
- if err != nil {
- panic(err.Error())
- }
- } else {
- // Embedded messages.
- en.uvarint(key | 2)
- emb := encoder{}
- emb.message(val)
- b = emb.Bytes()
- }
- en.uvarint(uint64(len(b)))
- en.Write(b)
- case reflect.Slice, reflect.Array:
- // Length-delimited slices or byte-vectors.
- en.slice(key, val)
- return
- case reflect.Ptr:
- // Optional field: encode only if pointer is non-nil.
- if val.IsNil() {
- if prefix == TagRequired {
- panic("required field is nil")
- }
- return
- }
- en.value(key, val.Elem(), prefix)
- case reflect.Interface:
- // Abstract interface field.
- if val.IsNil() {
- return
- }
- // If the object support self-encoding, use that.
- if enc, ok := val.Interface().(encoding.BinaryMarshaler); ok {
- en.uvarint(key | 2)
- bytes, err := enc.MarshalBinary()
- if err != nil {
- panic(err.Error())
- }
- size := len(bytes)
- var id GeneratorID
- im, ok := val.Interface().(InterfaceMarshaler)
- if ok {
- id = im.MarshalID()
- g := generators.get(id)
- ok = g != nil
- if ok {
- // add the length of the type tag
- size += len(id)
- }
- }
- en.uvarint(uint64(size))
- if ok {
- // Only write the tag if a generator exists
- en.Write(id[:])
- }
- en.Write(bytes)
- return
- }
- // Encode from the object the interface points to.
- en.value(key, val.Elem(), prefix)
- case reflect.Map:
- en.handleMap(key, val, prefix)
- return
- default:
- panic(fmt.Sprintf("unsupported field Kind %d", val.Kind()))
- }
- }
- func (en *encoder) slice(key uint64, slval reflect.Value) {
- // First handle common cases with a direct typeswitch
- sllen := slval.Len()
- packed := encoder{}
- switch slt := slval.Interface().(type) {
- case []bool:
- for i := 0; i < sllen; i++ {
- v := uint64(0)
- if slt[i] {
- v = 1
- }
- packed.uvarint(v)
- }
- case []int32:
- for i := 0; i < sllen; i++ {
- packed.svarint(int64(slt[i]))
- }
- case []int64:
- for i := 0; i < sllen; i++ {
- packed.svarint(slt[i])
- }
- case []uint32:
- for i := 0; i < sllen; i++ {
- packed.uvarint(uint64(slt[i]))
- }
- case []uint64:
- for i := 0; i < sllen; i++ {
- packed.uvarint(slt[i])
- }
- case []Sfixed32:
- for i := 0; i < sllen; i++ {
- packed.u32(uint32(slt[i]))
- }
- case []Sfixed64:
- for i := 0; i < sllen; i++ {
- packed.u64(uint64(slt[i]))
- }
- case []Ufixed32:
- for i := 0; i < sllen; i++ {
- packed.u32(uint32(slt[i]))
- }
- case []Ufixed64:
- for i := 0; i < sllen; i++ {
- packed.u64(uint64(slt[i]))
- }
- case []float32:
- for i := 0; i < sllen; i++ {
- packed.u32(math.Float32bits(slt[i]))
- }
- case []float64:
- for i := 0; i < sllen; i++ {
- packed.u64(math.Float64bits(slt[i]))
- }
- case []byte: // Write the whole byte-slice as one key,value pair
- en.uvarint(key | 2)
- en.uvarint(uint64(sllen))
- en.Write(slt)
- return
- case []string:
- for i := 0; i < sllen; i++ {
- subVal := slval.Index(i)
- subStr := subVal.Interface().(string)
- subSlice := []byte(subStr)
- en.uvarint(key | 2)
- en.uvarint(uint64(len(subSlice)))
- en.Write(subSlice)
- }
- return
- default: // We'll need to use the reflective path
- en.sliceReflect(key, slval)
- return
- }
- // Encode packed representation key/value pair
- en.uvarint(key | 2)
- b := packed.Bytes()
- en.uvarint(uint64(len(b)))
- en.Write(b)
- }
- // Handle the encoding of an arbritary map[K]V
- func (en *encoder) handleMap(key uint64, mpval reflect.Value, prefix TagPrefix) {
- /*
- A map defined as
- map<key_type, value_type> map_field = N;
- is encoded in the same way as
- message MapFieldEntry {
- key_type key = 1;
- value_type value = 2;
- }
- repeated MapFieldEntry map_field = N;
- */
- for _, mkey := range mpval.MapKeys() {
- mval := mpval.MapIndex(mkey)
- // illegal map entry values
- // - nil message pointers.
- switch kind := mval.Kind(); kind {
- case reflect.Ptr:
- if mval.IsNil() {
- panic("proto: map has nil element")
- }
- case reflect.Slice, reflect.Array:
- if mval.Type().Elem().Kind() != reflect.Uint8 {
- panic("protobuf: map only support []byte or string as repeated value")
- }
- }
- packed := encoder{}
- packed.value(1<<3, mkey, prefix)
- packed.value(2<<3, mval, prefix)
- en.uvarint(key | 2)
- b := packed.Bytes()
- en.uvarint((uint64(len(b))))
- en.Write(b)
- }
- }
- var bytesType = reflect.TypeOf([]byte{})
- func (en *encoder) sliceReflect(key uint64, slval reflect.Value) {
- kind := slval.Kind()
- if kind != reflect.Slice && kind != reflect.Array {
- panic("no slice passed")
- }
- sllen := slval.Len()
- slelt := slval.Type().Elem()
- packed := encoder{}
- switch slelt.Kind() {
- case reflect.Bool:
- for i := 0; i < sllen; i++ {
- v := uint64(0)
- if slval.Index(i).Bool() {
- v = 1
- }
- packed.uvarint(v)
- }
- case reflect.Int, reflect.Int32, reflect.Int64:
- for i := 0; i < sllen; i++ {
- packed.svarint(slval.Index(i).Int())
- }
- case reflect.Uint32, reflect.Uint64:
- for i := 0; i < sllen; i++ {
- packed.uvarint(slval.Index(i).Uint())
- }
- case reflect.Float32:
- for i := 0; i < sllen; i++ {
- packed.u32(math.Float32bits(
- float32(slval.Index(i).Float())))
- }
- case reflect.Float64:
- for i := 0; i < sllen; i++ {
- packed.u64(math.Float64bits(slval.Index(i).Float()))
- }
- case reflect.Uint8: // Write the byte-slice as one key,value pair
- en.uvarint(key | 2)
- en.uvarint(uint64(sllen))
- var b []byte
- if slval.Kind() == reflect.Array {
- if slval.CanAddr() {
- sliceVal := slval.Slice(0, sllen)
- b = sliceVal.Convert(bytesType).Interface().([]byte)
- } else {
- sliceVal := reflect.MakeSlice(bytesType, sllen, sllen)
- reflect.Copy(sliceVal, slval)
- b = sliceVal.Interface().([]byte)
- }
- } else {
- b = slval.Convert(bytesType).Interface().([]byte)
- }
- en.Write(b)
- return
- default: // Write each element as a separate key,value pair
- t := slval.Type().Elem()
- if t.Kind() == reflect.Slice || t.Kind() == reflect.Array {
- subSlice := t.Elem()
- if subSlice.Kind() != reflect.Uint8 {
- panic("protobuf: no support for 2-dimensional array except for [][]byte")
- }
- }
- for i := 0; i < sllen; i++ {
- en.value(key, slval.Index(i), TagNone)
- }
- return
- }
- // Encode packed representation key/value pair
- en.uvarint(key | 2)
- b := packed.Bytes()
- en.uvarint(uint64(len(b)))
- en.Write(b)
- }
- func (en *encoder) uvarint(v uint64) {
- var b [binary.MaxVarintLen64]byte
- n := binary.PutUvarint(b[:], v)
- en.Write(b[:n])
- }
- func (en *encoder) svarint(v int64) {
- if v >= 0 {
- en.uvarint(uint64(v) << 1)
- } else {
- en.uvarint(^uint64(v << 1))
- }
- }
- func (en *encoder) u32(v uint32) {
- var b [4]byte
- b[0] = byte(v)
- b[1] = byte(v >> 8)
- b[2] = byte(v >> 16)
- b[3] = byte(v >> 24)
- en.Write(b[:])
- }
- func (en *encoder) u64(v uint64) {
- var b [8]byte
- b[0] = byte(v)
- b[1] = byte(v >> 8)
- b[2] = byte(v >> 16)
- b[3] = byte(v >> 24)
- b[4] = byte(v >> 32)
- b[5] = byte(v >> 40)
- b[6] = byte(v >> 48)
- b[7] = byte(v >> 56)
- en.Write(b[:])
- }
|