summaryrefslogtreecommitdiff
path: root/vendor/github.com/bytedance/sonic/internal/decoder/optdec/structs.go
blob: bce2758f1e4575dd3bf16d612cfb60cb47a797e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package optdec

import (
	"reflect"
	"unsafe"

	caching "github.com/bytedance/sonic/internal/optcaching"
	"github.com/bytedance/sonic/internal/resolver"
)

type fieldEntry struct {
	resolver.FieldMeta
	fieldDec decFunc
}

type structDecoder struct {
	fieldMap   caching.FieldLookup
	fields     []fieldEntry
	structName string
	typ        reflect.Type
}

func (d *structDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
	if node.IsNull() {
		return nil
	}

	var gerr error
	obj, ok := node.AsObj()
	if !ok {
		return error_mismatch(node, ctx, d.typ)
	}

	next := obj.Children()
	for i := 0; i < obj.Len(); i++ {
		key, _ := NewNode(next).AsStrRef(ctx)
		val := NewNode(PtrOffset(next, 1))
		next = val.Next()

		// find field idx
		idx := d.fieldMap.Get(key)
        if idx == -1 {
            if Options(ctx.Options())&OptionDisableUnknown != 0 {
                return error_field(key)
            }
            continue
        }

		offset := d.fields[idx].Path[0].Size
		elem := unsafe.Pointer(uintptr(vp) + offset)
		err := d.fields[idx].fieldDec.FromDom(elem, val, ctx)

		// deal with mismatch type errors
		if gerr == nil && err != nil {
			// TODO: better error info
			gerr = err
		}
	}
	return gerr
}