Test Failed
Push — master ( 17f9f7...fd8660 )
by Nikita
01:46
created

decode.decode   C

Complexity

Conditions 9

Size

Total Lines 33
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 9.4453

Importance

Changes 0
Metric Value
cc 9
eloc 21
dl 0
loc 33
ccs 14
cts 17
cp 0.8235
crap 9.4453
rs 6.6666
c 0
b 0
f 0
nop 2
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
	if rt.Implements(unmarshalerType) && isStorageContainer(containerType) {
36 1
		size, _, err := readSize(reader)
37 1
		if err != nil {
38
			return err
39
		}
40 1
		buf := make([]byte, size)
41
42
		err = decodeUnmarshaler(buf, v)
43
		if err != nil {
44 1
			return err
45 1
		}
46
47
		return nil
48
	}
49 1
50 1
	err = decodeStorage(containerType, reader, v)
51
	if err != nil {
52 1
		return err
53
	}
54
55
	return nil
56 1
}
57
58 1
func decodeStorage(containerType binn.Type, reader io.Reader, v interface{}) error {
59
	decoder := loadDecodeFunc(containerType)
60 1
	return decoder(reader, v)
61
}
62 1
63
func decodeItem(rt reflect.Type, btype binn.Type, bval []byte) (interface{}, error) {
64 1
	var v interface{}
65
	var err error
66 1
67
	switch btype {
68 1
	case binn.Null:
69
		return nil, nil
70 1
	case binn.True:
71
		return true, nil
72 1
	case binn.False:
73
		return false, nil
74 1
	case binn.Uint8Type:
75
		v = Uint8(bval)
76 1
	case binn.Uint16Type:
77
		v = Uint16(bval)
78 1
	case binn.Uint32Type:
79
		v = Uint32(bval)
80 1
	case binn.Uint64Type:
81
		v = Uint64(bval)
82 1
	case binn.Int8Type:
83
		v = Int8(bval)
84 1
	case binn.Int16Type:
85 1
		v = Int16(bval)
86 1
	case binn.Int32Type:
87 1
		v = Int32(bval)
88 1
	case binn.Int64Type:
89
		v = Int64(bval)
90 1
	case binn.Float32Type:
91 1
		v = Float32(bval)
92
	case binn.Float64Type:
93
		v = Float64(bval)
94
	case binn.StringType:
95 1
		v = String(bval[:len(bval)-1])
96
	case binn.BlobType:
97 1
		v = bval
98 1
	case binn.ListType:
99 1
		var l []interface{}
100
		br := bytes.NewReader(bval)
101 1
		_, wasReadLen, _ := readSize(br)
102 1
		cnt, wasReadCnt, _ := readSize(br)
103 1
		wasRead := wasReadLen + wasReadCnt
104 1
105
		err = decodeListItems(br, &l, len(bval)-int(wasRead), wasRead, cnt)
106 1
		if err != nil {
107 1
			return nil, err
108
		}
109
110
		return l, nil
111 1
	case binn.MapType:
112
		br := bytes.NewReader(bval)
113 1
		sz, rlsize, _ := readSize(br)
114 1
		cnt, rlcnt, _ := readSize(br)
115
116
		mapType := reflect.MapOf(reflect.TypeOf(int(0)), rt.Elem())
117 1
		ptr := reflect.New(mapType)
118 1
		ptr.Elem().Set(reflect.MakeMap(mapType))
119
		m := ptr.Interface()
120
121 1
		err = decodeMapItems(br, m, sz, rlsize+rlcnt, cnt)
122
		if err != nil {
123 1
			return nil, err
124
		}
125 1
126
		return reflect.ValueOf(m).Elem().Interface(), nil
127
	case binn.ObjectType:
128
		var obj interface{}
129 1
		if rt.Kind() == reflect.Interface {
130
			obj = map[string]interface{}{}
131
		} else {
132 1
			ptr := reflect.New(rt)
133 1
			obj = ptr.Interface()
134 1
		}
135
136
		br := bytes.NewReader(bval)
137
138 1
		err = decodeStorage(btype, br, &obj)
139 1
140
		if err != nil {
141
			return nil, err
142
		}
143
144 1
		return obj, nil
145
	}
146
147
	if rt.Kind() == reflect.Interface {
148 1
		v, err = convertToKind(kindMapper[btype], v)
149 1
		if err != nil {
150
			return nil, err
151
		}
152 1
	} else {
153
		v, err = convertToType(rt, v)
154
		if err != nil {
155
			return nil, err
156 1
		}
157 1
	}
158
159
	return v, nil
160
}
161 1
162
func loadDecodeFunc(bt binn.Type) decodeFunc {
163
	if fi, ok := decoderCache.Load(bt); ok {
164
		return fi.(decodeFunc)
165 1
	}
166 1
167 1
	var (
168 1
		wg sync.WaitGroup
169
		f  decodeFunc
170
	)
171
	wg.Add(1)
172 1
	fi, loaded := decoderCache.LoadOrStore(bt, decodeFunc(func(reader io.Reader, v interface{}) error {
173
		wg.Wait()
174 1
		return f(reader, v)
175
	}))
176 1
	if loaded {
177
		return fi.(decodeFunc)
178 1
	}
179
180 1
	f = newTypeDecoder(bt)
181 1
	wg.Done()
182
	decoderCache.Store(bt, f)
183
	return f
184
}
185 1
186 1
func newTypeDecoder(bt binn.Type) decodeFunc {
187
	switch bt {
188
	case binn.ListType:
189
		return decodeList
190 1
	case binn.MapType:
191
		return decodeMap
192
	case binn.ObjectType:
193
		return decodeObject
194
	case binn.Null:
195
		return func(_ io.Reader, _ interface{}) error {
196 1
			return nil
197
		}
198
	}
199
200
	decoder := newValueDecoder(bt)
201 1
	return decoder.DecodeValue
202
}
203 1
204
func convertToType(rt reflect.Type, val interface{}) (interface{}, error) {
205 1
	switch rt.Kind() {
206
	case reflect.Interface:
207 1
		return val, nil
208
	case reflect.Ptr:
209 1
		return convertToType(rt.Elem(), val)
210
	default:
211 1
		return convertToKind(rt.Kind(), val)
212
	}
213
}
214
215 1
func convertToKind(rk reflect.Kind, v interface{}) (interface{}, error) {
216
	switch rk {
217 1
	case reflect.Int:
218
		return conv.Int(v)
219 1
	case reflect.Int8:
220
		return conv.Int8(v)
221
	case reflect.Int16:
222
		return conv.Int16(v)
223
	case reflect.Int32:
224
		return conv.Int32(v)
225 1
	case reflect.Int64:
226
		return conv.Int64(v)
227
	case reflect.Uint:
228 1
		return conv.Uint(v)
229
	case reflect.Uint8:
230
		return conv.Uint8(v)
231
	case reflect.Uint16:
232
		return conv.Uint16(v)
233
	case reflect.Uint32:
234
		return conv.Int32(v)
235
	case reflect.Uint64:
236
		return conv.Uint64(v)
237
	case reflect.Bool:
238
		return conv.Bool(v)
239
	case reflect.String:
240
		return conv.String(v)
241
	}
242
243
	return v, nil
244
}
245