string.go raw

   1  /*
   2   * Copyright 2017 Baidu, Inc.
   3   *
   4   * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
   5   * except in compliance with the License. You may obtain a copy of the License at
   6   *
   7   * http://www.apache.org/licenses/LICENSE-2.0
   8   *
   9   * Unless required by applicable law or agreed to in writing, software distributed under the
  10   * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  11   * either express or implied. See the License for the specific language governing permissions
  12   * and limitations under the License.
  13   */
  14  
  15  // string.go - define the string util function
  16  
  17  // Package util defines the common utilities including string and time.
  18  package util
  19  
  20  import (
  21  	"bytes"
  22  	"crypto/hmac"
  23  	"crypto/md5"
  24  	"crypto/rand"
  25  	"crypto/sha256"
  26  	"encoding/base64"
  27  	"encoding/hex"
  28  	"fmt"
  29  	"hash/crc32"
  30  	"io"
  31  	"os"
  32  	"strconv"
  33  )
  34  
  35  func HmacSha256Hex(key, str_to_sign string) string {
  36  	hasher := hmac.New(sha256.New, []byte(key))
  37  	hasher.Write([]byte(str_to_sign))
  38  	return hex.EncodeToString(hasher.Sum(nil))
  39  }
  40  
  41  func CalculateContentMD5(data io.Reader, size int64) (string, error) {
  42  	hasher := md5.New()
  43  	n, err := io.CopyN(hasher, data, size)
  44  	if err != nil {
  45  		return "", fmt.Errorf("calculate content-md5 occurs error: %v", err)
  46  	}
  47  	if n != size {
  48  		return "", fmt.Errorf("calculate content-md5 writing size %d != size %d", n, size)
  49  	}
  50  	return base64.StdEncoding.EncodeToString(hasher.Sum(nil)), nil
  51  }
  52  
  53  func CalculateContentCrc32c(data io.Reader, size int64) (string, error) {
  54  	castagnoliTable := crc32.MakeTable(crc32.Castagnoli)
  55  	hashCrc32c := crc32.New(castagnoliTable)
  56  	n, err := io.CopyN(hashCrc32c, data, size)
  57  	if err != nil {
  58  		return "", fmt.Errorf("calculate content-crc32c occurs error: %w", err)
  59  	}
  60  	if n != size {
  61  		return "", fmt.Errorf("calculate content-crc32c writing size %d != size %d", n, size)
  62  	}
  63  	return strconv.FormatUint(uint64(hashCrc32c.Sum32()), 10), nil
  64  }
  65  
  66  func CalculateContentCrc32cFromStream(reader io.Reader) (string, error) {
  67  	var buf bytes.Buffer
  68  	rdLen, err := io.Copy(&buf, reader)
  69  	if err != nil {
  70  		return "", err
  71  	}
  72  	if rdLen != int64(buf.Len()) {
  73  		return "", fmt.Errorf("unexpected reader")
  74  	}
  75  	return CalculateContentCrc32c(bytes.NewBuffer(buf.Bytes()), rdLen)
  76  }
  77  
  78  func CalculateContentCrc32cFromFile(fileName string) (string, error) {
  79  	file, err := os.Open(fileName)
  80  	if err != nil {
  81  		return "", err
  82  	}
  83  	defer file.Close()
  84  	fileInfo, infoErr := file.Stat()
  85  	if infoErr != nil {
  86  		return "", infoErr
  87  	}
  88  	return CalculateContentCrc32c(file, fileInfo.Size())
  89  }
  90  
  91  func UriEncode(uri string, encodeSlash bool) string {
  92  	var byte_buf bytes.Buffer
  93  	for _, b := range []byte(uri) {
  94  		if (b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z') || (b >= '0' && b <= '9') ||
  95  			b == '-' || b == '_' || b == '.' || b == '~' || (b == '/' && !encodeSlash) {
  96  			byte_buf.WriteByte(b)
  97  		} else {
  98  			byte_buf.WriteString(fmt.Sprintf("%%%02X", b))
  99  		}
 100  	}
 101  	return byte_buf.String()
 102  }
 103  
 104  func NewUUID() string {
 105  	var buf [16]byte
 106  	for {
 107  		if _, err := rand.Read(buf[:]); err == nil {
 108  			break
 109  		}
 110  	}
 111  	buf[6] = (buf[6] & 0x0f) | (4 << 4)
 112  	buf[8] = (buf[8] & 0xbf) | 0x80
 113  
 114  	res := make([]byte, 36)
 115  	hex.Encode(res[0:8], buf[0:4])
 116  	res[8] = '-'
 117  	hex.Encode(res[9:13], buf[4:6])
 118  	res[13] = '-'
 119  	hex.Encode(res[14:18], buf[6:8])
 120  	res[18] = '-'
 121  	hex.Encode(res[19:23], buf[8:10])
 122  	res[23] = '-'
 123  	hex.Encode(res[24:], buf[10:])
 124  	return string(res)
 125  }
 126  
 127  func NewRequestId() string {
 128  	return NewUUID()
 129  }
 130