github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/id/shortid/id.go (about)

     1  package shortid
     2  
     3  import (
     4  	"crypto/rand"
     5  	"errors"
     6  	"fmt"
     7  	"math"
     8  	"sync"
     9  	"sync/atomic"
    10  	"time"
    11  	"unsafe"
    12  
    13  	"github.com/angenalZZZ/gofunc/data/random"
    14  )
    15  
    16  // DefaultABC is the default URL-friendly alphabet.
    17  const DefaultABC = "0129abcCDEijImk4567lnuJKMvLwxFGHyzABpqNrOPtoQsRSUdYefTghVW38ZX"
    18  
    19  // Abc represents a shuffled alphabet used to generate the Ids and provides methods to
    20  // encode data.
    21  type Abc struct {
    22  	alphabet []rune
    23  }
    24  
    25  // Id type represents a short Id generator working with a given alphabet.
    26  type Id struct {
    27  	abc    Abc
    28  	worker uint
    29  	epoch  time.Time  // ids can be generated for 34 years since this date
    30  	ms     uint       // ms since epoch for the last id
    31  	count  uint       // request count within the same ms
    32  	mx     sync.Mutex // locks access to ms and count
    33  }
    34  
    35  var id *Id
    36  
    37  func init() {
    38  	id = MustNew(0, DefaultABC, 1)
    39  }
    40  
    41  // GetDefault retrieves the default short Id generator initialised with the default alphabet,
    42  // worker=0 and seed=1. The default can be overwritten using SetDefault.
    43  func GetDefault() *Id {
    44  	return (*Id)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&id))))
    45  }
    46  
    47  // SetDefault overwrites the default generator.
    48  func SetDefault(sid *Id) {
    49  	target := (*unsafe.Pointer)(unsafe.Pointer(&id))
    50  	source := unsafe.Pointer(sid)
    51  	atomic.SwapPointer(target, source)
    52  }
    53  
    54  // Generate generates an Id using the default generator.
    55  func Generate() (string, error) {
    56  	return id.Generate()
    57  }
    58  
    59  // MustGenerate acts just like Generate, but panics instead of returning errors.
    60  func MustGenerate() string {
    61  	id, err := Generate()
    62  	if err == nil {
    63  		return id
    64  	}
    65  	panic(err)
    66  }
    67  
    68  // New constructs an instance of the short Id generator for the given worker number [0,31], alphabet
    69  // (64 unique symbols) and seed value (to shuffle the alphabet). The worker number should be
    70  // different for multiple or distributed processes generating Ids into the same data space. The
    71  // seed, on contrary, should be identical.
    72  func New(worker uint8, alphabet string, seed uint64) (*Id, error) {
    73  	if worker > 31 {
    74  		return nil, errors.New("expected worker in the range [0,31]")
    75  	}
    76  	abc, err := NewAbc(alphabet, seed)
    77  	if err == nil {
    78  		sid := &Id{
    79  			abc:    abc,
    80  			worker: uint(worker),
    81  			epoch:  time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
    82  			ms:     0,
    83  			count:  0,
    84  		}
    85  		return sid, nil
    86  	}
    87  	return nil, err
    88  }
    89  
    90  // MustNew acts just like New, but panics instead of returning errors.
    91  func MustNew(worker uint8, alphabet string, seed uint64) *Id {
    92  	sid, err := New(worker, alphabet, seed)
    93  	if err == nil {
    94  		return sid
    95  	}
    96  	panic(err)
    97  }
    98  
    99  // Generate generates a new short Id.
   100  func (sid *Id) Generate() (string, error) {
   101  	return sid.GenerateInternal(nil, sid.epoch)
   102  }
   103  
   104  // MustGenerate acts just like Generate, but panics instead of returning errors.
   105  func (sid *Id) MustGenerate() string {
   106  	id, err := sid.Generate()
   107  	if err == nil {
   108  		return id
   109  	}
   110  	panic(err)
   111  }
   112  
   113  // GenerateInternal should only be used for testing purposes.
   114  func (sid *Id) GenerateInternal(tm *time.Time, epoch time.Time) (string, error) {
   115  	ms, count := sid.getMsAndCounter(tm, epoch)
   116  	ids := make([]rune, 9)
   117  	if tmp, err := sid.abc.Encode(ms, 8, 5); err == nil {
   118  		copy(ids, tmp) // first 8 symbols
   119  	} else {
   120  		return "", err
   121  	}
   122  	if tmp, err := sid.abc.Encode(sid.worker, 1, 5); err == nil {
   123  		ids[8] = tmp[0]
   124  	} else {
   125  		return "", err
   126  	}
   127  	if count > 0 {
   128  		if s, err := sid.abc.Encode(count, 0, 6); err == nil {
   129  			// only extend if really need it
   130  			ids = append(ids, s...)
   131  		} else {
   132  			return "", err
   133  		}
   134  	}
   135  	return string(ids), nil
   136  }
   137  
   138  func (sid *Id) getMsAndCounter(tm *time.Time, epoch time.Time) (uint, uint) {
   139  	sid.mx.Lock()
   140  	defer sid.mx.Unlock()
   141  	var ms uint
   142  	if tm != nil {
   143  		ms = uint(tm.Sub(epoch).Nanoseconds() / 1000000)
   144  	} else {
   145  		ms = uint(time.Now().Sub(epoch).Nanoseconds() / 1000000)
   146  	}
   147  	if ms == sid.ms {
   148  		sid.count++
   149  	} else {
   150  		sid.count = 0
   151  		sid.ms = ms
   152  	}
   153  	return sid.ms, sid.count
   154  }
   155  
   156  // String returns a string representation of the short Id generator.
   157  func (sid *Id) String() string {
   158  	return fmt.Sprintf("Id(worker=%v, epoch=%v, abc=%v)", sid.worker, sid.epoch, sid.abc)
   159  }
   160  
   161  // Abc returns the instance of alphabet used for representing the Ids.
   162  func (sid *Id) Abc() Abc {
   163  	return sid.abc
   164  }
   165  
   166  // Epoch returns the value of epoch used as the beginning of millisecond counting (normally
   167  // 2016-01-01 00:00:00 local time)
   168  func (sid *Id) Epoch() time.Time {
   169  	return sid.epoch
   170  }
   171  
   172  // Worker returns the value of worker for this short Id generator.
   173  func (sid *Id) Worker() uint {
   174  	return sid.worker
   175  }
   176  
   177  // NewAbc constructs a new instance of shuffled alphabet to be used for Id representation.
   178  func NewAbc(alphabet string, seed uint64) (Abc, error) {
   179  	runes := []rune(alphabet)
   180  	if len(runes) != len(DefaultABC) {
   181  		return Abc{}, fmt.Errorf("alphabet must contain %v unique characters", len(DefaultABC))
   182  	}
   183  	if nonUnique(runes) {
   184  		return Abc{}, errors.New("alphabet must contain unique characters only")
   185  	}
   186  	abc := Abc{alphabet: nil}
   187  	abc.shuffle(alphabet, seed)
   188  	return abc, nil
   189  }
   190  
   191  // MustNewAbc acts just like NewAbc, but panics instead of returning errors.
   192  func MustNewAbc(alphabet string, seed uint64) Abc {
   193  	res, err := NewAbc(alphabet, seed)
   194  	if err == nil {
   195  		return res
   196  	}
   197  	panic(err)
   198  }
   199  
   200  func nonUnique(runes []rune) bool {
   201  	found := make(map[rune]struct{})
   202  	for _, r := range runes {
   203  		if _, seen := found[r]; !seen {
   204  			found[r] = struct{}{}
   205  		}
   206  	}
   207  	return len(found) < len(runes)
   208  }
   209  
   210  func (abc *Abc) shuffle(alphabet string, seed uint64) {
   211  	source := []rune(alphabet)
   212  	for len(source) > 1 {
   213  		seed = (seed*9301 + 49297) % 233280
   214  		i := int(seed * uint64(len(source)) / 233280)
   215  
   216  		abc.alphabet = append(abc.alphabet, source[i])
   217  		source = append(source[:i], source[i+1:]...)
   218  	}
   219  	abc.alphabet = append(abc.alphabet, source[0])
   220  }
   221  
   222  // Encode encodes a given value into a slice of runes of length symbols. In case symbols==0, the
   223  // length of the result is automatically computed from data. Even if fewer symbols is required to
   224  // encode the data than symbols, all positions are used encoding 0 where required to guarantee
   225  // uniqueness in case further data is added to the sequence. The value of digits [4,6] represents
   226  // represents n in 2^n, which defines how much randomness flows into the algorithm: 4 -- every value
   227  // can be represented by 4 symbols in the alphabet (permitting at most 16 values), 5 -- every value
   228  // can be represented by 2 symbols in the alphabet (permitting at most 32 values), 6 -- every value
   229  // is represented by exactly 1 symbol with no randomness (permitting 64 values).
   230  func (abc *Abc) Encode(val, symbols, digits uint) ([]rune, error) {
   231  	if digits < 4 || 6 < digits {
   232  		return nil, fmt.Errorf("allowed digits range [4,6], found %v", digits)
   233  	}
   234  
   235  	var computedSize uint = 1
   236  	if val >= 1 {
   237  		computedSize = uint(math.Log2(float64(val)))/digits + 1
   238  	}
   239  	if symbols == 0 {
   240  		symbols = computedSize
   241  	} else if symbols < computedSize {
   242  		return nil, fmt.Errorf("cannot accommodate data, need %v digits, got %v", computedSize, symbols)
   243  	}
   244  
   245  	mask := 1<<digits - 1
   246  
   247  	rdm := make([]int, int(symbols))
   248  	// no random component if digits == 6
   249  	if digits < 6 {
   250  		copy(rdm, maskedRandomInt(len(rdm), 0x3f-mask))
   251  	}
   252  
   253  	res := make([]rune, int(symbols))
   254  	for i := range res {
   255  		shift := digits * uint(i)
   256  		index := (int(val>>shift) & mask) | rdm[i]
   257  		if 62 <= index {
   258  			index = random.R.Intn(60)
   259  		}
   260  		res[i] = abc.alphabet[index]
   261  	}
   262  	return res, nil
   263  }
   264  
   265  // MustEncode acts just like Encode, but panics instead of returning errors.
   266  func (abc *Abc) MustEncode(val, size, digits uint) []rune {
   267  	res, err := abc.Encode(val, size, digits)
   268  	if err == nil {
   269  		return res
   270  	}
   271  	panic(err)
   272  }
   273  
   274  func maskedRandomInt(size, mask int) []int {
   275  	s := make([]int, size)
   276  	bytes := make([]byte, size)
   277  	if _, err := rand.Read(bytes); err == nil {
   278  		for i, b := range bytes {
   279  			s[i] = int(b) & mask
   280  		}
   281  	} else {
   282  		for i := range s {
   283  			s[i] = random.R.Intn(0xff) & mask
   284  		}
   285  	}
   286  	return s
   287  }
   288  
   289  // String returns a string representation of the Abc instance.
   290  func (abc Abc) String() string {
   291  	return fmt.Sprintf("Abc{alphabet='%v')", abc.Alphabet())
   292  }
   293  
   294  // Alphabet returns the alphabet used as an immutable string.
   295  func (abc Abc) Alphabet() string {
   296  	return string(abc.alphabet)
   297  }