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  }