github.com/oarkflow/log@v1.0.78/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 // NewID 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 NewID() ID { 373 return node.New() 374 }