package yu_proto_old import ( "encoding" "encoding/binary" "errors" "fmt" "math" "reflect" "time" ) // Constructors represents a map defining how to instantiate any interface // types that Decode() might encounter while reading and decoding structured // data. The keys are reflect.Type values denoting interface types. The // corresponding values are functions expected to instantiate, and initialize // as necessary, an appropriate concrete object type supporting that // interface. A caller could use this capability to support // dynamic instantiation of objects of the concrete type // appropriate for a given abstract type. type Constructors map[reflect.Type]func() interface{} // String returns an easy way to visualize what you have in your constructors. func (c *Constructors) String() string { var s string for k := range *c { s += k.String() + "=>" + "(func() interface {})" + "\t" } return s } // Decoder is the main struct used to decode a protobuf blob. type decoder struct { nm Constructors } // Decode a protocol buffer into a Go struct. // The caller must pass a pointer to the struct to decode into. // // Decode() currently does not explicitly check that all 'required' fields // are actually present in the input buffer being decoded. // If required fields are missing, then the corresponding fields // will be left unmodified, meaning they will take on // their default Go zero values if Decode() is passed a fresh struct. func Decode(buf []byte, structPtr interface{}) error { return DecodeWithConstructors(buf, structPtr, nil) } // DecodeWithConstructors is like Decode, but you can pass a map of // constructors with which to instantiate interface types. func DecodeWithConstructors(buf []byte, structPtr interface{}, cons Constructors) (err error) { defer func() { if r := recover(); r != nil { switch e := r.(type) { case string: err = errors.New(e) case error: err = e default: err = errors.New("Failed to decode the field") } } }() if structPtr == nil { return nil } if bu, ok := structPtr.(encoding.BinaryUnmarshaler); ok { return bu.UnmarshalBinary(buf) } de := decoder{cons} val := reflect.ValueOf(structPtr) // if its NOT a pointer, it is bad return an error if val.Kind() != reflect.Ptr { return errors.New("Decode has been given a non pointer type") } return de.message(buf, val.Elem()) } // Decode a Protocol Buffers message into a Go struct. // The Kind of the passed value v must be Struct. func (de *decoder) message(buf []byte, sval reflect.Value) error { if sval.Kind() != reflect.Struct { return errors.New("not a struct") } for i := 0; i < sval.NumField(); i++ { switch field := sval.Field(i); field.Kind() { case reflect.Interface: // Interface are not reset because the decoder won't // be able to instantiate it again in some scenarios. default: if field.CanSet() { field.Set(reflect.Zero(field.Type())) } } } // Decode all the fields fields := ProtoFields(sval.Type()) fieldi := 0 for len(buf) > 0 { // Parse the key key, n := binary.Uvarint(buf) if n <= 0 { return errors.New("bad protobuf field key") } buf = buf[n:] wiretype := int(key & 7) fieldnum := key >> 3 // Lookup the corresponding struct field. // Leave field with a zero Value if fieldnum is out-of-range. // In this case, as well as for blank fields, // value() will just skip over and discard the field content. var field reflect.Value for fieldi < len(fields) && fields[fieldi].ID < int64(fieldnum) { fieldi++ } if fieldi < len(fields) && fields[fieldi].ID == int64(fieldnum) { // For fields within embedded structs, ensure the embedded values aren't nil. index := fields[fieldi].Index path := make([]int, 0, len(index)) for _, id := range index { path = append(path, id) field = sval.FieldByIndex(path) if field.Kind() == reflect.Ptr && field.IsNil() { field.Set(reflect.New(field.Type().Elem())) } } } // For more debugging output, uncomment the following three lines. // if fieldi < len(fields){ // fmt.Printf("Decoding FieldName %+v\n", fields[fieldi].Field) // } // Decode the field's value rem, err := de.value(wiretype, buf, field) if err != nil { if fieldi < len(fields) && fields[fieldi] != nil { return fmt.Errorf("Error while decoding field %+v: %v", fields[fieldi].Field, err) } return err } buf = rem } return nil } // Pull a value from the buffer and put it into a reflective Value. func (de *decoder) value(wiretype int, buf []byte, val reflect.Value) ([]byte, error) { // Break out the value from the buffer based on the wire type var v uint64 var n int var vb []byte switch wiretype { case 0: // varint v, n = binary.Uvarint(buf) if n <= 0 { return nil, errors.New("bad protobuf varint value") } buf = buf[n:] case 5: // 32-bit if len(buf) < 4 { return nil, errors.New("bad protobuf 32-bit value") } v = uint64(buf[0]) | uint64(buf[1])<<8 | uint64(buf[2])<<16 | uint64(buf[3])<<24 buf = buf[4:] case 1: // 64-bit if len(buf) < 8 { return nil, errors.New("bad protobuf 64-bit value") } v = uint64(buf[0]) | uint64(buf[1])<<8 | uint64(buf[2])<<16 | uint64(buf[3])<<24 | uint64(buf[4])<<32 | uint64(buf[5])<<40 | uint64(buf[6])<<48 | uint64(buf[7])<<56 buf = buf[8:] case 2: // length-delimited v, n = binary.Uvarint(buf) if n <= 0 || v > uint64(len(buf)-n) { return nil, errors.New( "bad protobuf length-delimited value") } vb = buf[n : n+int(v) : n+int(v)] buf = buf[n+int(v):] default: return nil, errors.New("unknown protobuf wire-type") } // We've gotten the value out of the buffer, // now put it into the appropriate reflective Value. if err := de.putvalue(wiretype, val, v, vb); err != nil { return nil, err } return buf, nil } func (de *decoder) decodeSignedInt(wiretype int, v uint64) (int64, error) { if wiretype == 0 { // encoded as varint sv := int64(v) >> 1 if v&1 != 0 { sv = ^sv } return sv, nil } else if wiretype == 5 { // sfixed32 return int64(int32(v)), nil } else if wiretype == 1 { // sfixed64 return int64(v), nil } else { return -1, errors.New("bad wiretype for sint") } } func (de *decoder) putvalue(wiretype int, val reflect.Value, v uint64, vb []byte) error { // If val is not settable, it either represents an out-of-range field // or an in-range but blank (padding) field in the struct. // In this case, simply ignore and discard the field's content. if !val.CanSet() { return nil } switch val.Kind() { case reflect.Bool: if wiretype != 0 { return errors.New("bad wiretype for bool") } if v > 1 { return errors.New("invalid bool value") } val.SetBool(v != 0) case reflect.Int, reflect.Int32, reflect.Int64: // Signed integers may be encoded either zigzag-varint or fixed // Note that protobufs don't support 8- or 16-bit ints. if val.Kind() == reflect.Int && val.Type().Size() < 8 { return errors.New("detected a 32bit machine, please use either int64 or int32") } sv, err := de.decodeSignedInt(wiretype, v) if err != nil { fmt.Println("Error Reflect.Int for v=", v, "wiretype=", wiretype, "for Value=", val.Type().Name()) return err } val.SetInt(sv) case reflect.Uint, reflect.Uint32, reflect.Uint64: // Varint-encoded 32-bit and 64-bit unsigned integers. if val.Kind() == reflect.Uint && val.Type().Size() < 8 { return errors.New("detected a 32bit machine, please use either uint64 or uint32") } if wiretype == 0 { val.SetUint(v) } else if wiretype == 5 { // ufixed32 val.SetUint(uint64(uint32(v))) } else if wiretype == 1 { // ufixed64 val.SetUint(uint64(v)) } else { return errors.New("bad wiretype for uint") } case reflect.Float32: // Fixed-length 32-bit floats. if wiretype != 5 { return errors.New("bad wiretype for float32") } val.SetFloat(float64(math.Float32frombits(uint32(v)))) case reflect.Float64: // Fixed-length 64-bit floats. if wiretype != 1 { return errors.New("bad wiretype for float64") } val.SetFloat(math.Float64frombits(v)) case reflect.String: // Length-delimited string. if wiretype != 2 { return errors.New("bad wiretype for string") } val.SetString(string(vb)) case reflect.Struct: // Embedded message if val.Type() == timeType { sv, err := de.decodeSignedInt(wiretype, v) if err != nil { return err } t := time.Unix(sv/int64(time.Second), sv%int64(time.Second)) val.Set(reflect.ValueOf(t)) return nil } else if enc, ok := val.Addr().Interface().(encoding.BinaryUnmarshaler); ok { return enc.UnmarshalBinary(vb[:]) } if wiretype != 2 { return errors.New("bad wiretype for embedded message") } return de.message(vb, val) case reflect.Ptr: // Optional field // Instantiate pointer's element type. if val.IsNil() { val.Set(de.instantiate(val.Type().Elem())) } return de.putvalue(wiretype, val.Elem(), v, vb) case reflect.Slice, reflect.Array: // Repeated field or byte-slice if wiretype != 2 { return errors.New("bad wiretype for repeated field") } return de.slice(val, vb) case reflect.Map: if wiretype != 2 { return errors.New("bad wiretype for repeated field") } if val.IsNil() { // make(map[k]v): val.Set(reflect.MakeMap(val.Type())) } return de.mapEntry(val, vb) case reflect.Interface: data := vb[:] // Abstract field: instantiate via dynamic constructor. if val.IsNil() { id := GeneratorID{} var g InterfaceGeneratorFunc if len(id) < len(vb) { copy(id[:], vb[:len(id)]) g = generators.get(id) } if g == nil { // Backwards compatible usage of the default constructors val.Set(de.instantiate(val.Type())) } else { // As pointers to interface are discouraged in Go, we use // the generator only for interface types data = vb[len(id):] val.Set(reflect.ValueOf(g())) } } // If the object support self-decoding, use that. if enc, ok := val.Interface().(encoding.BinaryUnmarshaler); ok { if wiretype != 2 { return errors.New("bad wiretype for bytes") } return enc.UnmarshalBinary(data) } // Decode into the object the interface points to. // XXX perhaps better ONLY to support self-decoding // for interface fields? return Decode(vb, val.Interface()) default: panic("unsupported value kind " + val.Kind().String()) } return nil } // Instantiate an arbitrary type, handling dynamic interface types. // Returns a Ptr value. func (de *decoder) instantiate(t reflect.Type) reflect.Value { // If it's an interface type, lookup a dynamic constructor for it. if t.Kind() == reflect.Interface { newfunc, ok := de.nm[t] if !ok { panic("no constructor for interface " + t.String()) } return reflect.ValueOf(newfunc()) } // Otherwise, for all concrete types, just instantiate directly. return reflect.New(t) } var sfixed32type = reflect.TypeOf(Sfixed32(0)) var sfixed64type = reflect.TypeOf(Sfixed64(0)) var ufixed32type = reflect.TypeOf(Ufixed32(0)) var ufixed64type = reflect.TypeOf(Ufixed64(0)) // Handle decoding of slices func (de *decoder) slice(slval reflect.Value, vb []byte) error { // Find the element type, and create a temporary instance of it. eltype := slval.Type().Elem() val := reflect.New(eltype).Elem() // Decide on the wiretype to use for decoding. var wiretype int switch eltype.Kind() { case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Int, reflect.Uint32, reflect.Uint64, reflect.Uint: if (eltype.Kind() == reflect.Int || eltype.Kind() == reflect.Uint) && eltype.Size() < 8 { return errors.New("detected a 32bit machine, please either use (u)int64 or (u)int32") } switch eltype { case sfixed32type: wiretype = 5 // Packed 32-bit representation case sfixed64type: wiretype = 1 // Packed 64-bit representation case ufixed32type: wiretype = 5 // Packed 32-bit representation case ufixed64type: wiretype = 1 // Packed 64-bit representation default: wiretype = 0 // Packed varint representation } case reflect.Float32: wiretype = 5 // Packed 32-bit representation case reflect.Float64: wiretype = 1 // Packed 64-bit representation case reflect.Uint8: // Unpacked byte-slice if slval.Kind() == reflect.Array { if slval.Len() != len(vb) { return errors.New("array length and buffer length differ") } for i := 0; i < slval.Len(); i++ { // no SetByte method in reflect so has to pass down by uint64 slval.Index(i).SetUint(uint64(vb[i])) } } else { slval.SetBytes(vb) } return nil default: // Other unpacked repeated types // Just unpack and append one value from vb. if err := de.putvalue(2, val, 0, vb); err != nil { return err } if slval.Kind() != reflect.Slice { return errors.New("append to non-slice") } slval.Set(reflect.Append(slval, val)) return nil } // Decode packed values from the buffer and append them to the slice. for len(vb) > 0 { rem, err := de.value(wiretype, vb, val) if err != nil { return err } slval.Set(reflect.Append(slval, val)) vb = rem } return nil } // Handles the entry k,v of a map[K]V func (de *decoder) mapEntry(slval reflect.Value, vb []byte) error { mKey := reflect.New(slval.Type().Key()) mVal := reflect.New(slval.Type().Elem()) k := mKey.Elem() v := mVal.Elem() key, n := binary.Uvarint(vb) if n <= 0 { return errors.New("bad protobuf field key") } buf := vb[n:] wiretype := int(key & 7) var err error buf, err = de.value(wiretype, buf, k) if err != nil { return err } for len(buf) > 0 { // for repeated values (slices etc) key, n = binary.Uvarint(buf) if n <= 0 { return errors.New("bad protobuf field key") } buf = buf[n:] wiretype = int(key & 7) buf, err = de.value(wiretype, buf, v) if err != nil { return err } } if !k.IsValid() || !v.IsValid() { // We did not decode the key or the value in the map entry. // Either way, it's an invalid map entry. return errors.New("proto: bad map data: missing key/val") } slval.SetMapIndex(k, v) return nil }