-
Notifications
You must be signed in to change notification settings - Fork 3
/
robusthashingdata.go
119 lines (110 loc) · 2.83 KB
/
robusthashingdata.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
package care
import (
"errors"
"fmt"
"reflect"
"sort"
"strings"
)
func squashSequenceToString(val reflect.Value, builder *strings.Builder) (err error) {
arrlen := val.Len()
if arrlen < 1 {
builder.WriteString("nil")
} else {
sb := strings.Builder{}
items := make([]string, 0, arrlen)
for i := 0; i < arrlen; i++ {
err = robustHashingData(val.Index(i).Interface(), &sb)
if err != nil {
return
}
items = append(items, sb.String())
sb.Reset()
}
sort.Strings(items)
builder.WriteString(strings.Join(items, " "))
}
return
}
func squashMapToString(val reflect.Value, builder *strings.Builder) (err error) {
mkeys := val.MapKeys()
mlen := len(mkeys)
if mlen < 1 {
builder.WriteString("nil")
} else {
items := make([]string, 0, 2*mlen)
sb := strings.Builder{}
for _, mkey := range mkeys {
mval := val.MapIndex(mkey)
if err = robustHashingData(mkey.Interface(), &sb); err != nil {
return
}
kitem := sb.String()
sb.Reset()
if err = robustHashingData(mval.Interface(), &sb); err != nil {
return
}
vitem := sb.String()
sb.Reset()
items = append(items, kitem+" "+vitem)
}
sort.Strings(items)
builder.WriteString(strings.Join(items, " "))
}
return
}
func squashStructToString(val reflect.Value, typ reflect.Type, builder *strings.Builder) (err error) {
fields := val.NumField()
items := make([]string, 0, fields)
sb := strings.Builder{}
for i := 0; i < fields; i++ {
tf := typ.Field(i)
if !tf.IsExported() {
continue
}
if err = robustHashingData(val.Field(i).Interface(), &sb); err != nil {
return
}
fname := tf.Name
item := fname + " " + sb.String()
sb.Reset()
items = append(items, item)
}
sort.Strings(items)
builder.WriteString(strings.Join(items, " "))
return
}
func robustHashingData(val interface{}, builder *strings.Builder) (err error) {
defer func() {
if r := recover(); r != nil {
err = errors.New(fmt.Sprint("Something goes wrong, ", r))
}
}()
v := reflect.ValueOf(val)
if !v.IsValid() {
return errors.New("The input value is not a valid value.")
}
typ := v.Type()
builder.WriteString(typ.String() + ": ")
switch v.Type().Kind() {
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Uintptr, reflect.Float32, reflect.Float64, reflect.String:
builder.WriteString(fmt.Sprint(v))
case reflect.Array, reflect.Slice:
err = squashSequenceToString(v, builder)
case reflect.Map:
err = squashMapToString(v, builder)
case reflect.Pointer:
if v.IsNil() {
builder.WriteString("nil")
} else {
err = robustHashingData(v.Elem().Interface(), builder)
}
case reflect.Struct:
err = squashStructToString(v, typ, builder)
default:
panic("The type \"" + typ.String() + "\" is not for processing.")
}
return
}