-
Notifications
You must be signed in to change notification settings - Fork 3
/
util.go
89 lines (78 loc) · 2.06 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
package main
import (
"crypto/sha512"
"encoding/csv"
"errors"
"fmt"
"os"
"github.com/gocarina/gocsv"
"golang.org/x/exp/constraints"
)
// Min returns the smaller of two values.
func Min[T constraints.Ordered](a T, b T) T {
if a < b {
return a
}
return b
}
// Max returns the larger of two values.
func Max[T constraints.Ordered](a T, b T) T {
if a > b {
return a
}
return b
}
// Concurrent runs the given function concurrently, returning its result on a
// channel.
func Concurrent[T any](f func() T) <-chan T {
ret := make(chan T)
go func() {
ret <- f()
close(ret)
}()
return ret
}
// RemoveDuplicates removes duplicates from the given slice in-place.
func RemoveDuplicates[T comparable](slice *[]T) {
firstIndexOf := make(map[T]int, len(*slice))
for _, v := range *slice {
if _, ok := firstIndexOf[v]; !ok {
firstIndexOf[v] = len(firstIndexOf)
}
}
for v, i := range firstIndexOf {
(*slice)[i] = v
}
*slice = (*slice)[:len(firstIndexOf)]
}
// RightPad returns s, right-padded with spaces up to the total given padded
// length, or s unchanged if paddedLen is smaller than len(s).
func RightPad(s string, paddedLen int) string {
return fmt.Sprintf("%s%-*s", s, Max((paddedLen-len(s)), 0), "")
}
// CryptHash represents a hash created by a current cryptographically secure
// algorithm.
type CryptHash [sha512.Size]byte
// CryptHashOfSlice hashes the given byte slice using a current
// cryptographically secure algorithm.
var CryptHashOfSlice = sha512.Sum512
// CryptHashOfFile hashes the file with the given name using a current
// cryptographically secure algorithm.
func CryptHashOfFile(fn string) CryptHash {
f, err := os.ReadFile(fn)
FatalIf(err)
return CryptHashOfSlice(f)
}
// LoadTSV loads a TSV file using the given gocsv unmarshaler.
func LoadTSV(slice any, fn string, unmarshaler func(gocsv.CSVReader, interface{}) error) bool {
f, err := os.Open(fn)
if errors.Is(err, os.ErrNotExist) {
return false
}
FatalIf(err)
reader := csv.NewReader(f)
reader.Comma = '\t'
reader.LazyQuotes = true
FatalIf(unmarshaler(reader, slice))
return true
}