-
Notifications
You must be signed in to change notification settings - Fork 3
/
utils.go
244 lines (213 loc) · 6.11 KB
/
utils.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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
package utils
// utils contains utility functions that are used in packages
import (
"crypto/rand"
"encoding/binary"
"encoding/hex"
"log"
"math/big"
"os/user"
"runtime"
"strconv"
"time"
"github.com/pkg/errors"
"golang.org/x/crypto/sha3"
)
// ErrTypeNotSupported is an error returned if the given type conversion isn't supported yet
var ErrTypeNotSupported = errors.New("type not supported, please feel free to PR")
// Timestamp gets the human readable timestamp
func Timestamp() string {
return time.Now().Format(time.RFC850)
}
// Unix gets the unix timestamp
func Unix() int64 {
return time.Now().Unix()
}
// IntToHumanTime converts an int64 to human readable time
func IntToHumanTime(inputInt int64) string {
return time.Unix(inputInt, 0).Format(time.RFC850)
}
// StringToHumanTime converts an int64 in string form to human readable time
func StringToHumanTime(inputString string) string {
inputInt, err := strconv.ParseInt(inputString, 10, 64)
if err != nil {
log.Println(err)
}
return IntToHumanTime(inputInt)
}
// StringToIntTime converts a string to unix time
func StringToIntTime(inputString string) int64 {
layout := "Monday, 02-Jan-06 15:04:05 MST"
t, err := time.Parse(layout, inputString)
if err != nil {
return 0
}
return t.Unix()
}
// SHA3hash gets the SHA3-512 hash of the passed string
func SHA3hash(inputString string) string {
byteString := sha3.Sum512([]byte(inputString))
return hex.EncodeToString(byteString[:])
// so now we have a SHA3hash that we can use to assign unique ids to our assets
}
// GetHomeDir gets the home directory of the user
func GetHomeDir() (string, error) {
usr, err := user.Current()
if err != nil {
log.Println("error while getting current directory")
}
return usr.HomeDir, err
}
// GetRandomString gets a random string of length n
func GetRandomString(n int) string {
// random string implementation courtesy: icza
// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go
const (
letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
letterIdxBits = 6 // 6 bits to represent a letter index
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
)
var err error
int64Lim := new(big.Int).SetInt64(int64(1<<63 - 1)) // int64 lim = 2*63 -1
b := make([]byte, n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
for i, remain := n-1, letterIdxMax; i >= 0; {
var tmp *big.Int
tmp, err = rand.Int(rand.Reader, int64Lim)
cache := tmp.Int64()
if remain == 0 {
tmp, err = rand.Int(rand.Reader, int64Lim)
cache = tmp.Int64()
remain = letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
b[i] = letterBytes[idx]
i--
}
cache >>= letterIdxBits
remain--
}
if err != nil {
b = []byte{0}
}
return string(b)
}
// ToBigInt converts a passed interface to big.Int
func ToBigInt(x interface{}) (*big.Int, error) {
log.Println("calling anything to byte function")
switch x.(type) {
case big.Int:
return x.(*big.Int), nil
case []byte:
return new(big.Int).SetBytes(x.([]byte)), nil
case int:
return big.NewInt(int64(x.(int))), nil
case uint64:
return new(big.Int).SetUint64(x.(uint64)), nil
case string:
log.Println([]byte(x.(string)))
return new(big.Int).SetBytes([]byte(x.(string))), nil
default:
return new(big.Int).SetUint64(0), nil
}
}
// ToByte converts a passed interface to bytes
func ToByte(x interface{}) ([]byte, error) {
switch x.(type) {
case []byte:
return x.([]byte), nil
case int:
string1 := strconv.Itoa(x.(int))
return []byte(string1), nil
case uint32:
a := make([]byte, 4)
binary.BigEndian.PutUint32(a, x.(uint32))
return a, nil
case uint16:
a := make([]byte, 2)
binary.BigEndian.PutUint16(a, x.(uint16))
return a[1:], nil
case uint64:
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, x.(uint64))
return b, nil
}
log.Println("type conversion not supported")
return nil, ErrTypeNotSupported
}
// ToString converts a passed interface to string
func ToString(x interface{}) (string, error) {
switch x.(type) {
case string:
return x.(string), nil
case float64:
return strconv.FormatFloat(x.(float64), 'f', 6, 64), nil
case int64:
return strconv.FormatInt(x.(int64), 10), nil // s == "97" (decimal)
case uint32:
return strconv.FormatUint(uint64(x.(uint32)), 10), nil
case int:
return strconv.Itoa(x.(int)), nil
}
log.Println("type conversion not supported")
return "", ErrTypeNotSupported
}
// ToInt converts a passed interface to int
func ToInt(x interface{}) (int, error) {
switch x.(type) {
case int:
return x.(int), nil
case string:
return strconv.Atoi(x.(string))
case []byte:
return strconv.Atoi(string(x.([]byte)))
}
log.Println("type conversion not supported")
return -1, ErrTypeNotSupported
}
// ToFloat converts a passed interface to float
func ToFloat(x interface{}) (float64, error) {
switch x.(type) {
case float64:
return x.(float64), nil
case []byte:
return ToFloat(string(x.([]byte)))
case string:
return strconv.ParseFloat(x.(string), 32)
case int:
return float64(x.(int)), nil
}
log.Println("type conversion not supported")
return -1, ErrTypeNotSupported
}
// ToUint16 converts a passed interface to uint16
func ToUint16(x interface{}) (uint16, error) {
switch x.(type) {
case uint16:
return x.(uint16), nil
case []byte:
b := x.([]byte)
if len(b) == 1 {
zero := make([]byte, 1)
b = append(zero, b...)
}
return binary.BigEndian.Uint16(b), nil
}
log.Println("type conversion not supported")
return 0, ErrTypeNotSupported
}
// PrintMemUsage outputs the current, total and OS memory being used. As well as the number
// of garage collection cycles completed.
func PrintMemUsage() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
log.Printf("Alloc = %v MiB", BToMb(m.Alloc))
log.Printf("\tTotalAlloc = %v MiB", BToMb(m.TotalAlloc))
log.Printf("\tSys = %v MiB", BToMb(m.Sys))
log.Printf("\tNumGC = %v\n", m.NumGC)
}
// BToMb converts bytes (b) to Mb
func BToMb(b uint64) uint64 {
return b / 1024 / 1024
}