ssob/decoder.go

61 lines
1.0 KiB
Go

package ssob
import (
"encoding/binary"
"fmt"
"io"
"reflect"
"sync"
)
type Decoder struct {
mutex sync.Mutex
r io.Reader
}
func NewDecoder(r io.Reader) *Decoder {
dec := new(Decoder)
dec.r = r
return dec
}
func (dec *Decoder) Decode(e interface{}) (ret interface{}, err error) {
st := make([]byte, ST_ID_SIZE)
dec.mutex.Lock()
defer dec.mutex.Unlock()
if err = binary.Read(dec.r, binary.BigEndian, st); err != nil {
return nil, err
}
l := binary.BigEndian.Uint32(st)
b := make([]byte, l)
if err = binary.Read(dec.r, binary.BigEndian, b); err != nil {
return nil, fmt.Errorf("ssob: Cannot decode value: %w", err)
}
_, ret, err = unmarshalVal(b)
if err != nil {
return ret, err
}
ret = getVal(ret).Interface()
if e != nil {
var v reflect.Value
if v, err = indirectValue(reflect.ValueOf(e)); err != nil {
return ret, ErrValueInvalid
}
if valueIsNil(v) {
return ret, ErrValueInvalid
}
if v.Type() != reflect.TypeOf(ret) {
return ret, ErrTypeMismatch
}
v.Set(reflect.ValueOf(ret))
}
return ret, err
}