// Copyright 2018 Google Inc.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package uuid

import (
	
	
	
	
	
	
	
	
)

// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID [16]byte

// A Version represents a UUID's version.
type Version byte

// A Variant represents a UUID's variant.
type Variant byte

// Constants returned by Variant.
const (
	Invalid   = Variant(iota) // Invalid UUID
	RFC4122                   // The variant specified in RFC4122
	Reserved                  // Reserved, NCS backward compatibility.
	Microsoft                 // Reserved, Microsoft Corporation backward compatibility.
	Future                    // Reserved for future definition.
)

const randPoolSize = 16 * 16

var (
	rander      = rand.Reader // random function
	poolEnabled = false
	poolMu      sync.Mutex
	poolPos     = randPoolSize     // protected with poolMu
	pool        [randPoolSize]byte // protected with poolMu
)

type invalidLengthError struct{ len int }

func ( invalidLengthError) () string {
	return fmt.Sprintf("invalid UUID length: %d", .len)
}

// IsInvalidLengthError is matcher function for custom error invalidLengthError
func ( error) bool {
	,  := .(invalidLengthError)
	return 
}

// Parse decodes s into a UUID or returns an error if it cannot be parsed.  Both
// the standard UUID forms defined in RFC 4122
// (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) are decoded.  In addition,
// Parse accepts non-standard strings such as the raw hex encoding
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and 38 byte "Microsoft style" encodings,
// e.g.  {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.  Only the middle 36 bytes are
// examined in the latter case.  Parse should not be used to validate strings as
// it parses non-standard encodings as indicated above.
func ( string) (UUID, error) {
	var  UUID
	switch len() {
	// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	case 36:

	// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	case 36 + 9:
		if !strings.EqualFold([:9], "urn:uuid:") {
			return , fmt.Errorf("invalid urn prefix: %q", [:9])
		}
		 = [9:]

	// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
	case 36 + 2:
		 = [1:]

	// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	case 32:
		var  bool
		for  := range  {
			[],  = xtob([*2], [*2+1])
			if ! {
				return , errors.New("invalid UUID format")
			}
		}
		return , nil
	default:
		return , invalidLengthError{len()}
	}
	// s is now at least 36 bytes long
	// it must be of the form  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	if [8] != '-' || [13] != '-' || [18] != '-' || [23] != '-' {
		return , errors.New("invalid UUID format")
	}
	for ,  := range [16]int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34,
	} {
		,  := xtob([], [+1])
		if ! {
			return , errors.New("invalid UUID format")
		}
		[] = 
	}
	return , nil
}

// ParseBytes is like Parse, except it parses a byte slice instead of a string.
func ( []byte) (UUID, error) {
	var  UUID
	switch len() {
	case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
		if !bytes.EqualFold([:9], []byte("urn:uuid:")) {
			return , fmt.Errorf("invalid urn prefix: %q", [:9])
		}
		 = [9:]
	case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
		 = [1:]
	case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
		var  bool
		for  := 0;  < 32;  += 2 {
			[/2],  = xtob([], [+1])
			if ! {
				return , errors.New("invalid UUID format")
			}
		}
		return , nil
	default:
		return , invalidLengthError{len()}
	}
	// s is now at least 36 bytes long
	// it must be of the form  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	if [8] != '-' || [13] != '-' || [18] != '-' || [23] != '-' {
		return , errors.New("invalid UUID format")
	}
	for ,  := range [16]int{
		0, 2, 4, 6,
		9, 11,
		14, 16,
		19, 21,
		24, 26, 28, 30, 32, 34,
	} {
		,  := xtob([], [+1])
		if ! {
			return , errors.New("invalid UUID format")
		}
		[] = 
	}
	return , nil
}

// MustParse is like Parse but panics if the string cannot be parsed.
// It simplifies safe initialization of global variables holding compiled UUIDs.
func ( string) UUID {
	,  := Parse()
	if  != nil {
		panic(`uuid: Parse(` +  + `): ` + .Error())
	}
	return 
}

// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
// does not have a length of 16. The bytes are copied from the slice.
func ( []byte) ( UUID,  error) {
	 = .UnmarshalBinary()
	return , 
}

// Must returns uuid if err is nil and panics otherwise.
func ( UUID,  error) UUID {
	if  != nil {
		panic()
	}
	return 
}

// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func ( UUID) () string {
	var  [36]byte
	encodeHex([:], )
	return string([:])
}

// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,  or "" if uuid is invalid.
func ( UUID) () string {
	var  [36 + 9]byte
	copy([:], "urn:uuid:")
	encodeHex([9:], )
	return string([:])
}

func encodeHex( []byte,  UUID) {
	hex.Encode(, [:4])
	[8] = '-'
	hex.Encode([9:13], [4:6])
	[13] = '-'
	hex.Encode([14:18], [6:8])
	[18] = '-'
	hex.Encode([19:23], [8:10])
	[23] = '-'
	hex.Encode([24:], [10:])
}

// Variant returns the variant encoded in uuid.
func ( UUID) () Variant {
	switch {
	case ([8] & 0xc0) == 0x80:
		return RFC4122
	case ([8] & 0xe0) == 0xc0:
		return Microsoft
	case ([8] & 0xe0) == 0xe0:
		return Future
	default:
		return Reserved
	}
}

// Version returns the version of uuid.
func ( UUID) () Version {
	return Version([6] >> 4)
}

func ( Version) () string {
	if  > 15 {
		return fmt.Sprintf("BAD_VERSION_%d", )
	}
	return fmt.Sprintf("VERSION_%d", )
}

func ( Variant) () string {
	switch  {
	case RFC4122:
		return "RFC4122"
	case Reserved:
		return "Reserved"
	case Microsoft:
		return "Microsoft"
	case Future:
		return "Future"
	case Invalid:
		return "Invalid"
	}
	return fmt.Sprintf("BadVariant%d", int())
}

// SetRand sets the random number generator to r, which implements io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func ( io.Reader) {
	if  == nil {
		rander = rand.Reader
		return
	}
	rander = 
}

// EnableRandPool enables internal randomness pool used for Random
// (Version 4) UUID generation. The pool contains random bytes read from
// the random number generator on demand in batches. Enabling the pool
// may improve the UUID generation throughput significantly.
//
// Since the pool is stored on the Go heap, this feature may be a bad fit
// for security sensitive applications.
//
// Both EnableRandPool and DisableRandPool are not thread-safe and should
// only be called when there is no possibility that New or any other
// UUID Version 4 generation function will be called concurrently.
func () {
	poolEnabled = true
}

// DisableRandPool disables the randomness pool if it was previously
// enabled with EnableRandPool.
//
// Both EnableRandPool and DisableRandPool are not thread-safe and should
// only be called when there is no possibility that New or any other
// UUID Version 4 generation function will be called concurrently.
func () {
	poolEnabled = false
	defer poolMu.Unlock()
	poolMu.Lock()
	poolPos = randPoolSize
}

// UUIDs is a slice of UUID types.
type UUIDs []UUID

// Strings returns a string slice containing the string form of each UUID in uuids.
func ( UUIDs) () []string {
	var  = make([]string, len())
	for ,  := range  {
		[] = .String()
	}
	return 
}