Passed
Push — master ( c32edb...17f9f7 )
by Nikita
02:16
created

decode/decode.go   D

Size/Duplication

Total Lines 228
Duplicated Lines 0 %

Test Coverage

Coverage 84.26%

Importance

Changes 0
Metric Value
cc 59
eloc 168
dl 0
loc 228
ccs 91
cts 108
cp 0.8426
crap 72.5742
rs 4.08
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A decode.decodeStorage 0 3 1
A decode.loadDecodeFunc 0 22 4
F decode.decodeItem 0 97 26
A decode.decode 0 18 5
A decode.convertToType 0 8 4
B decode.newTypeDecoder 0 16 6
D decode.convertToKind 0 29 13
1
package decode
2
3
import (
4
	"bytes"
5
	"io"
6
	"reflect"
7
	"sync"
8
9
	"github.com/cstockton/go-conv"
10
	"github.com/et-nik/binngo/binn"
11
)
12
13
const (
14
	maxOneByteSize = 127
15
)
16
17
type decodeFunc func(reader io.Reader, v interface{}) error
18
19
var decoderCache sync.Map // map[binn.Type]decodeFunc
20
21
type readLen int
22
23
func decode(reader io.Reader, v interface{}) error {
24 1
	rv := reflect.ValueOf(v)
25 1
	rt := reflect.TypeOf(v)
26 1
	if rv.Kind() != reflect.Ptr || rv.IsNil() {
27
		return &InvalidUnmarshalError{rt}
28
	}
29
30 1
	containerType, _, err := readType(reader)
31 1
	if err != nil {
32
		return err
33
	}
34
35 1
	err = decodeStorage(containerType, reader, v)
36 1
	if err != nil {
37 1
		return err
38
	}
39
40 1
	return nil
41
}
42
43
func decodeStorage(containerType binn.Type, reader io.Reader, v interface{}) error {
44 1
	decoder := loadDecodeFunc(containerType)
45 1
	return decoder(reader, v)
46
}
47
48
func decodeItem(rt reflect.Type, btype binn.Type, bval []byte) (interface{}, error) {
49 1
	var v interface{}
50 1
	var err error
51
52 1
	switch btype {
53
	case binn.Null:
54
		return nil, nil
55
	case binn.True:
56 1
		return true, nil
57
	case binn.False:
58 1
		return false, nil
59
	case binn.Uint8Type:
60 1
		v = Uint8(bval)
61
	case binn.Uint16Type:
62 1
		v = Uint16(bval)
63
	case binn.Uint32Type:
64 1
		v = Uint32(bval)
65
	case binn.Uint64Type:
66 1
		v = Uint64(bval)
67
	case binn.Int8Type:
68 1
		v = Int8(bval)
69
	case binn.Int16Type:
70 1
		v = Int16(bval)
71
	case binn.Int32Type:
72 1
		v = Int32(bval)
73
	case binn.Int64Type:
74 1
		v = Int64(bval)
75
	case binn.Float32Type:
76 1
		v = Float32(bval)
77
	case binn.Float64Type:
78 1
		v = Float64(bval)
79
	case binn.StringType:
80 1
		v = String(bval[:len(bval)-1])
81
	case binn.BlobType:
82 1
		v = bval
83
	case binn.ListType:
84 1
		var l []interface{}
85 1
		br := bytes.NewReader(bval)
86 1
		_, wasReadLen, _ := readSize(br)
87 1
		cnt, wasReadCnt, _ := readSize(br)
88 1
		wasRead := wasReadLen + wasReadCnt
89
90 1
		err = decodeListItems(br, &l, len(bval)-int(wasRead), wasRead, cnt)
91 1
		if err != nil {
92
			return nil, err
93
		}
94
95 1
		return l, nil
96
	case binn.MapType:
97 1
		br := bytes.NewReader(bval)
98 1
		sz, rlsize, _ := readSize(br)
99 1
		cnt, rlcnt, _ := readSize(br)
100
101 1
		mapType := reflect.MapOf(reflect.TypeOf(int(0)), rt.Elem())
102 1
		ptr := reflect.New(mapType)
103 1
		ptr.Elem().Set(reflect.MakeMap(mapType))
104 1
		m := ptr.Interface()
105
106 1
		err = decodeMapItems(br, m, sz, rlsize+rlcnt, cnt)
107 1
		if err != nil {
108
			return nil, err
109
		}
110
111 1
		return reflect.ValueOf(m).Elem().Interface(), nil
112
	case binn.ObjectType:
113 1
		var obj interface{}
114 1
		if rt.Kind() == reflect.Interface {
115
			obj = map[string]interface{}{}
116
		} else {
117 1
			ptr := reflect.New(rt)
118 1
			obj = ptr.Interface()
119
		}
120
121 1
		br := bytes.NewReader(bval)
122
123 1
		err = decodeStorage(btype, br, &obj)
124
125 1
		if err != nil {
126
			return nil, err
127
		}
128
129 1
		return obj, nil
130
	}
131
132 1
	if rt.Kind() == reflect.Interface {
133 1
		v, err = convertToKind(kindMapper[btype], v)
134 1
		if err != nil {
135
			return nil, err
136
		}
137
	} else {
138 1
		v, err = convertToType(rt, v)
139 1
		if err != nil {
140
			return nil, err
141
		}
142
	}
143
144 1
	return v, nil
145
}
146
147
func loadDecodeFunc(bt binn.Type) decodeFunc {
148 1
	if fi, ok := decoderCache.Load(bt); ok {
149 1
		return fi.(decodeFunc)
150
	}
151
152 1
	var (
153
		wg sync.WaitGroup
154
		f  decodeFunc
155
	)
156 1
	wg.Add(1)
157 1
	fi, loaded := decoderCache.LoadOrStore(bt, decodeFunc(func(reader io.Reader, v interface{}) error {
158
		wg.Wait()
159
		return f(reader, v)
160
	}))
161 1
	if loaded {
162
		return fi.(decodeFunc)
163
	}
164
165 1
	f = newTypeDecoder(bt)
166 1
	wg.Done()
167 1
	decoderCache.Store(bt, f)
168 1
	return f
169
}
170
171
func newTypeDecoder(bt binn.Type) decodeFunc {
172 1
	switch bt {
173
	case binn.ListType:
174 1
		return decodeList
175
	case binn.MapType:
176 1
		return decodeMap
177
	case binn.ObjectType:
178 1
		return decodeObject
179
	case binn.Null:
180 1
		return func(_ io.Reader, _ interface{}) error {
181 1
			return nil
182
		}
183
	}
184
185 1
	decoder := newValueDecoder(bt)
186 1
	return decoder.DecodeValue
187
}
188
189
func convertToType(rt reflect.Type, val interface{}) (interface{}, error) {
190 1
	switch rt.Kind() {
191
	case reflect.Interface:
192
		return val, nil
193
	case reflect.Ptr:
194
		return convertToType(rt.Elem(), val)
195
	default:
196 1
		return convertToKind(rt.Kind(), val)
197
	}
198
}
199
200
func convertToKind(rk reflect.Kind, v interface{}) (interface{}, error) {
201 1
	switch rk {
202
	case reflect.Int:
203 1
		return conv.Int(v)
204
	case reflect.Int8:
205 1
		return conv.Int8(v)
206
	case reflect.Int16:
207 1
		return conv.Int16(v)
208
	case reflect.Int32:
209 1
		return conv.Int32(v)
210
	case reflect.Int64:
211 1
		return conv.Int64(v)
212
	case reflect.Uint:
213
		return conv.Uint(v)
214
	case reflect.Uint8:
215 1
		return conv.Uint8(v)
216
	case reflect.Uint16:
217 1
		return conv.Uint16(v)
218
	case reflect.Uint32:
219 1
		return conv.Int32(v)
220
	case reflect.Uint64:
221
		return conv.Uint64(v)
222
	case reflect.Bool:
223
		return conv.Bool(v)
224
	case reflect.String:
225 1
		return conv.String(v)
226
	}
227
228 1
	return v, nil
229
}
230