github.com/phuslu/log@v1.0.100/xid.go (about) 1 package log 2 3 import ( 4 "sync/atomic" 5 "time" 6 ) 7 8 var counter = Fastrandn(4294967295) 9 10 // XID represents a unique request id 11 type XID [12]byte 12 13 var nilXID XID 14 15 // NewXID generates a globally unique XID 16 func NewXID() XID { 17 sec, _, _ := now() 18 return NewXIDWithTime(sec) 19 } 20 21 // NewXIDWithTime generates a globally unique XID with unix timestamp 22 func NewXIDWithTime(timestamp int64) (x XID) { 23 // timestamp 24 x[0] = byte(timestamp >> 24) 25 x[1] = byte(timestamp >> 16) 26 x[2] = byte(timestamp >> 8) 27 x[3] = byte(timestamp) 28 // machine 29 x[4] = machine[0] 30 x[5] = machine[1] 31 x[6] = machine[2] 32 // pid 33 x[7] = byte(pid >> 8) 34 x[8] = byte(pid) 35 // counter 36 i := atomic.AddUint32(&counter, 1) 37 x[9] = byte(i >> 16) 38 x[10] = byte(i >> 8) 39 x[11] = byte(i) 40 return 41 } 42 43 // Time returns the timestamp part of the id. 44 func (x XID) Time() time.Time { 45 return time.Unix(int64(x[0])<<32|int64(x[1])<<16|int64(x[2])<<8|int64(x[3]), 0) 46 } 47 48 // Machine returns the 3-byte machine id part of the id. 49 func (x XID) Machine() []byte { 50 return x[4:7] 51 } 52 53 // Pid returns the process id part of the id. 54 func (x XID) Pid() uint16 { 55 return uint16(x[7])<<8 | uint16(x[8]) 56 } 57 58 // Counter returns the incrementing value part of the id. 59 func (x XID) Counter() uint32 { 60 return uint32(x[9])<<16 | uint32(x[10])<<8 | uint32(x[11]) 61 } 62 63 const base32 = "0123456789abcdefghijklmnopqrstuv" 64 65 func (x XID) encode(dst []byte) { 66 dst[19] = base32[(x[11]<<4)&0x1F] 67 dst[18] = base32[(x[11]>>1)&0x1F] 68 dst[17] = base32[(x[11]>>6)&0x1F|(x[10]<<2)&0x1F] 69 dst[16] = base32[x[10]>>3] 70 dst[15] = base32[x[9]&0x1F] 71 dst[14] = base32[(x[9]>>5)|(x[8]<<3)&0x1F] 72 dst[13] = base32[(x[8]>>2)&0x1F] 73 dst[12] = base32[x[8]>>7|(x[7]<<1)&0x1F] 74 dst[11] = base32[(x[7]>>4)&0x1F|(x[6]<<4)&0x1F] 75 dst[10] = base32[(x[6]>>1)&0x1F] 76 dst[9] = base32[(x[6]>>6)&0x1F|(x[5]<<2)&0x1F] 77 dst[8] = base32[x[5]>>3] 78 dst[7] = base32[x[4]&0x1F] 79 dst[6] = base32[x[4]>>5|(x[3]<<3)&0x1F] 80 dst[5] = base32[(x[3]>>2)&0x1F] 81 dst[4] = base32[x[3]>>7|(x[2]<<1)&0x1F] 82 dst[3] = base32[(x[2]>>4)&0x1F|(x[1]<<4)&0x1F] 83 dst[2] = base32[(x[1]>>1)&0x1F] 84 dst[1] = base32[(x[1]>>6)&0x1F|(x[0]<<2)&0x1F] 85 dst[0] = base32[x[0]>>3] 86 } 87 88 // String returns a base32 hex lowercased representation of the id. 89 func (x XID) String() string { 90 dst := make([]byte, 20) 91 x.encode(dst) 92 return b2s(dst) 93 } 94 95 // MarshalText implements encoding/text TextMarshaler interface 96 func (x XID) MarshalText() (dst []byte, err error) { 97 dst = make([]byte, 20) 98 x.encode(dst) 99 return 100 } 101 102 // MarshalJSON implements encoding/json Marshaler interface 103 func (x XID) MarshalJSON() (dst []byte, err error) { 104 if x == nilXID { 105 dst = []byte("null") 106 } else { 107 dst = make([]byte, 22) 108 dst[0] = '"' 109 x.encode(dst[1:21]) 110 dst[21] = '"' 111 } 112 return 113 } 114 115 // UnmarshalText implements encoding/text TextUnmarshaler interface 116 func (x *XID) UnmarshalText(text []byte) (err error) { 117 *x, err = ParseXID(b2s(text)) 118 return 119 } 120 121 // UnmarshalJSON implements encoding/json Unmarshaler interface 122 func (x *XID) UnmarshalJSON(b []byte) (err error) { 123 if string(b) == "null" { 124 *x = nilXID 125 return 126 } 127 *x, err = ParseXID(b2s(b[1 : len(b)-1])) 128 return 129 } 130 131 const base32r = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 132 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 133 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 134 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff" + 135 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 136 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 137 "\xff\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18" + 138 "\x19\x1a\x1b\x1c\x1d\x1e\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 139 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 140 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 141 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 142 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 143 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 144 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 145 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 146 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" 147 148 type xidError string 149 150 func (e xidError) Error() string { return string(e) } 151 152 // ErrInvalidXID is returned when trying to parse an invalid XID 153 const ErrInvalidXID = xidError("xid: invalid XID") 154 155 // ParseXID parses an XID from its string representation 156 func ParseXID(s string) (x XID, err error) { 157 if len(s) != 20 { 158 err = ErrInvalidXID 159 return 160 } 161 _ = s[19] 162 for i := 0; i < 20; i++ { 163 if base32r[s[i]] == 0xff { 164 err = ErrInvalidXID 165 return 166 } 167 } 168 x[0] = base32r[s[0]]<<3 | base32r[s[1]]>>2 169 x[1] = base32r[s[1]]<<6 | base32r[s[2]]<<1 | base32r[s[3]]>>4 170 x[2] = base32r[s[3]]<<4 | base32r[s[4]]>>1 171 x[3] = base32r[s[4]]<<7 | base32r[s[5]]<<2 | base32r[s[6]]>>3 172 x[4] = base32r[s[6]]<<5 | base32r[s[7]] 173 x[5] = base32r[s[8]]<<3 | base32r[s[9]]>>2 174 x[6] = base32r[s[9]]<<6 | base32r[s[10]]<<1 | base32r[s[11]]>>4 175 x[7] = base32r[s[11]]<<4 | base32r[s[12]]>>1 176 x[8] = base32r[s[12]]<<7 | base32r[s[13]]<<2 | base32r[s[14]]>>3 177 x[9] = base32r[s[14]]<<5 | base32r[s[15]] 178 x[10] = base32r[s[16]]<<3 | base32r[s[17]]>>2 179 x[11] = base32r[s[17]]<<6 | base32r[s[18]]<<1 | base32r[s[19]]>>4 180 return 181 }