decode/decode.go   F
last analyzed

Size/Duplication

Total Lines 260
Duplicated Lines 0 %

Test Coverage

Coverage 84%

Importance

Changes 0
Metric Value
cc 65
eloc 187
dl 0
loc 260
ccs 105
cts 125
cp 0.84
crap 82.3056
rs 3.2
c 0
b 0
f 0

8 Methods

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