Passed
Push — master ( 0d5f9d...2a2c68 )
by Nikita
01:51
created

decode.decodeUnmarshalerStorage   B

Complexity

Conditions 5

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5.1158

Importance

Changes 0
Metric Value
cc 5
eloc 19
dl 0
loc 29
ccs 15
cts 18
cp 0.8333
crap 5.1158
rs 8.9833
c 0
b 0
f 0
nop 3
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
func decodeItem(rt reflect.Type, btype binn.Type, bval []byte) (interface{}, error) {
80 1
	var v interface{}
81 1
	var err error
82
83 1
	switch btype {
84
	case binn.Null:
85
		return nil, nil
86
	case binn.True:
87 1
		return true, nil
88
	case binn.False:
89 1
		return false, nil
90
	case binn.Uint8Type:
91 1
		v = Uint8(bval)
92
	case binn.Uint16Type:
93 1
		v = Uint16(bval)
94
	case binn.Uint32Type:
95 1
		v = Uint32(bval)
96
	case binn.Uint64Type:
97 1
		v = Uint64(bval)
98
	case binn.Int8Type:
99 1
		v = Int8(bval)
100
	case binn.Int16Type:
101 1
		v = Int16(bval)
102
	case binn.Int32Type:
103 1
		v = Int32(bval)
104
	case binn.Int64Type:
105 1
		v = Int64(bval)
106
	case binn.Float32Type:
107 1
		v = Float32(bval)
108
	case binn.Float64Type:
109 1
		v = Float64(bval)
110
	case binn.StringType:
111 1
		v = String(bval[:len(bval)-1])
112
	case binn.BlobType:
113 1
		v = bval
114
	case binn.ListType:
115 1
		var l []interface{}
116 1
		br := bytes.NewReader(bval)
117 1
		_, wasReadLen, _ := readSize(br)
118 1
		cnt, wasReadCnt, _ := readSize(br)
119 1
		wasRead := wasReadLen + wasReadCnt
120
121 1
		err = decodeListItems(br, &l, len(bval)-int(wasRead), wasRead, cnt)
122 1
		if err != nil {
123
			return nil, err
124
		}
125
126 1
		return l, nil
127
	case binn.MapType:
128 1
		br := bytes.NewReader(bval)
129 1
		sz, rlsize, _ := readSize(br)
130 1
		cnt, rlcnt, _ := readSize(br)
131
132 1
		mapType := reflect.MapOf(reflect.TypeOf(int(0)), rt.Elem())
133 1
		ptr := reflect.New(mapType)
134 1
		ptr.Elem().Set(reflect.MakeMap(mapType))
135 1
		m := ptr.Interface()
136
137 1
		err = decodeMapItems(br, m, sz, rlsize+rlcnt, cnt)
138 1
		if err != nil {
139
			return nil, err
140
		}
141
142 1
		return reflect.ValueOf(m).Elem().Interface(), nil
143
	case binn.ObjectType:
144 1
		var obj interface{}
145 1
		if rt.Kind() == reflect.Interface {
146
			obj = map[string]interface{}{}
147
		} else {
148 1
			ptr := reflect.New(rt)
149 1
			obj = ptr.Interface()
150
		}
151
152 1
		br := bytes.NewReader(bval)
153
154 1
		err = decodeStorage(btype, br, &obj)
155
156 1
		if err != nil {
157
			return nil, err
158
		}
159
160 1
		return obj, nil
161
	}
162
163 1
	if rt.Kind() == reflect.Interface {
164 1
		v, err = convertToKind(kindMapper[btype], v)
165 1
		if err != nil {
166
			return nil, err
167
		}
168
	} else {
169 1
		v, err = convertToType(rt, v)
170 1
		if err != nil {
171
			return nil, err
172
		}
173
	}
174
175 1
	return v, nil
176
}
177
178
func loadDecodeFunc(bt binn.Type) decodeFunc {
179 1
	if fi, ok := decoderCache.Load(bt); ok {
180 1
		return fi.(decodeFunc)
181
	}
182
183 1
	var (
184
		wg sync.WaitGroup
185
		f  decodeFunc
186
	)
187 1
	wg.Add(1)
188 1
	fi, loaded := decoderCache.LoadOrStore(bt, decodeFunc(func(reader io.Reader, v interface{}) error {
189
		wg.Wait()
190
		return f(reader, v)
191
	}))
192 1
	if loaded {
193
		return fi.(decodeFunc)
194
	}
195
196 1
	f = newTypeDecoder(bt)
197 1
	wg.Done()
198 1
	decoderCache.Store(bt, f)
199 1
	return f
200
}
201
202
func newTypeDecoder(bt binn.Type) decodeFunc {
203 1
	switch bt {
204
	case binn.ListType:
205 1
		return decodeList
206
	case binn.MapType:
207 1
		return decodeMap
208
	case binn.ObjectType:
209 1
		return decodeObject
210
	case binn.Null:
211 1
		return func(_ io.Reader, _ interface{}) error {
212 1
			return nil
213
		}
214
	}
215
216 1
	decoder := newValueDecoder(bt)
217 1
	return decoder.DecodeValue
218
}
219
220
func convertToType(rt reflect.Type, val interface{}) (interface{}, error) {
221 1
	switch rt.Kind() {
222
	case reflect.Interface:
223
		return val, nil
224
	case reflect.Ptr:
225
		return convertToType(rt.Elem(), val)
226
	default:
227 1
		return convertToKind(rt.Kind(), val)
228
	}
229
}
230
231
func convertToKind(rk reflect.Kind, v interface{}) (interface{}, error) {
232 1
	switch rk {
233
	case reflect.Int:
234 1
		return conv.Int(v)
235
	case reflect.Int8:
236 1
		return conv.Int8(v)
237
	case reflect.Int16:
238 1
		return conv.Int16(v)
239
	case reflect.Int32:
240 1
		return conv.Int32(v)
241
	case reflect.Int64:
242 1
		return conv.Int64(v)
243
	case reflect.Uint:
244
		return conv.Uint(v)
245
	case reflect.Uint8:
246 1
		return conv.Uint8(v)
247
	case reflect.Uint16:
248 1
		return conv.Uint16(v)
249
	case reflect.Uint32:
250 1
		return conv.Int32(v)
251
	case reflect.Uint64:
252
		return conv.Uint64(v)
253
	case reflect.Bool:
254
		return conv.Bool(v)
255
	case reflect.String:
256 1
		return conv.String(v)
257
	}
258
259 1
	return v, nil
260
}
261