github.com/chain5j/chain5j-pkg@v1.0.7/uuid/snowflake/snowflake.go (about)

     1  // Package snowflake
     2  //
     3  // @author: xwc1125
     4  package snowflake
     5  
     6  import (
     7  	"encoding/base64"
     8  	"encoding/binary"
     9  	"errors"
    10  	"fmt"
    11  	"strconv"
    12  	"sync"
    13  	"time"
    14  )
    15  
    16  var (
    17  	// Epoch is set to the twitter snowflake epoch of Nov 04 2010 01:42:54 UTC in milliseconds
    18  	// You may customize this to set a different epoch for your application.
    19  	Epoch int64 = 1288834974657
    20  
    21  	// NodeBits holds the number of bits to use for Node
    22  	// Remember, you have a total 22 bits to share between Node/Step
    23  	NodeBits uint8 = 10
    24  
    25  	// StepBits holds the number of bits to use for Step
    26  	// Remember, you have a total 22 bits to share between IdWorker/Step
    27  	StepBits uint8 = 12
    28  
    29  	// DEPRECATED: the below four variables will be removed in a future release.
    30  	mu        sync.Mutex
    31  	nodeMax   int64 = -1 ^ (-1 << NodeBits)
    32  	nodeMask        = nodeMax << StepBits
    33  	stepMask  int64 = -1 ^ (-1 << StepBits)
    34  	timeShift       = NodeBits + StepBits
    35  	nodeShift       = StepBits
    36  )
    37  
    38  const encodeBase32Map = "ybndrfg8ejkmcpqxot1uwisza345h769"
    39  
    40  var decodeBase32Map [256]byte
    41  
    42  const encodeBase58Map = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
    43  
    44  var decodeBase58Map [256]byte
    45  
    46  // A JSONSyntaxError is returned from UnmarshalJSON if an invalid ID is provided.
    47  type JSONSyntaxError struct{ original []byte }
    48  
    49  func (j JSONSyntaxError) Error() string {
    50  	return fmt.Sprintf("invalid snowflake ID %q", string(j.original))
    51  }
    52  
    53  // ErrInvalidBase58 is returned by ParseBase58 when given an invalid []byte
    54  var ErrInvalidBase58 = errors.New("invalid base58")
    55  
    56  // ErrInvalidBase32 is returned by ParseBase32 when given an invalid []byte
    57  var ErrInvalidBase32 = errors.New("invalid base32")
    58  
    59  // Create maps for decoding Base58/Base32.
    60  // This speeds up the process tremendously.
    61  func init() {
    62  	for i := 0; i < len(encodeBase58Map); i++ {
    63  		decodeBase58Map[i] = 0xFF
    64  	}
    65  
    66  	for i := 0; i < len(encodeBase58Map); i++ {
    67  		decodeBase58Map[encodeBase58Map[i]] = byte(i)
    68  	}
    69  
    70  	for i := 0; i < len(encodeBase32Map); i++ {
    71  		decodeBase32Map[i] = 0xFF
    72  	}
    73  
    74  	for i := 0; i < len(encodeBase32Map); i++ {
    75  		decodeBase32Map[encodeBase32Map[i]] = byte(i)
    76  	}
    77  }
    78  
    79  // A IdWorker struct holds the basic information needed for a snowflake generator
    80  // node
    81  type IdWorker struct {
    82  	mu    sync.Mutex
    83  	epoch time.Time
    84  	time  int64
    85  	node  int64
    86  	step  int64
    87  
    88  	nodeMax   int64
    89  	nodeMask  int64
    90  	stepMask  int64
    91  	timeShift uint8
    92  	nodeShift uint8
    93  }
    94  
    95  // An ID is a custom type used for a snowflake ID.  This is used so we can
    96  // attach methods onto the ID.
    97  type ID int64
    98  
    99  // NewWorker returns a new snowflake node that can be used to generate snowflake
   100  // IDs
   101  func NewWorker(workId int64) (*IdWorker, error) {
   102  	// re-calc in case custom NodeBits or StepBits were set
   103  	// DEPRECATED: the below block will be removed in a future release.
   104  	mu.Lock()
   105  	nodeMax = -1 ^ (-1 << NodeBits)
   106  	nodeMask = nodeMax << StepBits
   107  	stepMask = -1 ^ (-1 << StepBits)
   108  	timeShift = NodeBits + StepBits
   109  	nodeShift = StepBits
   110  	mu.Unlock()
   111  
   112  	n := IdWorker{}
   113  	n.node = workId
   114  	n.nodeMax = -1 ^ (-1 << NodeBits)
   115  	n.nodeMask = n.nodeMax << StepBits
   116  	n.stepMask = -1 ^ (-1 << StepBits)
   117  	n.timeShift = NodeBits + StepBits
   118  	n.nodeShift = StepBits
   119  
   120  	if n.node < 0 || n.node > n.nodeMax {
   121  		return nil, errors.New("IdWorker number must be between 0 and " + strconv.FormatInt(n.nodeMax, 10))
   122  	}
   123  
   124  	var curTime = time.Now()
   125  	// add time.Duration to curTime to make sure we use the monotonic clock if available
   126  	n.epoch = curTime.Add(time.Unix(Epoch/1000, (Epoch%1000)*1000000).Sub(curTime))
   127  
   128  	return &n, nil
   129  }
   130  
   131  // Generate creates and returns a unique snowflake ID
   132  // To help guarantee uniqueness
   133  // - Make sure your system is keeping accurate system time
   134  // - Make sure you never have multiple nodes running with the same node ID
   135  func (n *IdWorker) Generate() ID {
   136  
   137  	n.mu.Lock()
   138  
   139  	now := time.Since(n.epoch).Nanoseconds() / 1000000
   140  
   141  	if now == n.time {
   142  		n.step = (n.step + 1) & n.stepMask
   143  
   144  		if n.step == 0 {
   145  			for now <= n.time {
   146  				now = time.Since(n.epoch).Nanoseconds() / 1000000
   147  			}
   148  		}
   149  	} else {
   150  		n.step = 0
   151  	}
   152  
   153  	n.time = now
   154  
   155  	r := ID((now)<<n.timeShift |
   156  		(n.node << n.nodeShift) |
   157  		(n.step),
   158  	)
   159  
   160  	n.mu.Unlock()
   161  	return r
   162  }
   163  
   164  // Int64 returns an int64 of the snowflake ID
   165  func (f ID) Int64() int64 {
   166  	return int64(f)
   167  }
   168  
   169  // ParseInt64 converts an int64 into a snowflake ID
   170  func ParseInt64(id int64) ID {
   171  	return ID(id)
   172  }
   173  
   174  // String returns a string of the snowflake ID
   175  func (f ID) String() string {
   176  	return strconv.FormatInt(int64(f), 10)
   177  }
   178  
   179  // ParseString converts a string into a snowflake ID
   180  func ParseString(id string) (ID, error) {
   181  	i, err := strconv.ParseInt(id, 10, 64)
   182  	return ID(i), err
   183  
   184  }
   185  
   186  // Base2 returns a string base2 of the snowflake ID
   187  func (f ID) Base2() string {
   188  	return strconv.FormatInt(int64(f), 2)
   189  }
   190  
   191  // ParseBase2 converts a Base2 string into a snowflake ID
   192  func ParseBase2(id string) (ID, error) {
   193  	i, err := strconv.ParseInt(id, 2, 64)
   194  	return ID(i), err
   195  }
   196  
   197  // Base32 uses the z-base-32 character set but encodes and decodes similar
   198  // to base58, allowing it to create an even smaller result string.
   199  // NOTE: There are many different base32 implementations so becareful when
   200  // doing any interoperation.
   201  func (f ID) Base32() string {
   202  
   203  	if f < 32 {
   204  		return string(encodeBase32Map[f])
   205  	}
   206  
   207  	b := make([]byte, 0, 12)
   208  	for f >= 32 {
   209  		b = append(b, encodeBase32Map[f%32])
   210  		f /= 32
   211  	}
   212  	b = append(b, encodeBase32Map[f])
   213  
   214  	for x, y := 0, len(b)-1; x < y; x, y = x+1, y-1 {
   215  		b[x], b[y] = b[y], b[x]
   216  	}
   217  
   218  	return string(b)
   219  }
   220  
   221  // ParseBase32 parses a base32 []byte into a snowflake ID
   222  // NOTE: There are many different base32 implementations so becareful when
   223  // doing any interoperation.
   224  func ParseBase32(b []byte) (ID, error) {
   225  
   226  	var id int64
   227  
   228  	for i := range b {
   229  		if decodeBase32Map[b[i]] == 0xFF {
   230  			return -1, ErrInvalidBase32
   231  		}
   232  		id = id*32 + int64(decodeBase32Map[b[i]])
   233  	}
   234  
   235  	return ID(id), nil
   236  }
   237  
   238  // Base36 returns a base36 string of the snowflake ID
   239  func (f ID) Base36() string {
   240  	return strconv.FormatInt(int64(f), 36)
   241  }
   242  
   243  // ParseBase36 converts a Base36 string into a snowflake ID
   244  func ParseBase36(id string) (ID, error) {
   245  	i, err := strconv.ParseInt(id, 36, 64)
   246  	return ID(i), err
   247  }
   248  
   249  // Base58 returns a base58 string of the snowflake ID
   250  func (f ID) Base58() string {
   251  
   252  	if f < 58 {
   253  		return string(encodeBase58Map[f])
   254  	}
   255  
   256  	b := make([]byte, 0, 11)
   257  	for f >= 58 {
   258  		b = append(b, encodeBase58Map[f%58])
   259  		f /= 58
   260  	}
   261  	b = append(b, encodeBase58Map[f])
   262  
   263  	for x, y := 0, len(b)-1; x < y; x, y = x+1, y-1 {
   264  		b[x], b[y] = b[y], b[x]
   265  	}
   266  
   267  	return string(b)
   268  }
   269  
   270  // ParseBase58 parses a base58 []byte into a snowflake ID
   271  func ParseBase58(b []byte) (ID, error) {
   272  
   273  	var id int64
   274  
   275  	for i := range b {
   276  		if decodeBase58Map[b[i]] == 0xFF {
   277  			return -1, ErrInvalidBase58
   278  		}
   279  		id = id*58 + int64(decodeBase58Map[b[i]])
   280  	}
   281  
   282  	return ID(id), nil
   283  }
   284  
   285  // Base64 returns a base64 string of the snowflake ID
   286  func (f ID) Base64() string {
   287  	return base64.StdEncoding.EncodeToString(f.Bytes())
   288  }
   289  
   290  // ParseBase64 converts a base64 string into a snowflake ID
   291  func ParseBase64(id string) (ID, error) {
   292  	b, err := base64.StdEncoding.DecodeString(id)
   293  	if err != nil {
   294  		return -1, err
   295  	}
   296  	return ParseBytes(b)
   297  
   298  }
   299  
   300  // Bytes returns a byte slice of the snowflake ID
   301  func (f ID) Bytes() []byte {
   302  	return []byte(f.String())
   303  }
   304  
   305  // ParseBytes converts a byte slice into a snowflake ID
   306  func ParseBytes(id []byte) (ID, error) {
   307  	i, err := strconv.ParseInt(string(id), 10, 64)
   308  	return ID(i), err
   309  }
   310  
   311  // IntBytes returns an array of bytes of the snowflake ID, encoded as a
   312  // big endian integer.
   313  func (f ID) IntBytes() [8]byte {
   314  	var b [8]byte
   315  	binary.BigEndian.PutUint64(b[:], uint64(f))
   316  	return b
   317  }
   318  
   319  // ParseIntBytes converts an array of bytes encoded as big endian integer as
   320  // a snowflake ID
   321  func ParseIntBytes(id [8]byte) ID {
   322  	return ID(int64(binary.BigEndian.Uint64(id[:])))
   323  }
   324  
   325  // Time returns an int64 unix timestamp in milliseconds of the snowflake ID time
   326  // DEPRECATED: the below function will be removed in a future release.
   327  func (f ID) Time() int64 {
   328  	return (int64(f) >> timeShift) + Epoch
   329  }
   330  
   331  // IdWorker returns an int64 of the snowflake ID node number
   332  // DEPRECATED: the below function will be removed in a future release.
   333  func (f ID) IdWorker() int64 {
   334  	return int64(f) & nodeMask >> nodeShift
   335  }
   336  
   337  // Step returns an int64 of the snowflake step (or sequence) number
   338  // DEPRECATED: the below function will be removed in a future release.
   339  func (f ID) Step() int64 {
   340  	return int64(f) & stepMask
   341  }
   342  
   343  // MarshalJSON returns a json byte array string of the snowflake ID.
   344  func (f ID) MarshalJSON() ([]byte, error) {
   345  	buff := make([]byte, 0, 22)
   346  	buff = append(buff, '"')
   347  	buff = strconv.AppendInt(buff, int64(f), 10)
   348  	buff = append(buff, '"')
   349  	return buff, nil
   350  }
   351  
   352  // UnmarshalJSON converts a json byte array of a snowflake ID into an ID type.
   353  func (f *ID) UnmarshalJSON(b []byte) error {
   354  	if len(b) < 3 || b[0] != '"' || b[len(b)-1] != '"' {
   355  		return JSONSyntaxError{b}
   356  	}
   357  
   358  	i, err := strconv.ParseInt(string(b[1:len(b)-1]), 10, 64)
   359  	if err != nil {
   360  		return err
   361  	}
   362  
   363  	*f = ID(i)
   364  	return nil
   365  }