github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/util/util.go (about) 1 // Package util implements various utility functions used within ipfs 2 // that do not currently have a better place to live. 3 package util 4 5 import ( 6 "errors" 7 "io" 8 "math/rand" 9 "os" 10 "path/filepath" 11 "runtime/debug" 12 "strings" 13 "time" 14 15 b58 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" 16 ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" 17 mh "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" 18 19 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/mitchellh/go-homedir" 20 ) 21 22 // Debug is a global flag for debugging. 23 var Debug bool 24 25 // ErrNotImplemented signifies a function has not been implemented yet. 26 var ErrNotImplemented = errors.New("Error: not implemented yet.") 27 28 // ErrTimeout implies that a timeout has been triggered 29 var ErrTimeout = errors.New("Error: Call timed out.") 30 31 // ErrSeErrSearchIncomplete implies that a search type operation didnt 32 // find the expected node, but did find 'a' node. 33 var ErrSearchIncomplete = errors.New("Error: Search Incomplete.") 34 35 // ErrNotFound is returned when a search fails to find anything 36 var ErrNotFound = ds.ErrNotFound 37 38 // ErrNoSuchLogger is returned when the util pkg is asked for a non existant logger 39 var ErrNoSuchLogger = errors.New("Error: No such logger") 40 41 // TildeExpansion expands a filename, which may begin with a tilde. 42 func TildeExpansion(filename string) (string, error) { 43 return homedir.Expand(filename) 44 } 45 46 // ErrCast is returned when a cast fails AND the program should not panic. 47 func ErrCast() error { 48 debug.PrintStack() 49 return errCast 50 } 51 52 var errCast = errors.New("cast error") 53 54 // ExpandPathnames takes a set of paths and turns them into absolute paths 55 func ExpandPathnames(paths []string) ([]string, error) { 56 var out []string 57 for _, p := range paths { 58 abspath, err := filepath.Abs(p) 59 if err != nil { 60 return nil, err 61 } 62 out = append(out, abspath) 63 } 64 return out, nil 65 } 66 67 type randGen struct { 68 rand.Rand 69 } 70 71 func NewTimeSeededRand() io.Reader { 72 src := rand.NewSource(time.Now().UnixNano()) 73 return &randGen{ 74 Rand: *rand.New(src), 75 } 76 } 77 78 func NewSeededRand(seed int64) io.Reader { 79 src := rand.NewSource(seed) 80 return &randGen{ 81 Rand: *rand.New(src), 82 } 83 } 84 85 func (r *randGen) Read(p []byte) (n int, err error) { 86 for i := 0; i < len(p); i++ { 87 p[i] = byte(r.Rand.Intn(255)) 88 } 89 return len(p), nil 90 } 91 92 // GetenvBool is the way to check an env var as a boolean 93 func GetenvBool(name string) bool { 94 v := strings.ToLower(os.Getenv(name)) 95 return v == "true" || v == "t" || v == "1" 96 } 97 98 // MultiErr is a util to return multiple errors 99 type MultiErr []error 100 101 func (m MultiErr) Error() string { 102 if len(m) == 0 { 103 return "no errors" 104 } 105 106 s := "Multiple errors: " 107 for i, e := range m { 108 if i != 0 { 109 s += ", " 110 } 111 s += e.Error() 112 } 113 return s 114 } 115 116 func Partition(subject string, sep string) (string, string, string) { 117 if i := strings.Index(subject, sep); i != -1 { 118 return subject[:i], subject[i : i+len(sep)], subject[i+len(sep):] 119 } 120 return subject, "", "" 121 } 122 123 func RPartition(subject string, sep string) (string, string, string) { 124 if i := strings.LastIndex(subject, sep); i != -1 { 125 return subject[:i], subject[i : i+len(sep)], subject[i+len(sep):] 126 } 127 return subject, "", "" 128 } 129 130 // Hash is the global IPFS hash function. uses multihash SHA2_256, 256 bits 131 func Hash(data []byte) mh.Multihash { 132 h, err := mh.Sum(data, mh.SHA2_256, -1) 133 if err != nil { 134 // this error can be safely ignored (panic) because multihash only fails 135 // from the selection of hash function. If the fn + length are valid, it 136 // won't error. 137 panic("multihash failed to hash using SHA2_256.") 138 } 139 return h 140 } 141 142 // IsValidHash checks whether a given hash is valid (b58 decodable, len > 0) 143 func IsValidHash(s string) bool { 144 out := b58.Decode(s) 145 if out == nil || len(out) == 0 { 146 return false 147 } 148 _, err := mh.Cast(out) 149 if err != nil { 150 return false 151 } 152 return true 153 } 154 155 // XOR takes two byte slices, XORs them together, returns the resulting slice. 156 func XOR(a, b []byte) []byte { 157 c := make([]byte, len(a)) 158 for i := 0; i < len(a); i++ { 159 c[i] = a[i] ^ b[i] 160 } 161 return c 162 }