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 package ssob
import ( import (
"errors" "fmt"
"reflect" "reflect"
) )
func allocType(out reflect.Value) (err error) { func allocType(out reflect.Value) (err error) {
if out.Type().Kind() != reflect.Ptr || out.IsNil() { 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() t := out.Elem().Type()

View File

@ -3,6 +3,7 @@ package ssob
import ( import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
"reflect" "reflect"
"sync" "sync"
@ -24,12 +25,23 @@ func (dec *Decoder) Decode(e interface{}) (err error) {
} }
func (dec *Decoder) DecodeValue(value reflect.Value) (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 { 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() { 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() dec.mutex.Lock()

View File

@ -3,6 +3,7 @@ package ssob
import ( import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
"reflect" "reflect"
"sync" "sync"
@ -24,12 +25,20 @@ func (enc *Encoder) Encode(e interface{}) (err error) {
} }
func (enc *Encoder) EncodeValue(value reflect.Value) (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 { 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() { 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()) 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 ( import (
"encoding/binary" "encoding/binary"
"errors" "fmt"
"math" "math"
"reflect" "reflect"
) )
@ -98,85 +98,85 @@ func init() {
if i, ok := e.(bool); ok { if i, ok := e.(bool); ok {
return MarshalBool(i), nil 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) { RegisterEncoder("int8", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int8); ok { if i, ok := e.(int8); ok {
return MarshalInt8(i), nil 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) { RegisterEncoder("uint8", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint8); ok { if i, ok := e.(uint8); ok {
return MarshalUint8(i), nil 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) { RegisterEncoder("int16", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int16); ok { if i, ok := e.(int16); ok {
return MarshalInt16(i), nil 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) { RegisterEncoder("uint16", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint16); ok { if i, ok := e.(uint16); ok {
return MarshalUint16(i), nil 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) { RegisterEncoder("int32", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int32); ok { if i, ok := e.(int32); ok {
return MarshalInt32(i), nil 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) { RegisterEncoder("uint32", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint32); ok { if i, ok := e.(uint32); ok {
return MarshalUint32(i), nil 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) { RegisterEncoder("float32", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(float32); ok { if i, ok := e.(float32); ok {
return MarshalFloat32(i), nil 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) { RegisterEncoder("int64", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(int64); ok { if i, ok := e.(int64); ok {
return MarshalInt64(i), nil 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) { RegisterEncoder("uint64", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(uint64); ok { if i, ok := e.(uint64); ok {
return MarshalUint64(i), nil 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) { RegisterEncoder("float64", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(float64); ok { if i, ok := e.(float64); ok {
return MarshalFloat64(i), nil 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) { RegisterEncoder("string", func(e interface{}) (ret []byte, err error) {
if i, ok := e.(string); ok { if i, ok := e.(string); ok {
return MarshalString(i), nil 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) { func encRegister(e interface{}) (err error) {
t := reflect.TypeOf(e) t := reflect.TypeOf(e)
if t == nil { if t == nil {
return errors.New("ssob: Invalid type") return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
} }
switch t.Kind() { switch t.Kind() {
case reflect.Invalid: case reflect.Invalid:
return errors.New("ssob: Invalid type") return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
case reflect.Array: case reflect.Array:
f := func(e interface{}) (ret []byte, err error) { f := func(e interface{}) (ret []byte, err error) {
v := reflect.ValueOf(e) v := reflect.ValueOf(e)
@ -257,7 +257,7 @@ func encRegister(e interface{}) (err error) {
} }
} }
if len(mfields) == 0 { 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) { f := func(e interface{}) (ret []byte, err error) {
@ -340,7 +340,7 @@ func encRegister(e interface{}) (err error) {
} }
encoderCache[t.Name()] = f encoderCache[t.Name()] = f
default: default:
return errors.New("ssob: Unknown type " + string(t.Name())) return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
} }
return nil return nil
@ -373,7 +373,7 @@ func marshalBaseType(e interface{}) (ret []byte, err error) {
case string: case string:
return encoderCache["string"](t) return encoderCache["string"](t)
default: 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() { switch t.Kind() {
case reflect.Ptr: case reflect.Ptr:
if v.IsNil() { 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) p := reflect.Indirect(v)
return marshal(p.Interface()) return marshal(p.Interface())

View File

@ -2,26 +2,26 @@ package ssob
import ( import (
"encoding/binary" "encoding/binary"
"errors" "fmt"
"math" "math"
"reflect" "reflect"
) )
func UnmarshalString(in []byte) (ret string, n int, err error) { func UnmarshalString(in []byte) (ret string, n int, err error) {
if len(in) < 4 { 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)) l := int32(binary.BigEndian.Uint32(in))
if len(in[4:]) < int(l) { 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 return string(in[4 : l+4]), int(l) + 4, nil
} }
func UnmarshalBool(in []byte) (ret bool, n int, err error) { func UnmarshalBool(in []byte) (ret bool, n int, err error) {
if len(in) < 1 { 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) { 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) { func UnmarshalInt8(in []byte) (ret int8, n int, err error) {
if len(in) < 1 { 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 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) { func UnmarshalUint8(in []byte) (ret uint8, n int, err error) {
if len(in) < 1 { 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 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) { func UnmarshalInt16(in []byte) (ret int16, n int, err error) {
if len(in) < 2 { 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 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) { func UnmarshalUint16(in []byte) (ret uint16, n int, err error) {
if len(in) < 2 { 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 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) { func UnmarshalInt32(in []byte) (ret int32, n int, err error) {
if len(in) < 4 { 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 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) { func UnmarshalUint32(in []byte) (ret uint32, n int, err error) {
if len(in) < 4 { 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 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) { func UnmarshalFloat32(in []byte) (ret float32, n int, err error) {
if len(in) < 4 { 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 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) { func UnmarshalInt64(in []byte) (ret int64, n int, err error) {
if len(in) < 8 { 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 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) { func UnmarshalUint64(in []byte) (ret uint64, n int, err error) {
if len(in) < 8 { 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 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) { func UnmarshalFloat64(in []byte) (ret float64, n int, err error) {
if len(in) < 8 { 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 return float64(math.Float64frombits(binary.BigEndian.Uint64(in[0:8]))), 8, nil
@ -121,96 +121,96 @@ func init() {
*i, n, err = UnmarshalBool(in) *i, n, err = UnmarshalBool(in)
return n, err 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) { RegisterDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int8); ok { if i, ok := e.(*int8); ok {
*i, n, err = UnmarshalInt8(in) *i, n, err = UnmarshalInt8(in)
return n, err 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) { RegisterDecoder("uint8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint8); ok { if i, ok := e.(*uint8); ok {
*i, n, err = UnmarshalUint8(in) *i, n, err = UnmarshalUint8(in)
return n, err 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) { RegisterDecoder("int16", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int16); ok { if i, ok := e.(*int16); ok {
*i, n, err = UnmarshalInt16(in) *i, n, err = UnmarshalInt16(in)
return n, err 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) { RegisterDecoder("uint16", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint16); ok { if i, ok := e.(*uint16); ok {
*i, n, err = UnmarshalUint16(in) *i, n, err = UnmarshalUint16(in)
return n, err 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) { RegisterDecoder("int32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int32); ok { if i, ok := e.(*int32); ok {
*i, n, err = UnmarshalInt32(in) *i, n, err = UnmarshalInt32(in)
return n, err 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) { RegisterDecoder("uint32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint32); ok { if i, ok := e.(*uint32); ok {
*i, n, err = UnmarshalUint32(in) *i, n, err = UnmarshalUint32(in)
return n, err 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) { RegisterDecoder("float32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*float32); ok { if i, ok := e.(*float32); ok {
*i, n, err = UnmarshalFloat32(in) *i, n, err = UnmarshalFloat32(in)
return n, err 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) { RegisterDecoder("int64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int64); ok { if i, ok := e.(*int64); ok {
*i, n, err = UnmarshalInt64(in) *i, n, err = UnmarshalInt64(in)
return n, err 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) { RegisterDecoder("uint64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint64); ok { if i, ok := e.(*uint64); ok {
*i, n, err = UnmarshalUint64(in) *i, n, err = UnmarshalUint64(in)
return n, err 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) { RegisterDecoder("float64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*float64); ok { if i, ok := e.(*float64); ok {
*i, n, err = UnmarshalFloat64(in) *i, n, err = UnmarshalFloat64(in)
return n, err 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) { RegisterDecoder("string", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*string); ok { if i, ok := e.(*string); ok {
*i, n, err = UnmarshalString(in) *i, n, err = UnmarshalString(in)
return n, err 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) { func decRegister(e interface{}) (err error) {
t := reflect.TypeOf(e) t := reflect.TypeOf(e)
if t == nil { if t == nil {
return errors.New("ssob: Invalid type") return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
} }
switch t.Kind() { switch t.Kind() {
case reflect.Invalid: case reflect.Invalid:
return errors.New("ssob: Invalid type") return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
case reflect.Array: case reflect.Array:
f := func(e interface{}, in []byte) (n int, err error) { f := func(e interface{}, in []byte) (n int, err error) {
t := reflect.TypeOf(e) t := reflect.TypeOf(e)
@ -218,7 +218,7 @@ func decRegister(e interface{}) (err error) {
pos := 0 pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() { 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) l, r, err := UnmarshalInt32(in)
@ -229,7 +229,7 @@ func decRegister(e interface{}) (err error) {
ti := v.Elem() ti := v.Elem()
if int(l) != ti.Len() { 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++ { for i := 0; i < int(l); i++ {
e := reflect.New(reflect.TypeOf(ti.Interface()).Elem()) e := reflect.New(reflect.TypeOf(ti.Interface()).Elem())
@ -250,7 +250,7 @@ func decRegister(e interface{}) (err error) {
pos := 0 pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() { 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) l, r, err := UnmarshalInt32(in)
@ -283,7 +283,7 @@ func decRegister(e interface{}) (err error) {
} }
} }
if len(mfields) == 0 { 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) { f := func(e interface{}, in []byte) (n int, err error) {
@ -292,7 +292,7 @@ func decRegister(e interface{}) (err error) {
pos := 0 pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() { 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) vi := reflect.Indirect(v)
@ -314,7 +314,7 @@ func decRegister(e interface{}) (err error) {
pos := 0 pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() { 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) l, r, err := UnmarshalInt32(in)
@ -507,7 +507,7 @@ func decRegister(e interface{}) (err error) {
} }
decoderCache[t.Name()] = f decoderCache[t.Name()] = f
default: default:
return errors.New("ssob: Unknown type " + string(t.Name())) return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
} }
return nil return nil
@ -540,7 +540,7 @@ func unmarshalBaseType(e interface{}, in []byte) (n int, err error) {
case *string: case *string:
return decoderCache["string"](t, in) return decoderCache["string"](t, in)
default: 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) t := reflect.TypeOf(e)
v := reflect.ValueOf(e) v := reflect.ValueOf(e)
if !v.IsValid() || t.Kind() != reflect.Ptr || v.IsNil() { 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) p := reflect.Indirect(v)

View File

@ -2,7 +2,7 @@ package ssob
import ( import (
"encoding/binary" "encoding/binary"
"errors" "fmt"
"io" "io"
"reflect" "reflect"
"sync" "sync"
@ -25,11 +25,11 @@ func (dec *UnsafeDecoder) Decode(e interface{}) (err error) {
func (dec *UnsafeDecoder) DecodeValue(value reflect.Value) (err error) { func (dec *UnsafeDecoder) DecodeValue(value reflect.Value) (err error) {
if value.Kind() == reflect.Invalid { 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() { 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() dec.mutex.Lock()

View File

@ -2,7 +2,7 @@ package ssob
import ( import (
"encoding/binary" "encoding/binary"
"errors" "fmt"
"io" "io"
"reflect" "reflect"
"sync" "sync"
@ -25,11 +25,11 @@ func (enc *UnsafeEncoder) Encode(e interface{}) (err error) {
func (enc *UnsafeEncoder) EncodeValue(value reflect.Value) (err error) { func (enc *UnsafeEncoder) EncodeValue(value reflect.Value) (err error) {
if value.Kind() == reflect.Invalid { 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() { 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()) bb, err := unsafeMarshal(value.Interface())

View File

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

View File

@ -2,26 +2,26 @@ package ssob
import ( import (
"encoding/binary" "encoding/binary"
"errors" "fmt"
"reflect" "reflect"
"unsafe" "unsafe"
) )
func UnsafeUnmarshalString(in []byte) (ret string, n int, err error) { func UnsafeUnmarshalString(in []byte) (ret string, n int, err error) {
if len(in) < 4 { 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)) l := int32(binary.BigEndian.Uint32(in))
if len(in[4:]) < int(l) { 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 return string(in[4 : l+4]), int(l) + 4, nil
} }
func UnsafeUnmarshalBool(in []byte) (ret bool, n int, err error) { func UnsafeUnmarshalBool(in []byte) (ret bool, n int, err error) {
if len(in) < 1 { 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) { 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) { func UnsafeUnmarshalInt8(in []byte) (ret int8, n int, err error) {
if len(in) < 1 { 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 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) { func UnsafeUnmarshalUint8(in []byte) (ret uint8, n int, err error) {
if len(in) < 1 { 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 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) { func UnsafeUnmarshalInt16(in []byte) (ret int16, n int, err error) {
if len(in) < 2 { 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 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) { func UnsafeUnmarshalUint16(in []byte) (ret uint16, n int, err error) {
if len(in) < 2 { 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 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) { func UnsafeUnmarshalInt32(in []byte) (ret int32, n int, err error) {
if len(in) < 4 { 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 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) { func UnsafeUnmarshalUint32(in []byte) (ret uint32, n int, err error) {
if len(in) < 4 { 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 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) { func UnsafeUnmarshalFloat32(in []byte) (ret float32, n int, err error) {
if len(in) < 4 { 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 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) { func UnsafeUnmarshalInt64(in []byte) (ret int64, n int, err error) {
if len(in) < 8 { 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 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) { func UnsafeUnmarshalUint64(in []byte) (ret uint64, n int, err error) {
if len(in) < 8 { 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 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) { func UnsafeUnmarshalFloat64(in []byte) (ret float64, n int, err error) {
if len(in) < 8 { 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 var out float64
@ -247,92 +247,96 @@ func init() {
*i, n, err = UnsafeUnmarshalBool(in) *i, n, err = UnsafeUnmarshalBool(in)
return n, nil 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) { RegisterUnsafeDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int8); ok { if i, ok := e.(*int8); ok {
*i, n, err = UnsafeUnmarshalInt8(in) *i, n, err = UnsafeUnmarshalInt8(in)
return n, nil 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) { RegisterUnsafeDecoder("uint8", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint8); ok { if i, ok := e.(*uint8); ok {
*i, n, err = UnsafeUnmarshalUint8(in) *i, n, err = UnsafeUnmarshalUint8(in)
return n, nil 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) { RegisterUnsafeDecoder("int16", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int16); ok { if i, ok := e.(*int16); ok {
*i, n, err = UnsafeUnmarshalInt16(in) *i, n, err = UnsafeUnmarshalInt16(in)
return n, nil 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) { RegisterUnsafeDecoder("uint16", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint16); ok { if i, ok := e.(*uint16); ok {
*i, n, err = UnsafeUnmarshalUint16(in) *i, n, err = UnsafeUnmarshalUint16(in)
return n, nil 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) { RegisterUnsafeDecoder("int32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int32); ok { if i, ok := e.(*int32); ok {
*i, n, err = UnsafeUnmarshalInt32(in) *i, n, err = UnsafeUnmarshalInt32(in)
return n, nil 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) { RegisterUnsafeDecoder("uint32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint32); ok { if i, ok := e.(*uint32); ok {
*i, n, err = UnsafeUnmarshalUint32(in) *i, n, err = UnsafeUnmarshalUint32(in)
return n, nil 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) { RegisterUnsafeDecoder("float32", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*float32); ok { if i, ok := e.(*float32); ok {
*i, n, err = UnsafeUnmarshalFloat32(in) *i, n, err = UnsafeUnmarshalFloat32(in)
return n, nil 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) { RegisterUnsafeDecoder("int64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*int64); ok { if i, ok := e.(*int64); ok {
*i, n, err = UnsafeUnmarshalInt64(in) *i, n, err = UnsafeUnmarshalInt64(in)
return n, nil 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) { RegisterUnsafeDecoder("uint64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*uint64); ok { if i, ok := e.(*uint64); ok {
*i, n, err = UnsafeUnmarshalUint64(in) *i, n, err = UnsafeUnmarshalUint64(in)
return n, nil 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) { RegisterUnsafeDecoder("float64", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*float64); ok { if i, ok := e.(*float64); ok {
*i, n, err = UnsafeUnmarshalFloat64(in) *i, n, err = UnsafeUnmarshalFloat64(in)
return n, nil 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) { RegisterUnsafeDecoder("string", func(e interface{}, in []byte) (n int, err error) {
if i, ok := e.(*string); ok { if i, ok := e.(*string); ok {
*i, n, err = UnsafeUnmarshalString(in) *i, n, err = UnsafeUnmarshalString(in)
return n, nil 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) { func decRegisterUnsafe(e interface{}) (err error) {
t := reflect.TypeOf(e) t := reflect.TypeOf(e)
if t == nil {
return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
}
switch t.Kind() { switch t.Kind() {
case reflect.Invalid: case reflect.Invalid:
return errors.New("ssob: Invalid type") return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
case reflect.Array: case reflect.Array:
f := func(e interface{}, in []byte) (n int, err error) { f := func(e interface{}, in []byte) (n int, err error) {
t := reflect.TypeOf(e) t := reflect.TypeOf(e)
@ -340,7 +344,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
pos := 0 pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() { 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) l, r, err := UnsafeUnmarshalInt32(in)
@ -351,7 +355,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
ti := v.Elem() ti := v.Elem()
if int(l) != ti.Len() { 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++ { for i := 0; i < int(l); i++ {
e := reflect.New(reflect.TypeOf(ti.Interface()).Elem()) e := reflect.New(reflect.TypeOf(ti.Interface()).Elem())
@ -372,7 +376,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
pos := 0 pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() { 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) l, r, err := UnsafeUnmarshalInt32(in)
@ -405,7 +409,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
} }
} }
if len(mfields) == 0 { 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) { f := func(e interface{}, in []byte) (n int, err error) {
@ -414,7 +418,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
pos := 0 pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() { 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) vi := reflect.Indirect(v)
@ -436,7 +440,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
pos := 0 pos := 0
if t.Kind() != reflect.Ptr || v.IsNil() { 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) l, r, err := UnsafeUnmarshalInt32(in)
@ -629,7 +633,7 @@ func decRegisterUnsafe(e interface{}) (err error) {
} }
unsafeDecoderCache[t.Name()] = f unsafeDecoderCache[t.Name()] = f
default: default:
return errors.New("ssob: Unknown type " + string(t.Name())) return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
} }
return nil return nil
@ -662,7 +666,7 @@ func unsafeUnmarshalBaseType(e interface{}, in []byte) (n int, err error) {
case *string: case *string:
return unsafeDecoderCache["string"](t, in) return unsafeDecoderCache["string"](t, in)
default: 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) t := reflect.TypeOf(e)
v := reflect.ValueOf(e) v := reflect.ValueOf(e)
if t.Kind() != reflect.Ptr || v.IsNil() { 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) p := reflect.Indirect(v)