-
Notifications
You must be signed in to change notification settings - Fork 2
/
util.go
121 lines (107 loc) · 2.5 KB
/
util.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
package loggable
import (
"encoding/json"
"reflect"
"regexp"
"strings"
"unicode"
)
func isEqual(item1, item2 interface{}, except ...string) bool {
except = StringMap(except, ToSnakeCase)
m1, m2 := somethingToMapStringInterface(item1), somethingToMapStringInterface(item2)
if len(m1) != len(m2) {
return false
}
for k, v := range m1 {
if isInStringSlice(ToSnakeCase(k), except) {
continue
}
v2, ok := m2[k]
if !ok || !reflect.DeepEqual(v, v2) {
return false
}
}
return true
}
func somethingToMapStringInterface(item interface{}) map[string]interface{} {
if item == nil {
return nil
}
switch raw := item.(type) {
case string:
return somethingToMapStringInterface([]byte(raw))
case []byte:
var m map[string]interface{}
err := json.Unmarshal(raw, &m)
if err != nil {
return nil
}
return m
default:
data, err := json.Marshal(item)
if err != nil {
return nil
}
return somethingToMapStringInterface(data)
}
return nil
}
var ToSnakeCase = toSomeCase("_")
func toSomeCase(sep string) func(string) string {
return func(s string) string {
for i := range s {
if unicode.IsUpper(rune(s[i])) {
if i != 0 {
s = strings.Join([]string{s[:i], ToLowerFirst(s[i:])}, sep)
} else {
s = ToLowerFirst(s)
}
}
}
return s
}
}
func ToLowerFirst(s string) string {
if len(s) == 0 {
return ""
}
return strings.ToLower(string(s[0])) + s[1:]
}
func StringMap(strs []string, fn func(string) string) []string {
res := make([]string, len(strs))
for i := range strs {
res[i] = fn(strs[i])
}
return res
}
func isInStringSlice(what string, where []string) bool {
for i := range where {
if what == where[i] {
return true
}
}
return false
}
func getLoggableFieldNames(value interface{}) []string {
var names []string
t := reflect.TypeOf(value).Elem()
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value, ok := field.Tag.Lookup(loggableTag)
if ok && value == "disable" {
continue
}
names = append(names, field.Name)
}
return names
}
var matchFirstCap = regexp.MustCompile("([A-Z])([A-Z][a-z])")
var matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])")
// ToSnakeCase converts the provided string to snake_case.
// Based on https://gist.github.com/stoewer/fbe273b711e6a06315d19552dd4d33e6
func ToSnakeCaseRegEx(input string) string {
output := matchFirstCap.ReplaceAllString(input, "${1}_${2}")
output = matchAllCap.ReplaceAllString(output, "${1}_${2}")
output = strings.ReplaceAll(output, "-", "_")
return strings.ToLower(output)
}