Passed
Push — master ( 7f55c1...cbd69a )
by Nikita
01:47
created

decode/decode.go   D

Size/Duplication

Total Lines 227
Duplicated Lines 0 %

Test Coverage

Coverage 84.11%

Importance

Changes 0
Metric Value
cc 59
eloc 167
dl 0
loc 227
c 0
b 0
f 0
ccs 90
cts 107
cp 0.8411
crap 72.9661
rs 4.08

7 Methods

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