Added error type.

Error handling with sub types
This commit is contained in:
Matthias Fulz 2021-08-21 22:29:18 +02:00
parent 3b56e93763
commit 5d63c6d16a
10 changed files with 160 additions and 122 deletions

View File

@ -1,13 +1,13 @@
package ssob
import (
"errors"
"fmt"
"reflect"
)
func allocType(out reflect.Value) (err error) {
if out.Type().Kind() != reflect.Ptr || out.IsNil() {
return errors.New("ssob: Error allocating type (Got nil pointer)")
return fmt.Errorf("ssob: Error allocating type (Got nil pointer): %w", ErrValueInvalid)
}
t := out.Elem().Type()

View File

@ -3,6 +3,7 @@ package ssob
import (
"encoding/binary"
"errors"
"fmt"
"io"
"reflect"
"sync"
@ -24,12 +25,23 @@ func (dec *Decoder) Decode(e interface{}) (err error) {
}
func (dec *Decoder) DecodeValue(value reflect.Value) (err error) {
if value.Type() == reflect.TypeOf(errors.New("")) || value.Type() == reflect.TypeOf((*error)(nil)) {
var errstr string
if err = dec.Decode(&errstr); err != nil {
return err
}
if errstr != "" {
*value.Interface().(*error) = errors.New(errstr)
}
return nil
}
if value.Kind() == reflect.Invalid {
return errors.New("ssob: Cannot decode nil value")
return fmt.Errorf("ssob: Cannot decode nil: %w", ErrValueInvalid)
}
if value.Kind() == reflect.Ptr && value.IsNil() {
return errors.New("ssob: Cannot decode nil of type " + value.Type().String())
return fmt.Errorf("ssob: Cannot decode nil of type %s: %w", value.Type().String(), ErrValueInvalid)
}
dec.mutex.Lock()

View File

@ -3,6 +3,7 @@ package ssob
import (
"encoding/binary"
"errors"
"fmt"
"io"
"reflect"
"sync"
@ -24,12 +25,20 @@ func (enc *Encoder) Encode(e interface{}) (err error) {
}
func (enc *Encoder) EncodeValue(value reflect.Value) (err error) {
if value.Type() == reflect.TypeOf(errors.New("")) || value.Type() == reflect.TypeOf((*error)(nil)).Elem() {
if value.IsNil() {
return enc.Encode(string(""))
} else {
return enc.Encode(value.Interface().(error).Error())
}
}
if value.Kind() == reflect.Invalid {
return errors.New("ssob: Cannot encode nil value")
return fmt.Errorf("ssob: Cannot encode nil: %w", ErrValueInvalid)
}
if value.Kind() == reflect.Ptr && value.IsNil() {
return errors.New("ssob: Cannot encode nil of type " + value.Type().String())
return fmt.Errorf("ssob: Cannot encode nil of type %s: %w", value.Type().String(), ErrValueInvalid)
}
bb, err := marshal(value.Interface())

9
error.go Normal file
View File

@ -0,0 +1,9 @@
package ssob
import "errors"
var ErrValueInvalid = errors.New("value invalid")
var ErrTypeInvalid = errors.New("type invalid")
var ErrTypeUnknown = errors.New("type unknown")
var ErrTypeMismatch = errors.New("type mismatch")
var ErrParseFailed = errors.New("parsing failed")

View File

@ -2,7 +2,7 @@ package ssob
import (
"encoding/binary"
"errors"
"fmt"
"math"
"reflect"
)
@ -98,85 +98,85 @@ func init() {
if i, ok := e.(bool); ok {
return MarshalBool(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected bool")
return nil, fmt.Errorf("ssob: Incompatible type - expected bool: %w", ErrTypeMismatch)
})
RegisterEncoder("int8", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int8); ok {
return MarshalInt8(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected int8")
return nil, fmt.Errorf("ssob: Incompatible type - expected int8: %w", ErrTypeMismatch)
})
RegisterEncoder("uint8", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint8); ok {
return MarshalUint8(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected uint8")
return nil, fmt.Errorf("ssob: Incompatible type - expected uint8: %w", ErrTypeMismatch)
})
RegisterEncoder("int16", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int16); ok {
return MarshalInt16(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected int16")
return nil, fmt.Errorf("ssob: Incompatible type - expected int16: %w", ErrTypeMismatch)
})
RegisterEncoder("uint16", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint16); ok {
return MarshalUint16(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected uint16")
return nil, fmt.Errorf("ssob: Incompatible type - expected uint16: %w", ErrTypeMismatch)
})
RegisterEncoder("int32", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int32); ok {
return MarshalInt32(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected int32")
return nil, fmt.Errorf("ssob: Incompatible type - expected int32: %w", ErrTypeMismatch)
})
RegisterEncoder("uint32", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint32); ok {
return MarshalUint32(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected uint32")
return nil, fmt.Errorf("ssob: Incompatible type - expected uint32: %w", ErrTypeMismatch)
})
RegisterEncoder("float32", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(float32); ok {
return MarshalFloat32(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected float32")
return nil, fmt.Errorf("ssob: Incompatible type - expected float32: %w", ErrTypeMismatch)
})
RegisterEncoder("int64", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int64); ok {
return MarshalInt64(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected int64")
return nil, fmt.Errorf("ssob: Incompatible type - expected int64: %w", ErrTypeMismatch)
})
RegisterEncoder("uint64", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint64); ok {
return MarshalUint64(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected uint64")
return nil, fmt.Errorf("ssob: Incompatible type - expected uint64: %w", ErrTypeMismatch)
})
RegisterEncoder("float64", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(float64); ok {
return MarshalFloat64(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected float64")
return nil, fmt.Errorf("ssob: Incompatible type - expected float64: %w", ErrTypeMismatch)
})
RegisterEncoder("string", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(string); ok {
return MarshalString(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected string")
return nil, fmt.Errorf("ssob: Incompatible type - expected string: %w", ErrTypeMismatch)
})
}
func encRegister(e interface{}) (err error) {
t := reflect.TypeOf(e)
if t == nil {
return errors.New("ssob: Invalid type")
return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
}
switch t.Kind() {
case reflect.Invalid:
return errors.New("ssob: Invalid type")
return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
case reflect.Array:
f := func(e interface{}) (ret []byte, err error) {
v := reflect.ValueOf(e)
@ -257,7 +257,7 @@ func encRegister(e interface{}) (err error) {
}
}
if len(mfields) == 0 {
return errors.New("ssob: No exported fields for " + string(t.Name()))
return fmt.Errorf("ssob: No exported fields for %s: %w", string(t.Name()), ErrParseFailed)
}
f := func(e interface{}) (ret []byte, err error) {
@ -340,7 +340,7 @@ func encRegister(e interface{}) (err error) {
}
encoderCache[t.Name()] = f
default:
return errors.New("ssob: Unknown type " + string(t.Name()))
return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
}
return nil
@ -373,7 +373,7 @@ func marshalBaseType(e interface{}) (ret []byte, err error) {
case string:
return encoderCache["string"](t)
default:
return nil, errors.New("ssob: No base type")
return nil, fmt.Errorf("ssob: No base type: %w", ErrTypeUnknown)
}
}
@ -389,7 +389,7 @@ func marshal(e interface{}) (ret []byte, err error) {
switch t.Kind() {
case reflect.Ptr:
if v.IsNil() {
return nil, errors.New("ssob: Cannot marshal nil pointer")
return nil, fmt.Errorf("ssob: Cannot marshal nil pointer: %w", ErrValueInvalid)
}
p := reflect.Indirect(v)
return marshal(p.Interface())

View File

@ -2,26 +2,26 @@ package ssob
import (
"encoding/binary"
"errors"
"fmt"
"math"
"reflect"
)
func UnmarshalString(in []byte) (ret string, n int, err error) {
if len(in) < 4 {
return "", 0, errors.New("ssob: Invalid input to decode string")
return "", 0, fmt.Errorf("ssob: Decoding string: %w", ErrTypeInvalid)
}
l := int32(binary.BigEndian.Uint32(in))
if len(in[4:]) < int(l) {
return "", 0, errors.New("ssob: Invalid length of string")
return "", 0, fmt.Errorf("ssob: Invalid length of string: %w", ErrValueInvalid)
}
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")
return false, 0, fmt.Errorf("ssob: Decoding bool: %w", ErrTypeInvalid)
}
if in[0] == byte(0) {
@ -32,7 +32,7 @@ func UnmarshalBool(in []byte) (ret bool, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding int8: %w", ErrTypeInvalid)
}
return int8(in[0]), 1, nil
@ -40,7 +40,7 @@ func UnmarshalInt8(in []byte) (ret int8, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding uint8: %w", ErrTypeInvalid)
}
return uint8(in[0]), 1, nil
@ -48,7 +48,7 @@ func UnmarshalUint8(in []byte) (ret uint8, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding int16: %w", ErrTypeInvalid)
}
return int16(binary.BigEndian.Uint16(in[0:2])), 2, nil
@ -56,7 +56,7 @@ func UnmarshalInt16(in []byte) (ret int16, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding uint16: %w", ErrTypeInvalid)
}
return binary.BigEndian.Uint16(in[0:2]), 2, nil
@ -64,7 +64,7 @@ func UnmarshalUint16(in []byte) (ret uint16, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding int32: %w", ErrTypeInvalid)
}
return int32(binary.BigEndian.Uint32(in[0:4])), 4, nil
@ -72,7 +72,7 @@ func UnmarshalInt32(in []byte) (ret int32, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding uint32: %w", ErrTypeInvalid)
}
return binary.BigEndian.Uint32(in[0:4]), 4, nil
@ -80,7 +80,7 @@ func UnmarshalUint32(in []byte) (ret uint32, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding float32: %w", ErrTypeInvalid)
}
return float32(math.Float32frombits(binary.BigEndian.Uint32(in[0:4]))), 4, nil
@ -88,7 +88,7 @@ func UnmarshalFloat32(in []byte) (ret float32, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding int64: %w", ErrTypeInvalid)
}
return int64(binary.BigEndian.Uint64(in[0:8])), 8, nil
@ -96,7 +96,7 @@ func UnmarshalInt64(in []byte) (ret int64, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding uint64: %w", ErrTypeInvalid)
}
return binary.BigEndian.Uint64(in[0:8]), 8, nil
@ -104,7 +104,7 @@ func UnmarshalUint64(in []byte) (ret uint64, n int, err error) {
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 0, 0, fmt.Errorf("ssob: Decoding float64: %w", ErrTypeInvalid)
}
return float64(math.Float64frombits(binary.BigEndian.Uint64(in[0:8]))), 8, nil
@ -121,96 +121,96 @@ func init() {
*i, n, err = UnmarshalBool(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected bool")
return 0, fmt.Errorf("ssob: Incompatible type - expected bool: %w", ErrTypeMismatch)
})
RegisterDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int8); ok {
*i, n, err = UnmarshalInt8(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected int8")
return 0, fmt.Errorf("ssob: Incompatible type - expected int8: %w", ErrTypeMismatch)
})
RegisterDecoder("uint8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint8); ok {
*i, n, err = UnmarshalUint8(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected uint8")
return 0, fmt.Errorf("ssob: Incompatible type - expected uint8: %w", ErrTypeMismatch)
})
RegisterDecoder("int16", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int16); ok {
*i, n, err = UnmarshalInt16(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected int16")
return 0, fmt.Errorf("ssob: Incompatible type - expected int16: %w", ErrTypeMismatch)
})
RegisterDecoder("uint16", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint16); ok {
*i, n, err = UnmarshalUint16(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected uint16")
return 0, fmt.Errorf("ssob: Incompatible type - expected uint16: %w", ErrTypeMismatch)
})
RegisterDecoder("int32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int32); ok {
*i, n, err = UnmarshalInt32(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected int32")
return 0, fmt.Errorf("ssob: Incompatible type - expected int32: %w", ErrTypeMismatch)
})
RegisterDecoder("uint32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint32); ok {
*i, n, err = UnmarshalUint32(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected uint32")
return 0, fmt.Errorf("ssob: Incompatible type - expected uint32: %w", ErrTypeMismatch)
})
RegisterDecoder("float32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*float32); ok {
*i, n, err = UnmarshalFloat32(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected float32")
return 0, fmt.Errorf("ssob: Incompatible type - expected float32: %w", ErrTypeMismatch)
})
RegisterDecoder("int64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int64); ok {
*i, n, err = UnmarshalInt64(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected int64")
return 0, fmt.Errorf("ssob: Incompatible type - expected int64: %w", ErrTypeMismatch)
})
RegisterDecoder("uint64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint64); ok {
*i, n, err = UnmarshalUint64(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected uint64")
return 0, fmt.Errorf("ssob: Incompatible type - expected uint64: %w", ErrTypeMismatch)
})
RegisterDecoder("float64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*float64); ok {
*i, n, err = UnmarshalFloat64(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected float64")
return 0, fmt.Errorf("ssob: Incompatible type - expected float64: %w", ErrTypeMismatch)
})
RegisterDecoder("string", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*string); ok {
*i, n, err = UnmarshalString(in)
return n, err
}
return 0, errors.New("ssob: Incompatible type - expected string")
return 0, fmt.Errorf("ssob: Incompatible type - expected string: %w", ErrTypeMismatch)
})
}
func decRegister(e interface{}) (err error) {
t := reflect.TypeOf(e)
if t == nil {
return errors.New("ssob: Invalid type")
return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
}
switch t.Kind() {
case reflect.Invalid:
return errors.New("ssob: Invalid type")
return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
case reflect.Array:
f := func(e interface{}, in []byte) (n int, err error) {
t := reflect.TypeOf(e)
@ -218,7 +218,7 @@ func decRegister(e interface{}) (err error) {
pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() {
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
}
l, r, err := UnmarshalInt32(in)
@ -229,7 +229,7 @@ func decRegister(e interface{}) (err error) {
ti := v.Elem()
if int(l) != ti.Len() {
return pos, errors.New("ssob: Invalid array length. Expected " + string(l) + " got " + string(ti.Len()))
return pos, fmt.Errorf("ssob: Invalid array length. Expected %s got %s: %w", string(l), string(ti.Len()), ErrValueInvalid)
}
for i := 0; i < int(l); i++ {
e := reflect.New(reflect.TypeOf(ti.Interface()).Elem())
@ -250,7 +250,7 @@ func decRegister(e interface{}) (err error) {
pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() {
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
}
l, r, err := UnmarshalInt32(in)
@ -283,7 +283,7 @@ func decRegister(e interface{}) (err error) {
}
}
if len(mfields) == 0 {
return errors.New("ssob: No exported fields for " + string(t.Name()))
return fmt.Errorf("ssob: No exported fields for %s: %w", string(t.Name()), ErrParseFailed)
}
f := func(e interface{}, in []byte) (n int, err error) {
@ -292,7 +292,7 @@ func decRegister(e interface{}) (err error) {
pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() {
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
}
vi := reflect.Indirect(v)
@ -314,7 +314,7 @@ func decRegister(e interface{}) (err error) {
pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() {
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
}
l, r, err := UnmarshalInt32(in)
@ -507,7 +507,7 @@ func decRegister(e interface{}) (err error) {
}
decoderCache[t.Name()] = f
default:
return errors.New("ssob: Unknown type " + string(t.Name()))
return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
}
return nil
@ -540,7 +540,7 @@ func unmarshalBaseType(e interface{}, in []byte) (n int, err error) {
case *string:
return decoderCache["string"](t, in)
default:
return 0, errors.New("ssob: No base type")
return 0, fmt.Errorf("ssob: No base type: %w", ErrTypeUnknown)
}
}
@ -554,7 +554,7 @@ func unmarshal(e interface{}, in []byte) (n int, err error) {
t := reflect.TypeOf(e)
v := reflect.ValueOf(e)
if !v.IsValid() || t.Kind() != reflect.Ptr || v.IsNil() {
return 0, errors.New("ssob: Need a pointer that is fully allocated for unmarshalling")
return 0, fmt.Errorf("ssob: Need a pointer that is fully allocated for unmarshalling: %w", ErrValueInvalid)
}
p := reflect.Indirect(v)

View File

@ -2,7 +2,7 @@ package ssob
import (
"encoding/binary"
"errors"
"fmt"
"io"
"reflect"
"sync"
@ -25,11 +25,11 @@ func (dec *UnsafeDecoder) Decode(e interface{}) (err error) {
func (dec *UnsafeDecoder) DecodeValue(value reflect.Value) (err error) {
if value.Kind() == reflect.Invalid {
return errors.New("ssob: Cannot decode nil value")
return fmt.Errorf("ssob: Cannot decode nil: %w", ErrValueInvalid)
}
if value.Kind() == reflect.Ptr && value.IsNil() {
return errors.New("ssob: Cannot decode nil of type " + value.Type().String())
return fmt.Errorf("ssob: Cannot decode nil of type %s: %w", value.Type().String(), ErrValueInvalid)
}
dec.mutex.Lock()

View File

@ -2,7 +2,7 @@ package ssob
import (
"encoding/binary"
"errors"
"fmt"
"io"
"reflect"
"sync"
@ -25,11 +25,11 @@ func (enc *UnsafeEncoder) Encode(e interface{}) (err error) {
func (enc *UnsafeEncoder) EncodeValue(value reflect.Value) (err error) {
if value.Kind() == reflect.Invalid {
return errors.New("ssob: Cannot encode nil value")
return fmt.Errorf("ssob: Cannot encode nil: %w", ErrValueInvalid)
}
if value.Kind() == reflect.Ptr && value.IsNil() {
return errors.New("ssob: Cannot encode nil of type " + value.Type().String())
return fmt.Errorf("ssob: Cannot encode nil of type %s: %w", value.Type().String(), ErrValueInvalid)
}
bb, err := unsafeMarshal(value.Interface())

View File

@ -1,7 +1,7 @@
package ssob
import (
"errors"
"fmt"
"reflect"
"unsafe"
)
@ -207,81 +207,85 @@ func init() {
if i, ok := e.(bool); ok {
return UnsafeMarshalBool(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected bool")
return nil, fmt.Errorf("ssob: Incompatible type - expected bool: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("int8", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int8); ok {
return UnsafeMarshalInt8(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected int8")
return nil, fmt.Errorf("ssob: Incompatible type - expected int8: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("uint8", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint8); ok {
return UnsafeMarshalUint8(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected uint8")
return nil, fmt.Errorf("ssob: Incompatible type - expected uint8: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("int16", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int16); ok {
return UnsafeMarshalInt16(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected int16")
return nil, fmt.Errorf("ssob: Incompatible type - expected int16: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("uint16", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint16); ok {
return UnsafeMarshalUint16(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected uint16")
return nil, fmt.Errorf("ssob: Incompatible type - expected uint16: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("int32", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int32); ok {
return UnsafeMarshalInt32(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected int32")
return nil, fmt.Errorf("ssob: Incompatible type - expected int32: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("uint32", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint32); ok {
return UnsafeMarshalUint32(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected uint32")
return nil, fmt.Errorf("ssob: Incompatible type - expected uint32: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("float32", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(float32); ok {
return UnsafeMarshalFloat32(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected float32")
return nil, fmt.Errorf("ssob: Incompatible type - expected float32: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("int64", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int64); ok {
return UnsafeMarshalInt64(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected int64")
return nil, fmt.Errorf("ssob: Incompatible type - expected int64: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("uint64", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint64); ok {
return UnsafeMarshalUint64(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected uint64")
return nil, fmt.Errorf("ssob: Incompatible type - expected uint64: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("float64", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(float64); ok {
return UnsafeMarshalFloat64(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected float64")
return nil, fmt.Errorf("ssob: Incompatible type - expected float64: %w", ErrTypeMismatch)
})
RegisterUnsafeEncoder("string", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(string); ok {
return UnsafeMarshalString(i), nil
}
return nil, errors.New("ssob: Incompatible type - expected string")
return nil, fmt.Errorf("ssob: Incompatible type - expected string: %w", ErrTypeMismatch)
})
}
func encRegisterUnsafe(e interface{}) (err error) {
t := reflect.TypeOf(e)
if t == nil {
return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
}
switch t.Kind() {
case reflect.Invalid:
return errors.New("ssob: Invalid type")
return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
case reflect.Array:
f := func(e interface{}) (ret []byte, err error) {
v := reflect.ValueOf(e)
@ -362,7 +366,7 @@ func encRegisterUnsafe(e interface{}) (err error) {
}
}
if len(mfields) == 0 {
return errors.New("ssob: No exported fields for " + string(t.Name()))
return fmt.Errorf("ssob: No exported fields for %s: %w", string(t.Name()), ErrParseFailed)
}
f := func(e interface{}) (ret []byte, err error) {
@ -445,7 +449,7 @@ func encRegisterUnsafe(e interface{}) (err error) {
}
unsafeEncoderCache[t.Name()] = f
default:
return errors.New("ssob: Unknown type " + string(t.Name()))
return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
}
return nil
@ -478,7 +482,7 @@ func unsafeMarshalBaseType(e interface{}) (ret []byte, err error) {
case string:
return unsafeEncoderCache["string"](t)
default:
return nil, errors.New("ssob: No base type")
return nil, fmt.Errorf("ssob: No base type: %w", ErrTypeUnknown)
}
}
@ -494,7 +498,7 @@ func unsafeMarshal(e interface{}) (ret []byte, err error) {
switch t.Kind() {
case reflect.Ptr:
if v.IsNil() {
return nil, errors.New("ssob: Cannot marshal nil pointer")
return nil, fmt.Errorf("ssob: Cannot marshal nil pointer: %w", ErrValueInvalid)
}
p := reflect.Indirect(v)
return unsafeMarshal(p.Interface())

View File

@ -2,26 +2,26 @@ package ssob
import (
"encoding/binary"
"errors"
"fmt"
"reflect"
"unsafe"
)
func UnsafeUnmarshalString(in []byte) (ret string, n int, err error) {
if len(in) < 4 {
return "", 0, errors.New("ssob: Invalid input to decode string")
return "", 0, fmt.Errorf("ssob: Decoding string: %w", ErrTypeInvalid)
}
l := int32(binary.BigEndian.Uint32(in))
if len(in[4:]) < int(l) {
return "", 0, errors.New("ssob: Invalid length of string")
return "", 0, fmt.Errorf("ssob: Invalid length of string: %w", ErrValueInvalid)
}
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")
return false, 0, fmt.Errorf("ssob: Decoding bool: %w", ErrTypeInvalid)
}
if in[0] == byte(0) {
@ -32,7 +32,7 @@ func UnsafeUnmarshalBool(in []byte) (ret bool, n int, err error) {
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")
return 0, 0, fmt.Errorf("ssob: Decoding int8: %w", ErrTypeInvalid)
}
return int8(in[0]), 1, nil
@ -40,7 +40,7 @@ func UnsafeUnmarshalInt8(in []byte) (ret int8, n int, err error) {
func UnsafeUnmarshalUint8(in []byte) (ret uint8, n int, err error) {
if len(in) < 1 {
return 0, 0, errors.New("ssob: Invalid input to decode uint8")
return 0, 0, fmt.Errorf("ssob: Decoding uint8: %w", ErrTypeInvalid)
}
return uint8(in[0]), 1, nil
@ -48,7 +48,7 @@ func UnsafeUnmarshalUint8(in []byte) (ret uint8, n int, err error) {
func UnsafeUnmarshalInt16(in []byte) (ret int16, n int, err error) {
if len(in) < 2 {
return 0, 0, errors.New("ssob: Invalid input to decode int16")
return 0, 0, fmt.Errorf("ssob: Decoding int16: %w", ErrTypeInvalid)
}
var out int16
@ -66,7 +66,7 @@ func UnsafeUnmarshalInt16(in []byte) (ret int16, n int, err error) {
func UnsafeUnmarshalUint16(in []byte) (ret uint16, n int, err error) {
if len(in) < 2 {
return 0, 0, errors.New("ssob: Invalid input to decode uint16")
return 0, 0, fmt.Errorf("ssob: Decoding uint16: %w", ErrTypeInvalid)
}
var out uint16
@ -84,7 +84,7 @@ func UnsafeUnmarshalUint16(in []byte) (ret uint16, n int, err error) {
func UnsafeUnmarshalInt32(in []byte) (ret int32, n int, err error) {
if len(in) < 4 {
return 0, 0, errors.New("ssob: Invalid input to decode int32")
return 0, 0, fmt.Errorf("ssob: Decoding int32: %w", ErrTypeInvalid)
}
var out int32
@ -106,7 +106,7 @@ func UnsafeUnmarshalInt32(in []byte) (ret int32, n int, err error) {
func UnsafeUnmarshalUint32(in []byte) (ret uint32, n int, err error) {
if len(in) < 4 {
return 0, 0, errors.New("ssob: Invalid input to decode uint32")
return 0, 0, fmt.Errorf("ssob: Decoding uint32: %w", ErrTypeInvalid)
}
var out uint32
@ -128,7 +128,7 @@ func UnsafeUnmarshalUint32(in []byte) (ret uint32, n int, err error) {
func UnsafeUnmarshalFloat32(in []byte) (ret float32, n int, err error) {
if len(in) < 4 {
return 0, 0, errors.New("ssob: Invalid input to decode float32")
return 0, 0, fmt.Errorf("ssob: Decoding float32: %w", ErrTypeInvalid)
}
var out float32
@ -150,7 +150,7 @@ func UnsafeUnmarshalFloat32(in []byte) (ret float32, n int, err error) {
func UnsafeUnmarshalInt64(in []byte) (ret int64, n int, err error) {
if len(in) < 8 {
return 0, 0, errors.New("ssob: Invalid input to decode int64")
return 0, 0, fmt.Errorf("ssob: Decoding int64: %w", ErrTypeInvalid)
}
var out int64
@ -180,7 +180,7 @@ func UnsafeUnmarshalInt64(in []byte) (ret int64, n int, err error) {
func UnsafeUnmarshalUint64(in []byte) (ret uint64, n int, err error) {
if len(in) < 8 {
return 0, 0, errors.New("ssob: Invalid input to decode uint64")
return 0, 0, fmt.Errorf("ssob: Decoding uint64: %w", ErrTypeInvalid)
}
var out uint64
@ -210,7 +210,7 @@ func UnsafeUnmarshalUint64(in []byte) (ret uint64, n int, err error) {
func UnsafeUnmarshalFloat64(in []byte) (ret float64, n int, err error) {
if len(in) < 8 {
return 0, 0, errors.New("ssob: Invalid input to decode float64")
return 0, 0, fmt.Errorf("ssob: Decoding float64: %w", ErrTypeInvalid)
}
var out float64
@ -247,92 +247,96 @@ func init() {
*i, n, err = UnsafeUnmarshalBool(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected bool")
return 0, fmt.Errorf("ssob: Incompatible type - expected bool: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int8); ok {
*i, n, err = UnsafeUnmarshalInt8(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected int8")
return 0, fmt.Errorf("ssob: Incompatible type - expected int8: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("uint8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint8); ok {
*i, n, err = UnsafeUnmarshalUint8(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected uint8")
return 0, fmt.Errorf("ssob: Incompatible type - expected uint8: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("int16", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int16); ok {
*i, n, err = UnsafeUnmarshalInt16(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected int16")
return 0, fmt.Errorf("ssob: Incompatible type - expected int16: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("uint16", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint16); ok {
*i, n, err = UnsafeUnmarshalUint16(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected uint16")
return 0, fmt.Errorf("ssob: Incompatible type - expected uint16: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("int32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int32); ok {
*i, n, err = UnsafeUnmarshalInt32(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected int32")
return 0, fmt.Errorf("ssob: Incompatible type - expected int32: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("uint32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint32); ok {
*i, n, err = UnsafeUnmarshalUint32(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected uint32")
return 0, fmt.Errorf("ssob: Incompatible type - expected uint32: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("float32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*float32); ok {
*i, n, err = UnsafeUnmarshalFloat32(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected float32")
return 0, fmt.Errorf("ssob: Incompatible type - expected float32: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("int64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int64); ok {
*i, n, err = UnsafeUnmarshalInt64(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected int64")
return 0, fmt.Errorf("ssob: Incompatible type - expected int64: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("uint64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint64); ok {
*i, n, err = UnsafeUnmarshalUint64(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected uint64")
return 0, fmt.Errorf("ssob: Incompatible type - expected uint64: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("float64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*float64); ok {
*i, n, err = UnsafeUnmarshalFloat64(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected float64")
return 0, fmt.Errorf("ssob: Incompatible type - expected float64: %w", ErrTypeMismatch)
})
RegisterUnsafeDecoder("string", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*string); ok {
*i, n, err = UnsafeUnmarshalString(in)
return n, nil
}
return 0, errors.New("ssob: Incompatible type - expected string")
return 0, fmt.Errorf("ssob: Incompatible type - expected string: %w", ErrTypeMismatch)
})
}
func decRegisterUnsafe(e interface{}) (err error) {
t := reflect.TypeOf(e)
if t == nil {
return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
}
switch t.Kind() {
case reflect.Invalid:
return errors.New("ssob: Invalid type")
return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
case reflect.Array:
f := func(e interface{}, in []byte) (n int, err error) {
t := reflect.TypeOf(e)
@ -340,7 +344,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() {
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
}
l, r, err := UnsafeUnmarshalInt32(in)
@ -351,7 +355,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
ti := v.Elem()
if int(l) != ti.Len() {
return pos, errors.New("ssob: Invalid array length. Expected " + string(l) + " got " + string(ti.Len()))
return pos, fmt.Errorf("ssob: Invalid array length. Expected %s got %s: %w", string(l), string(ti.Len()), ErrValueInvalid)
}
for i := 0; i < int(l); i++ {
e := reflect.New(reflect.TypeOf(ti.Interface()).Elem())
@ -372,7 +376,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() {
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
}
l, r, err := UnsafeUnmarshalInt32(in)
@ -405,7 +409,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
}
}
if len(mfields) == 0 {
return errors.New("ssob: No exported fields for " + string(t.Name()))
return fmt.Errorf("ssob: No exported fields for %s: %w", string(t.Name()), ErrParseFailed)
}
f := func(e interface{}, in []byte) (n int, err error) {
@ -414,7 +418,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() {
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
}
vi := reflect.Indirect(v)
@ -436,7 +440,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() {
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
}
l, r, err := UnsafeUnmarshalInt32(in)
@ -629,7 +633,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
}
unsafeDecoderCache[t.Name()] = f
default:
return errors.New("ssob: Unknown type " + string(t.Name()))
return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
}
return nil
@ -662,7 +666,7 @@ func unsafeUnmarshalBaseType(e interface{}, in []byte) (n int, err error) {
case *string:
return unsafeDecoderCache["string"](t, in)
default:
return 0, errors.New("ssob: No base type")
return 0, fmt.Errorf("ssob: No base type: %w", ErrTypeUnknown)
}
}
@ -676,7 +680,7 @@ func unsafeUnmarshal(e interface{}, in []byte) (n int, err error) {
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")
return 0, fmt.Errorf("ssob: Need a pointer that is fully allocated for unmarshalling: %w", ErrValueInvalid)
}
p := reflect.Indirect(v)