decode.readValue   F
last analyzed

Complexity

Conditions 16

Size

Total Lines 65
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 16.8148

Importance

Changes 0
Metric Value
cc 16
eloc 46
dl 0
loc 65
ccs 29
cts 34
cp 0.8529
crap 16.8148
rs 2.4
c 0
b 0
f 0
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like decode.readValue often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package decode
2
3
import (
4
	"fmt"
5
	"io"
6
7
	"github.com/et-nik/binngo/binn"
8
	"github.com/et-nik/binngo/encode"
9
)
10
11
//nolint:funlen
12
func readValue(btype binn.Type, reader io.Reader) ([]byte, error) {
13 1
	tp := btype &^ binn.StorageTypeMask
14
15 1
	var readingSize int
16 1
	var containerSize int
17
18 1
	var bytes []byte
19
20 1
	switch tp {
21
	case binn.StorageNoBytes:
22 1
		readingSize = 0
23
	case binn.StorageByte:
24 1
		readingSize = 1
25
	case binn.StorageWord:
26 1
		readingSize = 2
27
	case binn.StorageDWord:
28 1
		readingSize = 4
29
	case binn.StorageQWord:
30 1
		readingSize = 8
31
	case binn.StorageString:
32 1
		dataSize, _, err := readSize(reader)
33 1
		if err != nil {
34
			return nil, fmt.Errorf("failed to read string storage size: %w", err)
35
		}
36 1
		readingSize = dataSize + 1 // data size and null terminator
37
	case binn.StorageBlob:
38 1
		dataSize, _, err := readSize(reader)
39 1
		if err != nil {
40
			return nil, fmt.Errorf("failed to read string storage size: %w", err)
41
		}
42 1
		readingSize = dataSize
43
	case binn.StorageContainer:
44 1
		s, l, err := readSize(reader)
45 1
		if err != nil {
46
			return nil, fmt.Errorf("failed to read storage size: %w", err)
47
		}
48
49 1
		containerSize = s
50
51 1
		bytes = append(bytes, encode.Size(s, false)...)
52
53 1
		readingSize = containerSize - 1 - int(l) // minus container type byte and size byte
54
	default:
55
		return nil, ErrUnknownType
56
	}
57
58 1
	if readingSize == 0 {
59 1
		return []byte{byte(btype)}, nil
60
	}
61
62 1
	b := make([]byte, readingSize)
63
	read := 0
64 1
65 1
	for read < readingSize {
66
		n, err := reader.Read(b[read:])
67 1
		if err != nil {
68
			return nil, fmt.Errorf("failed to read storage: %w", err)
69
		}
70
71 1
		read += n
72
	}
73
74
	bytes = append(bytes, b...)
75 1
76
	return bytes, nil
77
}
78
79 1
func isStorageContainer(btype binn.Type) bool {
80
	return (btype &^ binn.StorageTypeMask) == binn.StorageContainer
81 1
}
82 1
83 1
func readType(reader io.Reader) (binn.Type, readLen, error) {
84
	var bt = make([]byte, 1)
85
86 1
	_, err := reader.Read(bt)
87
	if err != nil {
88
		return binn.Null, 0, &FailedToReadTypeError{Previous: err}
89
	}
90 1
91 1
	return Type(bt), 1, nil
92 1
}
93
94
func readSize(reader io.Reader) (int, readLen, error) {
95
	var bsz = make([]byte, 1)
96 1
	_, err := reader.Read(bsz)
97
	if err != nil {
98 1
		return 0, 0, &FailedToReadSizeError{err}
99
	}
100 1
101 1
	read := 1
102 1
103 1
	sz := int(Uint8(bsz))
104
105
	if sz > maxOneByteSize {
106 1
		var bszOtherBytes = make([]byte, 3)
107
		_, err := reader.Read(bszOtherBytes)
108 1
		if err != nil {
109
			return 0, 0, fmt.Errorf("failed to read long size: %w", err)
110
		}
111
		read += 3
112
113
		sz = int(Uint32([]byte{
114
			byte(sz),
115 1
			bszOtherBytes[0],
116
			bszOtherBytes[1],
117
			bszOtherBytes[2],
118 1
		}))
119
120
		sz &= 0x7FFFFFFF
121
	}
122
123
	return sz, readLen(read), nil
124
}
125