snowflake.go 8.9 KB

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