amuz.es/src/infra/goutils@v0.1.3/misc/uuid.go (about)

     1  package misc
     2  
     3  import (
     4  	"bytes"
     5  	"database/sql/driver"
     6  	"encoding/hex"
     7  	"errors"
     8  	"github.com/NebulousLabs/fastrand"
     9  	"fmt"
    10  )
    11  
    12  type UUID [16]byte
    13  
    14  func (u UUID) Marshal() ([]byte, error) {
    15  	return u[:], nil
    16  }
    17  
    18  func (u UUID) MarshalTo(buf []byte) (n int, err error) {
    19  	if len(u) == 0 {
    20  		return 0, nil
    21  	}
    22  	copy(buf, u[:])
    23  	return len(u), nil
    24  }
    25  func (u *UUID) Unmarshal(buf []byte) error {
    26  	if len(buf) != 16 {
    27  		return fmt.Errorf("invalid UUID (got %d bytes)", len(buf))
    28  	}
    29  	copy(u[:], buf)
    30  	return nil
    31  }
    32  
    33  func (u UUID) Compare(other UUID) int {
    34  	return bytes.Compare(u[:], other[:])
    35  }
    36  
    37  func (u UUID) Equal(other UUID) bool {
    38  	return u.Compare(other) == 0
    39  }
    40  func (u *UUID) UnmarshalJSON(from []byte) error {
    41  	quote := []byte("\"")
    42  	quoteSize := len(quote)
    43  
    44  	if len(from) < quoteSize*2 {
    45  		return errors.New("invalid quote notation")
    46  	}
    47  
    48  	if !bytes.HasPrefix(from, quote) || !bytes.HasSuffix(from, quote) {
    49  		return errors.New("invalid quote notation")
    50  	} else if err := u.Unmarshal(from[quoteSize:len(from)-quoteSize]); err != nil {
    51  		return err
    52  	}
    53  	return nil
    54  }
    55  
    56  func (u UUID) MarshalJSON() ([]byte, error) {
    57  	var buffer bytes.Buffer
    58  	buffer.WriteRune('"')
    59  	buffer.WriteString(hex.EncodeToString(u[:]))
    60  	buffer.WriteRune('"')
    61  	return buffer.Bytes(), nil
    62  }
    63  
    64  func (u *UUID) Size() int {
    65  	if u == nil {
    66  		return 0
    67  	}
    68  	if len(*u) == 0 {
    69  		return 0
    70  	}
    71  	return 16
    72  }
    73  
    74  func NewUUID() (u UUID) {
    75  	newObj := UUID{}
    76  	newObj.Random()
    77  	return newObj
    78  }
    79  
    80  func (u *UUID) UUIDFromHexString(buf []byte) (error) {
    81  	hexBuf := make([]byte, hex.DecodedLen(len(buf)))
    82  	if _, err := hex.Decode(hexBuf, buf); err != nil {
    83  		return err
    84  	} else if err := u.Unmarshal(hexBuf); err != nil {
    85  		return err
    86  	}
    87  	return nil
    88  }
    89  
    90  func (u UUID) ToHexString() (string) {
    91  	return hex.EncodeToString(u[:])
    92  }
    93  
    94  // Scan implements the Scanner interface.
    95  func (u *UUID) Scan(src interface{}) error {
    96  	if src == nil {
    97  		return nil
    98  	}
    99  
   100  	b, ok := src.([]byte)
   101  	if !ok {
   102  		return errors.New("Scan source was not []bytes")
   103  	}
   104  
   105  	u.UUIDFromHexString(b)
   106  	return nil
   107  }
   108  
   109  // Value implements the driver Valuer interface.
   110  func (u UUID) Value() (driver.Value, error) {
   111  	return u.ToHexString(), nil
   112  }
   113  
   114  func (u UUID) Random() {
   115  	fastrand.Read(u[:])
   116  	u[6] = (u[6] & 0x0f) | 0x40 // Version 4
   117  	u[8] = (u[8] & 0x3f) | 0x80 // Variant is 10
   118  }