uuid.go raw

   1  package uuid
   2  
   3  import (
   4  	"crypto/rand"
   5  	"encoding/hex"
   6  	"fmt"
   7  	"io"
   8  )
   9  
  10  // GenerateRandomBytes is used to generate random bytes of given size.
  11  func GenerateRandomBytes(size int) ([]byte, error) {
  12  	return GenerateRandomBytesWithReader(size, rand.Reader)
  13  }
  14  
  15  // GenerateRandomBytesWithReader is used to generate random bytes of given size read from a given reader.
  16  func GenerateRandomBytesWithReader(size int, reader io.Reader) ([]byte, error) {
  17  	if reader == nil {
  18  		return nil, fmt.Errorf("provided reader is nil")
  19  	}
  20  	buf := make([]byte, size)
  21  	if _, err := io.ReadFull(reader, buf); err != nil {
  22  		return nil, fmt.Errorf("failed to read random bytes: %v", err)
  23  	}
  24  	return buf, nil
  25  }
  26  
  27  
  28  const uuidLen = 16
  29  
  30  // GenerateUUID is used to generate a random UUID
  31  func GenerateUUID() (string, error) {
  32  	return GenerateUUIDWithReader(rand.Reader)
  33  }
  34  
  35  // GenerateUUIDWithReader is used to generate a random UUID with a given Reader
  36  func GenerateUUIDWithReader(reader io.Reader) (string, error) {
  37  	if reader == nil {
  38  		return "", fmt.Errorf("provided reader is nil")
  39  	}
  40  	buf, err := GenerateRandomBytesWithReader(uuidLen, reader)
  41  	if err != nil {
  42  		return "", err
  43  	}
  44  	return FormatUUID(buf)
  45  }
  46  
  47  func FormatUUID(buf []byte) (string, error) {
  48  	if buflen := len(buf); buflen != uuidLen {
  49  		return "", fmt.Errorf("wrong length byte slice (%d)", buflen)
  50  	}
  51  
  52  	return fmt.Sprintf("%x-%x-%x-%x-%x",
  53  		buf[0:4],
  54  		buf[4:6],
  55  		buf[6:8],
  56  		buf[8:10],
  57  		buf[10:16]), nil
  58  }
  59  
  60  func ParseUUID(uuid string) ([]byte, error) {
  61  	if len(uuid) != 2 * uuidLen + 4 {
  62  		return nil, fmt.Errorf("uuid string is wrong length")
  63  	}
  64  
  65  	if uuid[8] != '-' ||
  66  		uuid[13] != '-' ||
  67  		uuid[18] != '-' ||
  68  		uuid[23] != '-' {
  69  		return nil, fmt.Errorf("uuid is improperly formatted")
  70  	}
  71  
  72  	hexStr := uuid[0:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
  73  
  74  	ret, err := hex.DecodeString(hexStr)
  75  	if err != nil {
  76  		return nil, err
  77  	}
  78  	if len(ret) != uuidLen {
  79  		return nil, fmt.Errorf("decoded hex is the wrong length")
  80  	}
  81  
  82  	return ret, nil
  83  }
  84