Files
QSfera/vendor/github.com/shamaton/msgpack/v2/internal/decoding/decoding.go
T
dependabot[bot]andRalf Haferkamp b3e5d80306 chore(deps): bump github.com/shamaton/msgpack/v2 from 2.2.0 to 2.2.2
Bumps [github.com/shamaton/msgpack/v2](https://github.com/shamaton/msgpack) from 2.2.0 to 2.2.2.
- [Release notes](https://github.com/shamaton/msgpack/releases)
- [Commits](https://github.com/shamaton/msgpack/compare/v2.2.0...v2.2.2)

---
updated-dependencies:
- dependency-name: github.com/shamaton/msgpack/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-23 12:57:52 +02:00

344 lines
6.7 KiB
Go

package decoding
import (
"fmt"
"reflect"
"github.com/shamaton/msgpack/v2/def"
"github.com/shamaton/msgpack/v2/internal/common"
)
type decoder struct {
data []byte
asArray bool
common.Common
}
// Decode analyzes the MessagePack-encoded data and stores
// the result into the pointer of v.
func Decode(data []byte, v interface{}, asArray bool) error {
d := decoder{data: data, asArray: asArray}
if d.data == nil || len(d.data) < 1 {
return def.ErrNoData
}
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
return fmt.Errorf("%w. v.(type): %T", def.ErrReceiverNotPointer, v)
}
rv = rv.Elem()
last, err := d.decode(rv, 0)
if err != nil {
return err
}
if len(data) != last {
return fmt.Errorf("%w size=%d, last=%d", def.ErrHasLeftOver, len(data), last)
}
return err
}
func (d *decoder) decode(rv reflect.Value, offset int) (int, error) {
k := rv.Kind()
switch k {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v, o, err := d.asInt(offset, k)
if err != nil {
return 0, err
}
rv.SetInt(v)
offset = o
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v, o, err := d.asUint(offset, k)
if err != nil {
return 0, err
}
rv.SetUint(v)
offset = o
case reflect.Float32:
v, o, err := d.asFloat32(offset, k)
if err != nil {
return 0, err
}
rv.SetFloat(float64(v))
offset = o
case reflect.Float64:
v, o, err := d.asFloat64(offset, k)
if err != nil {
return 0, err
}
rv.SetFloat(v)
offset = o
case reflect.String:
// byte slice
if d.isCodeBin(d.data[offset]) {
v, offset, err := d.asBinString(offset, k)
if err != nil {
return 0, err
}
rv.SetString(v)
return offset, nil
}
v, o, err := d.asString(offset, k)
if err != nil {
return 0, err
}
rv.SetString(v)
offset = o
case reflect.Bool:
v, o, err := d.asBool(offset, k)
if err != nil {
return 0, err
}
rv.SetBool(v)
offset = o
case reflect.Slice:
// nil
if d.isCodeNil(d.data[offset]) {
offset++
return offset, nil
}
// byte slice
if d.isCodeBin(d.data[offset]) {
bs, offset, err := d.asBin(offset, k)
if err != nil {
return 0, err
}
rv.SetBytes(bs)
return offset, nil
}
// string to bytes
if d.isCodeString(d.data[offset]) {
l, offset, err := d.stringByteLength(offset, k)
if err != nil {
return 0, err
}
bs, offset, err := d.asStringByteByLength(offset, l, k)
if err != nil {
return 0, err
}
rv.SetBytes(bs)
return offset, nil
}
// get slice length
l, o, err := d.sliceLength(offset, k)
if err != nil {
return 0, err
}
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
return 0, err
}
// check fixed type
fixedOffset, found, err := d.asFixedSlice(rv, o, l)
if err != nil {
return 0, err
}
if found {
return fixedOffset, nil
}
// create slice dynamically
tmpSlice := reflect.MakeSlice(rv.Type(), l, l)
for i := 0; i < l; i++ {
v := tmpSlice.Index(i)
if v.Kind() == reflect.Struct {
o, err = d.setStruct(v, o, k)
} else {
o, err = d.decode(v, o)
}
if err != nil {
return 0, err
}
}
rv.Set(tmpSlice)
offset = o
case reflect.Complex64:
v, o, err := d.asComplex64(offset, k)
if err != nil {
return 0, err
}
rv.SetComplex(complex128(v))
offset = o
case reflect.Complex128:
v, o, err := d.asComplex128(offset, k)
if err != nil {
return 0, err
}
rv.SetComplex(v)
offset = o
case reflect.Array:
// nil
if d.isCodeNil(d.data[offset]) {
offset++
return offset, nil
}
// byte slice
if d.isCodeBin(d.data[offset]) {
bs, offset, err := d.asBin(offset, k)
if err != nil {
return 0, err
}
if len(bs) > rv.Len() {
return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), len(bs), def.ErrNotMatchArrayElement)
}
for i, b := range bs {
rv.Index(i).SetUint(uint64(b))
}
return offset, nil
}
// string to bytes
if d.isCodeString(d.data[offset]) {
l, offset, err := d.stringByteLength(offset, k)
if err != nil {
return 0, err
}
if l > rv.Len() {
return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), l, def.ErrNotMatchArrayElement)
}
bs, offset, err := d.asStringByteByLength(offset, l, k)
if err != nil {
return 0, err
}
for i, b := range bs {
rv.Index(i).SetUint(uint64(b))
}
return offset, nil
}
// get slice length
l, o, err := d.sliceLength(offset, k)
if err != nil {
return 0, err
}
if l > rv.Len() {
return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), l, def.ErrNotMatchArrayElement)
}
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
return 0, err
}
// create array dynamically
for i := 0; i < l; i++ {
o, err = d.decode(rv.Index(i), o)
if err != nil {
return 0, err
}
}
offset = o
case reflect.Map:
// nil
if d.isCodeNil(d.data[offset]) {
offset++
return offset, nil
}
// get map length
l, o, err := d.mapLength(offset, k)
if err != nil {
return 0, err
}
if err = d.hasRequiredLeastMapSize(o, l); err != nil {
return 0, err
}
// check fixed type
fixedOffset, found, err := d.asFixedMap(rv, o, l)
if err != nil {
return 0, err
}
if found {
return fixedOffset, nil
}
// create dynamically
key := rv.Type().Key()
value := rv.Type().Elem()
if rv.IsNil() {
rv.Set(reflect.MakeMapWithSize(rv.Type(), l))
}
for i := 0; i < l; i++ {
k := reflect.New(key).Elem()
v := reflect.New(value).Elem()
o, err = d.decode(k, o)
if err != nil {
return 0, err
}
o, err = d.decode(v, o)
if err != nil {
return 0, err
}
rv.SetMapIndex(k, v)
}
offset = o
case reflect.Struct:
o, err := d.setStruct(rv, offset, k)
if err != nil {
return 0, err
}
offset = o
case reflect.Ptr:
// nil
if d.isCodeNil(d.data[offset]) {
offset++
return offset, nil
}
if rv.Elem().Kind() == reflect.Invalid {
n := reflect.New(rv.Type().Elem())
rv.Set(n)
}
o, err := d.decode(rv.Elem(), offset)
if err != nil {
return 0, err
}
offset = o
case reflect.Interface:
if rv.Elem().Kind() == reflect.Ptr {
o, err := d.decode(rv.Elem(), offset)
if err != nil {
return 0, err
}
offset = o
} else {
v, o, err := d.asInterface(offset, k)
if err != nil {
return 0, err
}
if v != nil {
rv.Set(reflect.ValueOf(v))
}
offset = o
}
default:
return 0, fmt.Errorf("%v is %w type", rv.Kind(), def.ErrUnsupportedType)
}
return offset, nil
}
func (d *decoder) errorTemplate(code byte, k reflect.Kind) error {
return fmt.Errorf("%w %x decoding as %v", def.ErrCanNotDecode, code, k)
}