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 }