go.temporal.io/server@v1.23.0/common/primitives/uuid.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package primitives
    26  
    27  import (
    28  	"database/sql/driver"
    29  	"encoding/hex"
    30  
    31  	guuid "github.com/google/uuid"
    32  	"github.com/pborman/uuid"
    33  )
    34  
    35  // UUID represents a 16-byte universally unique identifier
    36  // this type is a wrapper around google/uuid with the following differences
    37  //   - type is a byte slice instead of [16]byte
    38  //   - db serialization converts uuid to bytes as opposed to string
    39  type UUID []byte
    40  
    41  // MustParseUUID returns a UUID parsed from the given string representation
    42  // returns nil if the input is empty string
    43  // panics if the given input is malformed
    44  func MustParseUUID(s string) UUID {
    45  	if s == "" {
    46  		return nil
    47  	}
    48  	u := guuid.MustParse(s)
    49  	return u[:]
    50  }
    51  
    52  // ParseUUID returns a UUID parsed from the given string representation
    53  // returns:
    54  //   - nil if the input is empty string
    55  //   - error if input is malformed
    56  //   - UUID object if input can be parsed and is valid
    57  func ParseUUID(s string) (UUID, error) {
    58  	if s == "" {
    59  		return nil, nil
    60  	}
    61  	u, err := guuid.Parse(s)
    62  
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	return u[:], nil
    67  }
    68  
    69  // MustValidateUUID parses and validates UUID contents from the given string representation
    70  // returns empty string if the input is empty string
    71  // panics if the given input is malformed
    72  func MustValidateUUID(s string) string {
    73  	MustParseUUID(s)
    74  	return s
    75  }
    76  
    77  // ValidateUUID parses and validates UUID contents from the given string representation
    78  // returns:
    79  //   - nil if the input is empty string
    80  //   - error if input is malformed
    81  //   - input if input can be parsed and is valid
    82  func ValidateUUID(s string) (string, error) {
    83  	if s == "" {
    84  		return "", nil
    85  	}
    86  	_, err := guuid.Parse(s)
    87  	if err != nil {
    88  		return "", err
    89  	}
    90  
    91  	return s, nil
    92  }
    93  
    94  // NewUUID generates a new random UUID
    95  func NewUUID() UUID {
    96  	return UUID(uuid.NewRandom())
    97  }
    98  
    99  // Downcast returns the UUID as a byte slice. This is necessary when passing to type sensitive interfaces such as cql.
   100  func (u UUID) Downcast() []byte {
   101  	return u
   102  }
   103  
   104  // UUIDPtr simply returns a pointer for the given value type
   105  func UUIDPtr(u UUID) *UUID {
   106  	return &u
   107  }
   108  
   109  // String returns the 36 byte hexstring representation of this uuid
   110  // return empty string if this uuid is nil
   111  func (u UUID) String() string {
   112  	if len(u) != 16 {
   113  		return ""
   114  	}
   115  	var buf [36]byte
   116  	u.encodeHex(buf[:])
   117  	return string(buf[:])
   118  }
   119  
   120  // StringPtr returns a pointer to the 36 byte hexstring representation of this uuid
   121  // return empty string if this uuid is nil
   122  func (u UUID) StringPtr() *string {
   123  	if len(u) != 16 {
   124  		return stringPtr("")
   125  	}
   126  	var buf [36]byte
   127  	u.encodeHex(buf[:])
   128  	return stringPtr(string(buf[:]))
   129  }
   130  
   131  func UUIDString(b []byte) string {
   132  	return UUID(b).String()
   133  }
   134  
   135  func stringPtr(v string) *string {
   136  	return &v
   137  }
   138  
   139  // Scan implements sql.Scanner interface to allow this type to be
   140  // parsed transparently by database drivers
   141  func (u *UUID) Scan(src interface{}) error {
   142  	if src == nil {
   143  		return nil
   144  	}
   145  	guuid := &guuid.UUID{}
   146  	if err := guuid.Scan(src); err != nil {
   147  		return err
   148  	}
   149  	*u = (*guuid)[:]
   150  	return nil
   151  }
   152  
   153  // Value implements sql.Valuer so that UUIDs can be written to databases
   154  // transparently. This method returns a byte slice representation of uuid
   155  func (u UUID) Value() (driver.Value, error) {
   156  	return []byte(u), nil
   157  }
   158  
   159  func (u UUID) encodeHex(dst []byte) {
   160  	hex.Encode(dst, u[:4])
   161  	dst[8] = '-'
   162  	hex.Encode(dst[9:13], u[4:6])
   163  	dst[13] = '-'
   164  	hex.Encode(dst[14:18], u[6:8])
   165  	dst[18] = '-'
   166  	hex.Encode(dst[19:23], u[8:10])
   167  	dst[23] = '-'
   168  	hex.Encode(dst[24:], u[10:])
   169  }