generated from ipfs/ipfs-repository-template
-
Notifications
You must be signed in to change notification settings - Fork 97
/
util.go
158 lines (135 loc) · 4.04 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
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
// Package util implements various utility functions used within ipfs
// that do not currently have a better place to live.
package util
import (
"errors"
"io"
"math/rand"
"os"
"path/filepath"
"runtime/debug"
"strings"
"time"
b58 "github.com/mr-tron/base58/base58"
mh "github.com/multiformats/go-multihash"
)
// DefaultIpfsHash is the current default hash function used by IPFS.
const DefaultIpfsHash = mh.SHA2_256
// Debug is a global flag for debugging.
var Debug bool
// ErrNotImplemented signifies a function has not been implemented yet.
var ErrNotImplemented = errors.New("error: not implemented yet")
// ErrTimeout implies that a timeout has been triggered
var ErrTimeout = errors.New("error: call timed out")
// ErrSearchIncomplete implies that a search type operation didn't
// find the expected node, but did find 'a' node.
var ErrSearchIncomplete = errors.New("error: search incomplete")
// ErrCast is returned when a cast fails AND the program should not panic.
func ErrCast() error {
debug.PrintStack()
return errCast
}
var errCast = errors.New("cast error")
// ExpandPathnames takes a set of paths and turns them into absolute paths
func ExpandPathnames(paths []string) ([]string, error) {
var out []string
for _, p := range paths {
abspath, err := filepath.Abs(p)
if err != nil {
return nil, err
}
out = append(out, abspath)
}
return out, nil
}
type randGen struct {
rand.Rand
}
// NewTimeSeededRand returns a random bytes reader
// which has been initialized with the current time.
func NewTimeSeededRand() io.Reader {
src := rand.NewSource(time.Now().UnixNano())
return &randGen{
Rand: *rand.New(src),
}
}
// NewSeededRand returns a random bytes reader
// initialized with the given seed.
func NewSeededRand(seed int64) io.Reader {
src := rand.NewSource(seed)
return &randGen{
Rand: *rand.New(src),
}
}
func (r *randGen) Read(p []byte) (n int, err error) {
for i := 0; i < len(p); i++ {
p[i] = byte(r.Rand.Intn(255))
}
return len(p), nil
}
// GetenvBool is the way to check an env var as a boolean
func GetenvBool(name string) bool {
v := strings.ToLower(os.Getenv(name))
return v == "true" || v == "t" || v == "1"
}
// MultiErr is a util to return multiple errors
type MultiErr []error
func (m MultiErr) Error() string {
if len(m) == 0 {
return "no errors"
}
s := "Multiple errors: "
for i, e := range m {
if i != 0 {
s += ", "
}
s += e.Error()
}
return s
}
// Partition splits a subject 3 parts: prefix, separator, suffix.
// The first occurrence of the separator will be matched.
// ie. Partition("Ready, steady, go!", ", ") -> ["Ready", ", ", "steady, go!"]
func Partition(subject string, sep string) (string, string, string) {
if i := strings.Index(subject, sep); i != -1 {
return subject[:i], subject[i : i+len(sep)], subject[i+len(sep):]
}
return subject, "", ""
}
// RPartition splits a subject 3 parts: prefix, separator, suffix.
// The last occurrence of the separator will be matched.
// ie. RPartition("Ready, steady, go!", ", ") -> ["Ready, steady", ", ", "go!"]
func RPartition(subject string, sep string) (string, string, string) {
if i := strings.LastIndex(subject, sep); i != -1 {
return subject[:i], subject[i : i+len(sep)], subject[i+len(sep):]
}
return subject, "", ""
}
// Hash is the global IPFS hash function. uses multihash SHA2_256, 256 bits
func Hash(data []byte) mh.Multihash {
h, err := mh.Sum(data, DefaultIpfsHash, -1)
if err != nil {
// this error can be safely ignored (panic) because multihash only fails
// from the selection of hash function. If the fn + length are valid, it
// won't error.
panic("multihash failed to hash using SHA2_256.")
}
return h
}
// IsValidHash checks whether a given hash is valid (b58 decodable, len > 0)
func IsValidHash(s string) bool {
out, err := b58.Decode(s)
if err != nil {
return false
}
_, err = mh.Cast(out)
return err == nil
}
// XOR takes two byte slices, XORs them together, returns the resulting slice.
func XOR(a, b []byte) []byte {
c := make([]byte, len(a))
for i := 0; i < len(a); i++ {
c[i] = a[i] ^ b[i]
}
return c
}