version4.go raw

   1  // Copyright 2016 Google Inc.  All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  package uuid
   6  
   7  import "io"
   8  
   9  // New creates a new random UUID or panics.  New is equivalent to
  10  // the expression
  11  //
  12  //    uuid.Must(uuid.NewRandom())
  13  func New() UUID {
  14  	return Must(NewRandom())
  15  }
  16  
  17  // NewString creates a new random UUID and returns it as a string or panics.
  18  // NewString is equivalent to the expression
  19  //
  20  //    uuid.New().String()
  21  func NewString() string {
  22  	return Must(NewRandom()).String()
  23  }
  24  
  25  // NewRandom returns a Random (Version 4) UUID.
  26  //
  27  // The strength of the UUIDs is based on the strength of the crypto/rand
  28  // package.
  29  //
  30  // Uses the randomness pool if it was enabled with EnableRandPool.
  31  //
  32  // A note about uniqueness derived from the UUID Wikipedia entry:
  33  //
  34  //  Randomly generated UUIDs have 122 random bits.  One's annual risk of being
  35  //  hit by a meteorite is estimated to be one chance in 17 billion, that
  36  //  means the probability is about 0.00000000006 (6 × 10−11),
  37  //  equivalent to the odds of creating a few tens of trillions of UUIDs in a
  38  //  year and having one duplicate.
  39  func NewRandom() (UUID, error) {
  40  	if !poolEnabled {
  41  		return NewRandomFromReader(rander)
  42  	}
  43  	return newRandomFromPool()
  44  }
  45  
  46  // NewRandomFromReader returns a UUID based on bytes read from a given io.Reader.
  47  func NewRandomFromReader(r io.Reader) (UUID, error) {
  48  	var uuid UUID
  49  	_, err := io.ReadFull(r, uuid[:])
  50  	if err != nil {
  51  		return Nil, err
  52  	}
  53  	uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
  54  	uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
  55  	return uuid, nil
  56  }
  57  
  58  func newRandomFromPool() (UUID, error) {
  59  	var uuid UUID
  60  	poolMu.Lock()
  61  	if poolPos == randPoolSize {
  62  		_, err := io.ReadFull(rander, pool[:])
  63  		if err != nil {
  64  			poolMu.Unlock()
  65  			return Nil, err
  66  		}
  67  		poolPos = 0
  68  	}
  69  	copy(uuid[:], pool[poolPos:(poolPos+16)])
  70  	poolPos += 16
  71  	poolMu.Unlock()
  72  
  73  	uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
  74  	uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
  75  	return uuid, nil
  76  }
  77