encode.newMapEncoder   B
last analyzed

Complexity

Conditions 6

Size

Total Lines 23
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 10.5

Importance

Changes 0
Metric Value
cc 6
eloc 19
dl 0
loc 23
ccs 5
cts 10
cp 0.5
crap 10.5
rs 8.5166
c 0
b 0
f 0
nop 1
1
package encode
2
3
import (
4
	"encoding"
5
	"reflect"
6
7
	"github.com/et-nik/binngo/binn"
8
)
9
10
func newMapEncoder(t reflect.Type) encoderFunc {
11 1
	switch t.Key().Kind() {
12
	case reflect.String:
13 1
		me := mapObjectEncoder{
14
			newTypeEncoder(t.Elem()),
15
			t,
16
		}
17 1
		return me.encode
18
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
19
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
20 1
		me := mapEncoder{newTypeEncoder(t.Elem())}
21 1
		return me.encode
22
	default:
23
		if t.Key().Implements(textMarshalerType) {
24
			me := mapObjectEncoder{
25
				newTypeEncoder(t.Elem()),
26
				t,
27
			}
28
			return me.encode
29
		}
30
31
		return func(v reflect.Value) ([]byte, error) {
32
			return nil, &UnsupportedTypeError{t}
33
		}
34
	}
35
}
36
37
type mapObjectEncoder struct {
38
	elemEnc  encoderFunc
39
	itemType reflect.Type
40
}
41
42
func (me *mapObjectEncoder) encode(v reflect.Value) ([]byte, error) {
43 1
	dataBytes := []byte{}
44
45 1
	keys := v.MapKeys()
46
47 1
	for _, key := range keys {
48 1
		bval, err := encodeTextKey(key)
49 1
		if err != nil {
50
			return nil, err
51
		}
52 1
		dataBytes = append(dataBytes, bval...)
53
54 1
		encodedValue, err := me.elemEnc(v.MapIndex(key))
55 1
		if err != nil {
56
			return nil, err
57
		}
58
59 1
		dataBytes = append(dataBytes, encodedValue...)
60
	}
61
62 1
	bytes := []byte{}
63
64 1
	typeBytes := Uint8(binn.ObjectType)
65 1
	countBytes := Size(len(keys), false)
66
67 1
	bytes = append(bytes, typeBytes...)
68 1
	bytes = append(bytes, Size(len(typeBytes)+len(dataBytes)+len(countBytes), true)...)
69 1
	bytes = append(bytes, countBytes...)
70 1
	bytes = append(bytes, dataBytes...)
71
72 1
	return bytes, nil
73
}
74
75
type mapEncoder struct {
76
	elemEnc encoderFunc
77
}
78
79
func (me *mapEncoder) encode(v reflect.Value) ([]byte, error) {
80 1
	var dataBytes []byte
81
82 1
	iter := v.MapRange()
83
84 1
	for iter.Next() {
85 1
		key := iter.Key()
86 1
		val := iter.Value()
87
88 1
		dataBytes = append(dataBytes, Int32(int32(key.Int()))...)
89
90 1
		encodedValue, err := me.elemEnc(val)
91 1
		if err != nil {
92
			return nil, err
93
		}
94 1
		dataBytes = append(dataBytes, encodedValue...)
95
	}
96
97 1
	keys := v.MapKeys()
98
99 1
	bytes := []byte{}
100
101 1
	typeBytes := Uint8(binn.MapType)
102 1
	countBytes := Size(len(keys), false)
103
104 1
	bytes = append(bytes, typeBytes...)
105 1
	bytes = append(bytes, Size(len(typeBytes)+len(dataBytes)+len(countBytes), true)...)
106 1
	bytes = append(bytes, countBytes...)
107 1
	bytes = append(bytes, dataBytes...)
108
109 1
	return bytes, nil
110
}
111
112
func encodeTextKey(v reflect.Value) ([]byte, error) {
113 1
	if v.Kind() == reflect.String {
114 1
		return String(v.String()), nil
115
	}
116
117
	m, ok := v.Interface().(encoding.TextMarshaler)
118
	if !ok {
119
		return []byte{binn.Null}, nil
120
	}
121
122
	s, err := m.MarshalText()
123
	if err != nil {
124
		return nil, err
125
	}
126
127
	return String(string(s)), nil
128
}
129