github.com/GuanceCloud/cliutils@v1.1.21/utils.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 package cliutils 7 8 import ( 9 "bytes" 10 "compress/gzip" 11 "crypto/aes" 12 "crypto/cipher" 13 14 // nolint:gosec 15 "crypto/md5" 16 crand "crypto/rand" 17 "encoding/hex" 18 "fmt" 19 "io" 20 "math" 21 mrand "math/rand" 22 "sync" 23 "time" 24 25 "github.com/rs/xid" 26 ) 27 28 type Sem struct { 29 sem chan interface{} 30 } 31 32 func NewSem() *Sem { 33 return &Sem{sem: make(chan interface{})} 34 } 35 36 func (s *Sem) Close() { 37 select { 38 case <-s.sem: 39 // pass: s.sem has been closed before 40 default: 41 close(s.sem) 42 } 43 } 44 45 func (s *Sem) Wait() <-chan interface{} { 46 return s.sem 47 } 48 49 func WgWait(wg *sync.WaitGroup, timeout int) { 50 c := make(chan interface{}) 51 52 go func() { 53 defer close(c) 54 wg.Wait() 55 }() 56 57 if timeout > 0 { 58 select { 59 case <-c: 60 case <-time.After(time.Second * time.Duration(timeout)): 61 } 62 } else { 63 <-c 64 } 65 } 66 67 var ( 68 letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 69 letterIdxBits = uint(6) //nolint:gomnd // 6 bits to represent a letter index 70 letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits 71 letterIdxMax = 63 / letterIdxBits //nolint:gomnd 72 ) 73 74 func CreateRandomString(n int) string { 75 src := mrand.NewSource(time.Now().UnixNano()) 76 77 b := make([]byte, n) 78 for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; { 79 if remain == 0 { 80 cache, remain = src.Int63(), letterIdxMax 81 } 82 if idx := int(cache & int64(letterIdxMask)); idx < len(letterBytes) { 83 b[i] = letterBytes[idx] 84 i-- 85 } 86 cache >>= letterIdxBits 87 remain-- 88 } 89 90 return string(b) 91 } 92 93 func XID(p string) string { 94 return p + xid.New().String() 95 } 96 97 func SizeFmt(n int64) string { 98 f := float64(n) 99 100 unit := []string{"", "K", "M", "G", "T", "P", "E", "Z"} 101 for _, u := range unit { 102 if math.Abs(f) < 1024.0 { //nolint:gomnd 103 return fmt.Sprintf("%3.4f%sB", f, u) 104 } 105 f /= 1024.0 //nolint:gomnd 106 } 107 return fmt.Sprintf("%3.4fYB", f) 108 } 109 110 func Md5Hash(data []byte) string { 111 hasher := md5.New() //nolint:gosec 112 if _, err := hasher.Write(data); err != nil { 113 panic(err) 114 } 115 116 return hex.EncodeToString(hasher.Sum(nil)) 117 } 118 119 func Encrypt(data, phrase []byte) ([]byte, error) { 120 md5Cipher := Md5Hash(phrase) 121 122 block, _ := aes.NewCipher([]byte(md5Cipher)) 123 gcm, err := cipher.NewGCM(block) 124 if err != nil { 125 return nil, err 126 } 127 128 nonce := make([]byte, gcm.NonceSize()) 129 if _, err = io.ReadFull(crand.Reader, nonce); err != nil { 130 return nil, err 131 } 132 return gcm.Seal(nonce, nonce, data, nil), nil 133 } 134 135 func Decrypt(endata, phrase []byte) ([]byte, error) { 136 md5Cipher := Md5Hash(phrase) 137 138 block, err := aes.NewCipher([]byte(md5Cipher)) 139 if err != nil { 140 return nil, err 141 } 142 143 gcm, err := cipher.NewGCM(block) 144 if err != nil { 145 return nil, err 146 } 147 148 nonceSize := gcm.NonceSize() 149 nonce, ciphertext := endata[:nonceSize], endata[nonceSize:] 150 plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) 151 if err != nil { 152 return nil, err 153 } 154 return plaintext, nil 155 } 156 157 func StringTrim(s string, n int) string { 158 if len(s) > n { 159 return fmt.Sprintf("%s...(%d trimmed)", s[:n], len(s)-n) 160 } else { 161 return s 162 } 163 } 164 165 func LeftStringTrim(s string, n int) string { 166 if len(s) > n { 167 pos := len(s) - n 168 return fmt.Sprintf("...%s(%d trimmed)", s[pos:], pos) 169 } else { 170 return s 171 } 172 } 173 174 func GZipStr(str string) ([]byte, error) { 175 var z bytes.Buffer 176 zw := gzip.NewWriter(&z) 177 if _, err := io.WriteString(zw, str); err != nil { 178 return nil, err 179 } 180 181 if err := zw.Flush(); err != nil { 182 return nil, err 183 } 184 185 if err := zw.Close(); err != nil { 186 return nil, err 187 } 188 return z.Bytes(), nil 189 } 190 191 func MustGZip(data []byte) []byte { 192 data, err := GZip(data) 193 if err != nil { 194 panic(err.Error()) 195 } 196 197 return data 198 } 199 200 func GZip(data []byte) ([]byte, error) { 201 var z bytes.Buffer 202 zw := gzip.NewWriter(&z) 203 204 if _, err := zw.Write(data); err != nil { 205 return nil, err 206 } 207 208 if err := zw.Flush(); err != nil { 209 return nil, err 210 } 211 212 if err := zw.Close(); err != nil { 213 return nil, err 214 } 215 return z.Bytes(), nil 216 }