1
2
3
4 package template
5
6 import (
7 "errors"
8 "reflect"
9 )
10
11 var (
12 errBadComparisonType = errors.New("invalid type for comparison")
13 errBadComparison = errors.New("incompatible types for comparison")
14 errNoComparison = errors.New("missing argument for comparison")
15 )
16
17 type kind int
18
19 const (
20 invalidKind kind = iota
21 boolKind
22 complexKind
23 intKind
24 floatKind
25 integerKind
26 stringKind
27 uintKind
28 )
29
30 func basicKind(v reflect.Value) (kind, error) {
31 switch v.Kind() {
32 case reflect.Bool:
33 return boolKind, nil
34 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
35 return intKind, nil
36 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
37 return uintKind, nil
38 case reflect.Float32, reflect.Float64:
39 return floatKind, nil
40 case reflect.Complex64, reflect.Complex128:
41 return complexKind, nil
42 case reflect.String:
43 return stringKind, nil
44 }
45 return invalidKind, errBadComparisonType
46 }
47
48
49 func Equal(arg1 interface{}, arg2 ...interface{}) (bool, error) {
50 v1 := reflect.ValueOf(arg1)
51 k1, err := basicKind(v1)
52 if err != nil {
53 return false, err
54 }
55 if len(arg2) == 0 {
56 return false, errNoComparison
57 }
58 for _, arg := range arg2 {
59 v2 := reflect.ValueOf(arg)
60 k2, err := basicKind(v2)
61 if err != nil {
62 return false, err
63 }
64 truth := false
65 if k1 != k2 {
66
67 switch {
68 case k1 == intKind && k2 == uintKind:
69 truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint()
70 case k1 == uintKind && k2 == intKind:
71 truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int())
72 default:
73 return false, errBadComparison
74 }
75 } else {
76 switch k1 {
77 case boolKind:
78 truth = v1.Bool() == v2.Bool()
79 case complexKind:
80 truth = v1.Complex() == v2.Complex()
81 case floatKind:
82 truth = v1.Float() == v2.Float()
83 case intKind:
84 truth = v1.Int() == v2.Int()
85 case stringKind:
86 truth = v1.String() == v2.String()
87 case uintKind:
88 truth = v1.Uint() == v2.Uint()
89 default:
90 panic("invalid kind")
91 }
92 }
93 if truth {
94 return true, nil
95 }
96 }
97 return false, nil
98 }
99
100
101 func NotEqual(arg1, arg2 interface{}) (bool, error) {
102
103 equal, err := Equal(arg1, arg2)
104 return !equal, err
105 }
106
107
108 func Less(arg1, arg2 interface{}) (bool, error) {
109 v1 := reflect.ValueOf(arg1)
110 k1, err := basicKind(v1)
111 if err != nil {
112 return false, err
113 }
114 v2 := reflect.ValueOf(arg2)
115 k2, err := basicKind(v2)
116 if err != nil {
117 return false, err
118 }
119 truth := false
120 if k1 != k2 {
121
122 switch {
123 case k1 == intKind && k2 == uintKind:
124 truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint()
125 case k1 == uintKind && k2 == intKind:
126 truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int())
127 default:
128 return false, errBadComparison
129 }
130 } else {
131 switch k1 {
132 case boolKind, complexKind:
133 return false, errBadComparisonType
134 case floatKind:
135 truth = v1.Float() < v2.Float()
136 case intKind:
137 truth = v1.Int() < v2.Int()
138 case stringKind:
139 truth = v1.String() < v2.String()
140 case uintKind:
141 truth = v1.Uint() < v2.Uint()
142 default:
143 panic("invalid kind")
144 }
145 }
146 return truth, nil
147 }
148
149
150 func LessEqual(arg1, arg2 interface{}) (bool, error) {
151
152 lessThan, err := Less(arg1, arg2)
153 if lessThan || err != nil {
154 return lessThan, err
155 }
156 return Equal(arg1, arg2)
157 }
158
159
160 func Greater(arg1, arg2 interface{}) (bool, error) {
161
162 lessOrEqual, err := LessEqual(arg1, arg2)
163 if err != nil {
164 return false, err
165 }
166 return !lessOrEqual, nil
167 }
168
169
170 func GreaterEqual(arg1, arg2 interface{}) (bool, error) {
171
172 lessThan, err := Less(arg1, arg2)
173 if err != nil {
174 return false, err
175 }
176 return !lessThan, nil
177 }
178
View as plain text