Added boolean and arrays

This commit is contained in:
Matthias Fulz 2019-10-05 22:12:53 +02:00
parent cfee5a1a4c
commit 45dbd7cbca
4 changed files with 184 additions and 0 deletions

View File

@ -15,6 +15,14 @@ func MarshalString(in string) (ret []byte) {
return ret
}
func MarshalBool(in bool) (ret []byte) {
if in {
return []byte{byte(0)}
}
return []byte{byte(1)}
}
func MarshalInt8(in int8) (ret []byte) {
return []byte{byte(in)}
}
@ -85,6 +93,12 @@ var encoderCache map[string]MarshalFunc
func init() {
encoderCache = make(map[string]MarshalFunc)
RegisterEncoder("bool", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(bool); ok {
return MarshalBool(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected bool")
})
RegisterEncoder("int8", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int8); ok {
return MarshalInt8(i), nil
@ -159,6 +173,30 @@ func encRegister(e interface{}) (err error) {
switch t.Kind() {
case reflect.Invalid:
return errors.New("ssob: Invalid type")
case reflect.Array:
f := func(e interface{}) (ret []byte, err error) {
v := reflect.ValueOf(e)
l := v.Len()
slen := MarshalInt32(int32(l))
blen := 4
bs := make([][]byte, l)
for i := 0; i < l; i++ {
bs[i], err = marshal(v.Index(i).Interface())
if err != nil {
return nil, err
}
blen += len(bs[i])
}
ret = make([]byte, blen)
i := copy(ret, slen)
for c := 0; c < l; c++ {
i += copy(ret[i:], bs[c])
}
return ret, nil
}
encoderCache[string(t.Kind())] = f
case reflect.Slice:
f := func(e interface{}) (ret []byte, err error) {
v := reflect.ValueOf(e)
@ -234,6 +272,8 @@ func encRegister(e interface{}) (err error) {
func marshalBaseType(e interface{}) (ret []byte, err error) {
switch t := e.(type) {
case bool:
return encoderCache["bool"](t)
case int8:
return encoderCache["int8"](t)
case uint8:

View File

@ -18,6 +18,17 @@ func UnmarshalString(in []byte) (ret string, n int, err error) {
return string(in[4 : l+4]), int(l) + 4, nil
}
func UnmarshalBool(in []byte) (ret bool, n int, err error) {
if len(in) < 1 {
return false, 0, errors.New("ssob: Invalid input to decode bool")
}
if in[0] == byte(0) {
return true, 1, nil
}
return false, 1, 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")
@ -104,6 +115,13 @@ var decoderCache map[string]unmarshalFunc
func init() {
decoderCache = make(map[string]unmarshalFunc)
RegisterDecoder("bool", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*bool); ok {
*i, n, err = UnmarshalBool(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected bool")
})
RegisterDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int8); ok {
*i, n, err = UnmarshalInt8(in)
@ -189,6 +207,38 @@ func decRegister(e interface{}) (err error) {
switch t.Kind() {
case reflect.Invalid:
return errors.New("ssob: Invalid type")
case reflect.Array:
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")
}
l, r, err := UnmarshalInt32(in)
pos += r
if err != nil {
return pos, err
}
ti := v.Elem()
if int(l) != ti.Len() {
return pos, errors.New("ssob: Invalid array length. Expected " + string(l) + " got " + string(ti.Len()))
}
for i := 0; i < int(l); i++ {
e := reflect.New(reflect.TypeOf(ti.Interface()).Elem())
r, err := unmarshal(e.Interface(), in[pos:])
pos += r
if err != nil {
return pos, err
}
ti.Index(i).Set(reflect.Indirect(e))
}
return pos, nil
}
decoderCache[string(t.Kind())] = f
case reflect.Slice:
f := func(e interface{}, in []byte) (n int, err error) {
t := reflect.TypeOf(e)
@ -290,6 +340,8 @@ func decRegister(e interface{}) (err error) {
func unmarshalBaseType(e interface{}, in []byte) (n int, err error) {
switch t := e.(type) {
case *bool:
return decoderCache["bool"](t, in)
case *int8:
return decoderCache["int8"](t, in)
case *uint8:

View File

@ -15,6 +15,14 @@ func UnsafeMarshalString(in string) (ret []byte) {
return ret
}
func UnsafeMarshalBool(in bool) (ret []byte) {
if in {
return []byte{byte(0)}
}
return []byte{byte(1)}
}
func UnsafeMarshalInt8(in int8) (ret []byte) {
return []byte{byte(in)}
}
@ -195,6 +203,12 @@ var unsafeEncoderCache map[string]MarshalFunc
func init() {
unsafeEncoderCache = make(map[string]MarshalFunc)
RegisterUnsafeEncoder("bool", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(bool); ok {
return UnsafeMarshalBool(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected bool")
})
RegisterUnsafeEncoder("int8", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int8); ok {
return UnsafeMarshalInt8(i), nil
@ -269,6 +283,30 @@ func encRegisterUnsafe(e interface{}) (err error) {
switch t.Kind() {
case reflect.Invalid:
return errors.New("ssob: Invalid type")
case reflect.Array:
f := func(e interface{}) (ret []byte, err error) {
v := reflect.ValueOf(e)
l := v.Len()
slen := UnsafeMarshalInt32(int32(l))
blen := 4
bs := make([][]byte, l)
for i := 0; i < l; i++ {
bs[i], err = unsafeMarshal(v.Index(i).Interface())
if err != nil {
return nil, err
}
blen += len(bs[i])
}
ret = make([]byte, blen)
i := copy(ret, slen)
for c := 0; c < l; c++ {
i += copy(ret[i:], bs[c])
}
return ret, nil
}
unsafeEncoderCache[string(t.Kind())] = f
case reflect.Slice:
f := func(e interface{}) (ret []byte, err error) {
v := reflect.ValueOf(e)
@ -344,6 +382,8 @@ func encRegisterUnsafe(e interface{}) (err error) {
func unsafeMarshalBaseType(e interface{}) (ret []byte, err error) {
switch t := e.(type) {
case bool:
return unsafeEncoderCache["bool"](t)
case int8:
return unsafeEncoderCache["int8"](t)
case uint8:

View File

@ -19,6 +19,17 @@ func UnsafeUnmarshalString(in []byte) (ret string, n int, err error) {
return string(in[4 : l+4]), int(l) + 4, nil
}
func UnsafeUnmarshalBool(in []byte) (ret bool, n int, err error) {
if len(in) < 1 {
return false, 0, errors.New("ssob: Invalid input to decode bool")
}
if in[0] == byte(0) {
return true, 1, nil
}
return false, 1, nil
}
func UnsafeUnmarshalInt8(in []byte) (ret int8, n int, err error) {
if len(in) < 1 {
return 0, 0, errors.New("ssob: Invalid input to decode int8")
@ -231,6 +242,13 @@ var unsafeDecoderCache map[string]unmarshalFunc
func init() {
unsafeDecoderCache = make(map[string]unmarshalFunc)
RegisterUnsafeDecoder("bool", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*bool); ok {
*i, n, err = UnsafeUnmarshalBool(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected bool")
})
RegisterUnsafeDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int8); ok {
*i, n, err = UnsafeUnmarshalInt8(in)
@ -316,6 +334,38 @@ func decRegisterUnsafe(e interface{}) (err error) {
switch t.Kind() {
case reflect.Invalid:
return errors.New("ssob: Invalid type")
case reflect.Array:
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")
}
l, r, err := UnsafeUnmarshalInt32(in)
pos += r
if err != nil {
return pos, err
}
ti := v.Elem()
if int(l) != ti.Len() {
return pos, errors.New("ssob: Invalid array length. Expected " + string(l) + " got " + string(ti.Len()))
}
for i := 0; i < int(l); i++ {
e := reflect.New(reflect.TypeOf(ti.Interface()).Elem())
r, err := unsafeUnmarshal(e.Interface(), in[pos:])
pos += r
if err != nil {
return pos, err
}
ti.Index(i).Set(reflect.Indirect(e))
}
return pos, nil
}
unsafeDecoderCache[string(t.Kind())] = f
case reflect.Slice:
f := func(e interface{}, in []byte) (n int, err error) {
t := reflect.TypeOf(e)
@ -417,6 +467,8 @@ func decRegisterUnsafe(e interface{}) (err error) {
func unsafeUnmarshalBaseType(e interface{}, in []byte) (n int, err error) {
switch t := e.(type) {
case *bool:
return unsafeDecoderCache["bool"](t, in)
case *int8:
return unsafeDecoderCache["int8"](t, in)
case *uint8: