github.com/sujit-baniya/log@v1.0.73/xid.go (about)

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