1/*
2Gomega matchers
3
4This package implements the Gomega matchers and does not typically need to be imported.
5See the docs for Gomega for documentation on the matchers
6
7http://onsi.github.io/gomega/
8*/
9package matchers
10
11import (
12	"fmt"
13	"reflect"
14)
15
16type omegaMatcher interface {
17	Match(actual interface{}) (success bool, err error)
18	FailureMessage(actual interface{}) (message string)
19	NegatedFailureMessage(actual interface{}) (message string)
20}
21
22func isBool(a interface{}) bool {
23	return reflect.TypeOf(a).Kind() == reflect.Bool
24}
25
26func isNumber(a interface{}) bool {
27	if a == nil {
28		return false
29	}
30	kind := reflect.TypeOf(a).Kind()
31	return reflect.Int <= kind && kind <= reflect.Float64
32}
33
34func isInteger(a interface{}) bool {
35	kind := reflect.TypeOf(a).Kind()
36	return reflect.Int <= kind && kind <= reflect.Int64
37}
38
39func isUnsignedInteger(a interface{}) bool {
40	kind := reflect.TypeOf(a).Kind()
41	return reflect.Uint <= kind && kind <= reflect.Uint64
42}
43
44func isFloat(a interface{}) bool {
45	kind := reflect.TypeOf(a).Kind()
46	return reflect.Float32 <= kind && kind <= reflect.Float64
47}
48
49func toInteger(a interface{}) int64 {
50	if isInteger(a) {
51		return reflect.ValueOf(a).Int()
52	} else if isUnsignedInteger(a) {
53		return int64(reflect.ValueOf(a).Uint())
54	} else if isFloat(a) {
55		return int64(reflect.ValueOf(a).Float())
56	}
57	panic(fmt.Sprintf("Expected a number!  Got <%T> %#v", a, a))
58}
59
60func toUnsignedInteger(a interface{}) uint64 {
61	if isInteger(a) {
62		return uint64(reflect.ValueOf(a).Int())
63	} else if isUnsignedInteger(a) {
64		return reflect.ValueOf(a).Uint()
65	} else if isFloat(a) {
66		return uint64(reflect.ValueOf(a).Float())
67	}
68	panic(fmt.Sprintf("Expected a number!  Got <%T> %#v", a, a))
69}
70
71func toFloat(a interface{}) float64 {
72	if isInteger(a) {
73		return float64(reflect.ValueOf(a).Int())
74	} else if isUnsignedInteger(a) {
75		return float64(reflect.ValueOf(a).Uint())
76	} else if isFloat(a) {
77		return reflect.ValueOf(a).Float()
78	}
79	panic(fmt.Sprintf("Expected a number!  Got <%T> %#v", a, a))
80}
81
82func isError(a interface{}) bool {
83	_, ok := a.(error)
84	return ok
85}
86
87func isChan(a interface{}) bool {
88	if isNil(a) {
89		return false
90	}
91	return reflect.TypeOf(a).Kind() == reflect.Chan
92}
93
94func isMap(a interface{}) bool {
95	if a == nil {
96		return false
97	}
98	return reflect.TypeOf(a).Kind() == reflect.Map
99}
100
101func isArrayOrSlice(a interface{}) bool {
102	if a == nil {
103		return false
104	}
105	switch reflect.TypeOf(a).Kind() {
106	case reflect.Array, reflect.Slice:
107		return true
108	default:
109		return false
110	}
111}
112
113func isString(a interface{}) bool {
114	if a == nil {
115		return false
116	}
117	return reflect.TypeOf(a).Kind() == reflect.String
118}
119
120func toString(a interface{}) (string, bool) {
121	aString, isString := a.(string)
122	if isString {
123		return aString, true
124	}
125
126	aBytes, isBytes := a.([]byte)
127	if isBytes {
128		return string(aBytes), true
129	}
130
131	aStringer, isStringer := a.(fmt.Stringer)
132	if isStringer {
133		return aStringer.String(), true
134	}
135
136	return "", false
137}
138
139func lengthOf(a interface{}) (int, bool) {
140	if a == nil {
141		return 0, false
142	}
143	switch reflect.TypeOf(a).Kind() {
144	case reflect.Map, reflect.Array, reflect.String, reflect.Chan, reflect.Slice:
145		return reflect.ValueOf(a).Len(), true
146	default:
147		return 0, false
148	}
149}
150func capOf(a interface{}) (int, bool) {
151	if a == nil {
152		return 0, false
153	}
154	switch reflect.TypeOf(a).Kind() {
155	case reflect.Array, reflect.Chan, reflect.Slice:
156		return reflect.ValueOf(a).Cap(), true
157	default:
158		return 0, false
159	}
160}
161
162func isNil(a interface{}) bool {
163	if a == nil {
164		return true
165	}
166
167	switch reflect.TypeOf(a).Kind() {
168	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
169		return reflect.ValueOf(a).IsNil()
170	}
171
172	return false
173}
174