package ssob import ( "encoding/binary" "errors" "fmt" "reflect" ) func UnmarshalString(in []byte) (ret string, n int, err error) { if len(in) < 8 { return "", 0, errors.New("ssob: Invalid input to decode string") } l := int64(binary.BigEndian.Uint64(in)) if len(in[8:]) < int(l) { return "", 0, errors.New("ssob: Invalid length of string") } return string(in[8 : l+8]), int(l) + 8, nil } func UnmarshalInt8(in []byte) (ret int8, n int, err error) { if len(in) < 1 { return 0, 0, errors.New("ssob: Invalid input to decode int8") } return int8(in[0]), 1, nil } func UnmarshalUint8(in []byte) (ret uint8, n int, err error) { if len(in) < 1 { return 0, 0, errors.New("ssob: Invalid input to decode uint8") } return uint8(in[0]), 1, nil } func UnmarshalInt16(in []byte) (ret int16, n int, err error) { if len(in) < 2 { return 0, 0, errors.New("ssob: Invalid input to decode int16") } return int16(binary.BigEndian.Uint16(in[0:2])), 2, nil } func UnmarshalUint16(in []byte) (ret uint16, n int, err error) { if len(in) < 2 { return 0, 0, errors.New("ssob: Invalid input to decode uint16") } return binary.BigEndian.Uint16(in[0:1]), 2, nil } func UnmarshalInt32(in []byte) (ret int32, n int, err error) { if len(in) < 4 { return 0, 0, errors.New("ssob: Invalid input to decode int32") } return int32(binary.BigEndian.Uint32(in[0:4])), 4, nil } func UnmarshalUint32(in []byte) (ret uint32, n int, err error) { if len(in) < 4 { return 0, 0, errors.New("ssob: Invalid input to decode uint32") } return binary.BigEndian.Uint32(in[0:4]), 4, nil } func UnmarshalFloat32(in []byte) (ret float32, n int, err error) { if len(in) < 4 { return 0, 0, errors.New("ssob: Invalid input to decode float32") } return float32(binary.BigEndian.Uint64(in[0:4])), 4, nil } func UnmarshalInt64(in []byte) (ret int64, n int, err error) { if len(in) < 8 { return 0, 0, errors.New("ssob: Invalid input to decode int64") } return int64(binary.BigEndian.Uint64(in[0:8])), 8, nil } func UnmarshalUint64(in []byte) (ret uint64, n int, err error) { if len(in) < 8 { return 0, 0, errors.New("ssob: Invalid input to decode uint64") } return binary.BigEndian.Uint64(in[0:8]), 8, nil } func UnmarshalFloat64(in []byte) (ret float64, n int, err error) { if len(in) < 8 { return 0, 0, errors.New("ssob: Invalid input to decode float64") } return float64(binary.BigEndian.Uint64(in[0:8])), 8, nil } type unmarshalFunc func(e interface{}, in []byte) (n int, err error) var decoderCache map[string]unmarshalFunc func init() { decoderCache = make(map[string]unmarshalFunc) decRegister(int8(0)) decRegister(uint8(0)) decRegister(int16(0)) decRegister(uint16(0)) decRegister(int32(0)) decRegister(uint32(0)) decRegister(float32(0)) decRegister(int64(0)) decRegister(uint64(0)) decRegister(float64(0)) decRegister(string("")) } func decRegister(e interface{}) (err error) { t := reflect.TypeOf(e) v := reflect.ValueOf(e) switch t.Kind() { case reflect.Invalid: return errors.New("ssob: Invalid type") case reflect.Slice: return errors.New("ssob: Unsupported type") case reflect.Struct: f := func(e interface{}, in []byte) (n int, err error) { t := reflect.TypeOf(e) v := reflect.ValueOf(e) pos := 0 if t.Kind() != reflect.Ptr || v.IsNil() { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } vi := reflect.Indirect(v) l := vi.NumField() for i := 0; i < l; i++ { ni, err := unmarshal(vi.Field(i).Addr().Interface(), in[pos:]) pos += ni if err != nil { return pos, err } } return pos, nil } decoderCache[t.Name()] = f case reflect.Int8: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*int8); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalInt8(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *int8") } decoderCache[string(v.Kind())] = f case reflect.Uint8: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*uint8); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalUint8(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *uint8") } decoderCache[string(v.Kind())] = f case reflect.Int16: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*int16); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalInt16(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *int16") } decoderCache[string(v.Kind())] = f case reflect.Uint16: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*uint16); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalUint16(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *uint16") } decoderCache[string(v.Kind())] = f case reflect.Int32: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*int32); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalInt32(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *int32") } decoderCache[string(v.Kind())] = f case reflect.Uint32: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*uint32); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalUint32(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *uint32") } decoderCache[string(v.Kind())] = f case reflect.Float32: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*float32); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalFloat32(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *float32") } decoderCache[string(v.Kind())] = f case reflect.Int64: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*int64); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalInt64(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *int64") } decoderCache[string(v.Kind())] = f case reflect.Uint64: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*uint64); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalUint64(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *uint64") } decoderCache[string(v.Kind())] = f case reflect.Float64: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*float64); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalFloat64(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *float64") } decoderCache[string(v.Kind())] = f case reflect.String: f := func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*string); ok { if i == nil { return 0, errors.New("ssob: Cannot unmarshal to nil pointer") } *i, n, err = UnmarshalString(in) if err != nil { return 0, err } return n, err } return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *string") } decoderCache[string(v.Kind())] = f default: return errors.New("ssob: Unknown type " + string(v.Kind())) } return nil } func unmarshal(e interface{}, in []byte) (n int, err error) { var key string t := reflect.TypeOf(e) v := reflect.ValueOf(e) if t.Kind() != reflect.Ptr || v.IsNil() { return 0, errors.New("ssob: Need a pointer that is fully allocated for unmarshalling") } p := reflect.Indirect(v) if p.Kind() != reflect.Ptr { if p.Kind() == reflect.Struct { key = reflect.TypeOf(p.Interface()).Name() } else { key = string(p.Kind()) } if f, ok := decoderCache[key]; ok { return f(v.Interface(), in) } else { fmt.Println("Not found") err = decRegister(p.Interface()) if err != nil { return 0, err } } } return unmarshal(e, in) } func RegisterDecoder(name string, f func(e interface{}, in []byte) (n int, err error)) { decoderCache[name] = f }