-
Notifications
You must be signed in to change notification settings - Fork 1
/
class.go
188 lines (158 loc) · 5.4 KB
/
class.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
package errors
const (
majorBitSize = 8
minorBitSize = 10
indexBitSize = 32 - majorBitSize - minorBitSize
maxIndexValue = (2 << (indexBitSize - 1)) - 1
maxMinorValue = (2 << (minorBitSize - 1)) - 1
)
func init() {
initClasses()
}
func initClasses() {
internalMajor, _ := container.newMajor()
invalidMajor, _ := container.newMinor(internalMajor)
ClInvalidMajor = MustNewMinorClass(internalMajor, invalidMajor)
invalidMinor, _ := container.newMinor(internalMajor)
ClInvalidMinor = MustNewMinorClass(internalMajor, invalidMinor)
invalidIndex, _ := container.newMinor(internalMajor)
ClInvalidIndex = MustNewMinorClass(internalMajor, invalidIndex)
}
var (
// ClInvalidMajor defines the invalid major error classification.
ClInvalidMajor Class
// ClInvalidMinor defines the invalid minor error classification.
ClInvalidMinor Class
// ClInvalidIndex defines the invalid index error classification.
ClInvalidIndex Class
)
// Class is the error classification model.
// It is composed of the major, minor and index subclassifications.
// Each subclassifaction is a different length number, where
// major is composed of 8, minor 10 and index of 14 bits.
// Example:
// 44205263 in a binary form is:
//
// 00000010101000101000010011001111 which decomposes into:
// 00000010 - major (8 bit) - 2
// 1010001010 - minor (10 bit) - 650
// 00010011001111 - index (14 bit) - 1231
//
// Major should be a global scope division like 'Repository', 'Marshaler', 'Controller' etc.
// Minor should divide the 'major' into subclasses like the Repository filter builders, marshaler - invalid field etc.
// Index is the most precise classification - i.e. Repository - filter builder - unsupported operator.
type Class uint32
// Index is a four digit number unique within given minor and major.
func (c Class) Index() Index {
return c.index()
}
// Major is a single digit major classification.
func (c Class) Major() Major {
return c.major()
}
// Minor is a double digit minor classification unique within given major.
func (c Class) Minor() Minor {
return c.minor()
}
func (c Class) index() Index {
return Index(c & maxIndexValue)
}
func (c Class) major() Major {
return Major(c >> (32 - majorBitSize))
}
func (c Class) minor() Minor {
return Minor(c >> (indexBitSize) & maxMinorValue)
}
// NewClass gets new class from the provided 'minor' and 'index'.
// If any of the arguments is not valid or out of bands the function returns an error.
func NewClass(mjr Major, mnr Minor, index Index) (Class, error) {
return newClass(mjr, mnr, index)
}
// NewClassWIndex creates new index and class for provided 'mjr' Major and 'mnr' Minor.
// Returns error if any of the input values are not valid.
func NewClassWIndex(mjr Major, mnr Minor) (Class, error) {
return newClassWIndex(mjr, mnr)
}
func newClassWIndex(mjr Major, mnr Minor) (Class, error) {
index, err := container.newIndex(mjr, mnr)
if err != nil {
return 0, err
}
return newClass(mjr, mnr, index)
}
// MustNewClass gets new class from the provided 'minor' and 'index'.
// Panics if any of the arguments is not valid or out of bands.
func MustNewClass(mjr Major, mnr Minor, index Index) Class {
c, err := newClass(mjr, mnr, index)
if err != nil {
panic(err)
}
return c
}
// MustNewClassWIndex creates new 'mjr' Major, 'mnr' Minor 'index' and then
// a new Class for provided triplet.
// Panics on error.
func MustNewClassWIndex(mjr Major, mnr Minor) Class {
c, err := newClassWIndex(mjr, mnr)
if err != nil {
panic(err)
}
return c
}
// NewMinorClass gets the class from provided 'minor'.
// The function gets minor's major and gets the major/minor class.
func NewMinorClass(mjr Major, mnr Minor) (Class, error) {
return newMinorClass(mjr, mnr)
}
// MustNewMinorClass creates a class from the provided 'mjr' Major and 'mnr' Minor.
// Panics when any of the provided arguments is invalid.
func MustNewMinorClass(mjr Major, mnr Minor) Class {
c, err := newMinorClass(mjr, mnr)
if err != nil {
panic(err)
}
return c
}
// NewMajorClass creates Class from the provided 'mjr' Major.
// This class contains zero valued 'Minor' and 'Index'.
// Returns error if the 'mjr' is invalid.
func NewMajorClass(mjr Major) (Class, error) {
return newMajorClass(mjr)
}
// MustNewMajorClass creates Class from the provided 'mjr' Major.
// This class contains zero valued 'Minor' and 'Index'.
// Panics if provided 'mjr' is invalid.
func MustNewMajorClass(mjr Major) Class {
c, err := newMajorClass(mjr)
if err != nil {
panic(err)
}
return c
}
func newMajorClass(mjr Major) (Class, error) {
if !mjr.Valid() {
return Class(0), NewDet(ClInvalidMajor, "provided invalid major")
}
return Class(uint32(mjr) << (32 - majorBitSize)), nil
}
func newMinorClass(mjr Major, mnr Minor) (Class, error) {
if !mjr.Valid() {
return Class(0), NewDet(ClInvalidMajor, "provided invalid major")
}
if !mnr.Valid() {
return Class(0), NewDet(ClInvalidMinor, "provided invalid minor")
}
return Class(uint32(mjr)<<(32-majorBitSize) | uint32(mnr)<<(32-minorBitSize-majorBitSize)), nil
}
func newClass(mjr Major, mnr Minor, index Index) (Class, error) {
if !mjr.Valid() {
return Class(0), NewDet(ClInvalidMajor, "provided invalid major")
}
if !mnr.Valid() {
return Class(0), NewDet(ClInvalidMinor, "provided invalid minor")
}
if !index.Valid() {
return Class(0), NewDet(ClInvalidIndex, "provided invalid index")
}
return Class(uint32(mjr)<<(32-majorBitSize) | uint32(mnr)<<(32-minorBitSize-majorBitSize) | uint32(index)), nil
}