2019-10-04 12:28:45 +02:00
|
|
|
package ssob
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"errors"
|
2019-10-04 17:58:17 +02:00
|
|
|
"fmt"
|
2019-10-04 12:28:45 +02:00
|
|
|
"reflect"
|
|
|
|
)
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalString(in []byte) (ret string, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalInt8(in []byte) (ret int8, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 1 {
|
|
|
|
return 0, 0, errors.New("ssob: Invalid input to decode int8")
|
|
|
|
}
|
|
|
|
|
|
|
|
return int8(in[0]), 1, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalUint8(in []byte) (ret uint8, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 1 {
|
|
|
|
return 0, 0, errors.New("ssob: Invalid input to decode uint8")
|
|
|
|
}
|
|
|
|
|
|
|
|
return uint8(in[0]), 1, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalInt16(in []byte) (ret int16, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalUint16(in []byte) (ret uint16, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 2 {
|
|
|
|
return 0, 0, errors.New("ssob: Invalid input to decode uint16")
|
|
|
|
}
|
|
|
|
|
|
|
|
return binary.BigEndian.Uint16(in[0:1]), 2, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalInt32(in []byte) (ret int32, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalUint32(in []byte) (ret uint32, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 4 {
|
|
|
|
return 0, 0, errors.New("ssob: Invalid input to decode uint32")
|
|
|
|
}
|
|
|
|
|
|
|
|
return binary.BigEndian.Uint32(in[0:4]), 4, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalFloat32(in []byte) (ret float32, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalInt64(in []byte) (ret int64, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalUint64(in []byte) (ret uint64, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 8 {
|
|
|
|
return 0, 0, errors.New("ssob: Invalid input to decode uint64")
|
|
|
|
}
|
|
|
|
|
|
|
|
return binary.BigEndian.Uint64(in[0:8]), 8, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalFloat64(in []byte) (ret float64, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalInt8(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalUint8(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalInt16(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalUint16(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalInt32(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalUint32(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalFloat32(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalInt64(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalUint64(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalFloat64(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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")
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
*i, n, err = UnmarshalString(in)
|
2019-10-04 12:28:45 +02:00
|
|
|
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 {
|
2019-10-04 17:58:17 +02:00
|
|
|
fmt.Println("Not found")
|
2019-10-04 12:28:45 +02:00
|
|
|
err = decRegister(p.Interface())
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return unmarshal(e, in)
|
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
|
|
|
|
func RegisterDecoder(name string, f func(e interface{}, in []byte) (n int, err error)) {
|
|
|
|
decoderCache[name] = f
|
|
|
|
}
|