github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/id/shortid/id.go (about) 1 package shortid 2 3 import ( 4 "crypto/rand" 5 "errors" 6 "fmt" 7 "math" 8 "sync" 9 "sync/atomic" 10 "time" 11 "unsafe" 12 13 "github.com/angenalZZZ/gofunc/data/random" 14 ) 15 16 // DefaultABC is the default URL-friendly alphabet. 17 const DefaultABC = "0129abcCDEijImk4567lnuJKMvLwxFGHyzABpqNrOPtoQsRSUdYefTghVW38ZX" 18 19 // Abc represents a shuffled alphabet used to generate the Ids and provides methods to 20 // encode data. 21 type Abc struct { 22 alphabet []rune 23 } 24 25 // Id type represents a short Id generator working with a given alphabet. 26 type Id struct { 27 abc Abc 28 worker uint 29 epoch time.Time // ids can be generated for 34 years since this date 30 ms uint // ms since epoch for the last id 31 count uint // request count within the same ms 32 mx sync.Mutex // locks access to ms and count 33 } 34 35 var id *Id 36 37 func init() { 38 id = MustNew(0, DefaultABC, 1) 39 } 40 41 // GetDefault retrieves the default short Id generator initialised with the default alphabet, 42 // worker=0 and seed=1. The default can be overwritten using SetDefault. 43 func GetDefault() *Id { 44 return (*Id)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&id)))) 45 } 46 47 // SetDefault overwrites the default generator. 48 func SetDefault(sid *Id) { 49 target := (*unsafe.Pointer)(unsafe.Pointer(&id)) 50 source := unsafe.Pointer(sid) 51 atomic.SwapPointer(target, source) 52 } 53 54 // Generate generates an Id using the default generator. 55 func Generate() (string, error) { 56 return id.Generate() 57 } 58 59 // MustGenerate acts just like Generate, but panics instead of returning errors. 60 func MustGenerate() string { 61 id, err := Generate() 62 if err == nil { 63 return id 64 } 65 panic(err) 66 } 67 68 // New constructs an instance of the short Id generator for the given worker number [0,31], alphabet 69 // (64 unique symbols) and seed value (to shuffle the alphabet). The worker number should be 70 // different for multiple or distributed processes generating Ids into the same data space. The 71 // seed, on contrary, should be identical. 72 func New(worker uint8, alphabet string, seed uint64) (*Id, error) { 73 if worker > 31 { 74 return nil, errors.New("expected worker in the range [0,31]") 75 } 76 abc, err := NewAbc(alphabet, seed) 77 if err == nil { 78 sid := &Id{ 79 abc: abc, 80 worker: uint(worker), 81 epoch: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC), 82 ms: 0, 83 count: 0, 84 } 85 return sid, nil 86 } 87 return nil, err 88 } 89 90 // MustNew acts just like New, but panics instead of returning errors. 91 func MustNew(worker uint8, alphabet string, seed uint64) *Id { 92 sid, err := New(worker, alphabet, seed) 93 if err == nil { 94 return sid 95 } 96 panic(err) 97 } 98 99 // Generate generates a new short Id. 100 func (sid *Id) Generate() (string, error) { 101 return sid.GenerateInternal(nil, sid.epoch) 102 } 103 104 // MustGenerate acts just like Generate, but panics instead of returning errors. 105 func (sid *Id) MustGenerate() string { 106 id, err := sid.Generate() 107 if err == nil { 108 return id 109 } 110 panic(err) 111 } 112 113 // GenerateInternal should only be used for testing purposes. 114 func (sid *Id) GenerateInternal(tm *time.Time, epoch time.Time) (string, error) { 115 ms, count := sid.getMsAndCounter(tm, epoch) 116 ids := make([]rune, 9) 117 if tmp, err := sid.abc.Encode(ms, 8, 5); err == nil { 118 copy(ids, tmp) // first 8 symbols 119 } else { 120 return "", err 121 } 122 if tmp, err := sid.abc.Encode(sid.worker, 1, 5); err == nil { 123 ids[8] = tmp[0] 124 } else { 125 return "", err 126 } 127 if count > 0 { 128 if s, err := sid.abc.Encode(count, 0, 6); err == nil { 129 // only extend if really need it 130 ids = append(ids, s...) 131 } else { 132 return "", err 133 } 134 } 135 return string(ids), nil 136 } 137 138 func (sid *Id) getMsAndCounter(tm *time.Time, epoch time.Time) (uint, uint) { 139 sid.mx.Lock() 140 defer sid.mx.Unlock() 141 var ms uint 142 if tm != nil { 143 ms = uint(tm.Sub(epoch).Nanoseconds() / 1000000) 144 } else { 145 ms = uint(time.Now().Sub(epoch).Nanoseconds() / 1000000) 146 } 147 if ms == sid.ms { 148 sid.count++ 149 } else { 150 sid.count = 0 151 sid.ms = ms 152 } 153 return sid.ms, sid.count 154 } 155 156 // String returns a string representation of the short Id generator. 157 func (sid *Id) String() string { 158 return fmt.Sprintf("Id(worker=%v, epoch=%v, abc=%v)", sid.worker, sid.epoch, sid.abc) 159 } 160 161 // Abc returns the instance of alphabet used for representing the Ids. 162 func (sid *Id) Abc() Abc { 163 return sid.abc 164 } 165 166 // Epoch returns the value of epoch used as the beginning of millisecond counting (normally 167 // 2016-01-01 00:00:00 local time) 168 func (sid *Id) Epoch() time.Time { 169 return sid.epoch 170 } 171 172 // Worker returns the value of worker for this short Id generator. 173 func (sid *Id) Worker() uint { 174 return sid.worker 175 } 176 177 // NewAbc constructs a new instance of shuffled alphabet to be used for Id representation. 178 func NewAbc(alphabet string, seed uint64) (Abc, error) { 179 runes := []rune(alphabet) 180 if len(runes) != len(DefaultABC) { 181 return Abc{}, fmt.Errorf("alphabet must contain %v unique characters", len(DefaultABC)) 182 } 183 if nonUnique(runes) { 184 return Abc{}, errors.New("alphabet must contain unique characters only") 185 } 186 abc := Abc{alphabet: nil} 187 abc.shuffle(alphabet, seed) 188 return abc, nil 189 } 190 191 // MustNewAbc acts just like NewAbc, but panics instead of returning errors. 192 func MustNewAbc(alphabet string, seed uint64) Abc { 193 res, err := NewAbc(alphabet, seed) 194 if err == nil { 195 return res 196 } 197 panic(err) 198 } 199 200 func nonUnique(runes []rune) bool { 201 found := make(map[rune]struct{}) 202 for _, r := range runes { 203 if _, seen := found[r]; !seen { 204 found[r] = struct{}{} 205 } 206 } 207 return len(found) < len(runes) 208 } 209 210 func (abc *Abc) shuffle(alphabet string, seed uint64) { 211 source := []rune(alphabet) 212 for len(source) > 1 { 213 seed = (seed*9301 + 49297) % 233280 214 i := int(seed * uint64(len(source)) / 233280) 215 216 abc.alphabet = append(abc.alphabet, source[i]) 217 source = append(source[:i], source[i+1:]...) 218 } 219 abc.alphabet = append(abc.alphabet, source[0]) 220 } 221 222 // Encode encodes a given value into a slice of runes of length symbols. In case symbols==0, the 223 // length of the result is automatically computed from data. Even if fewer symbols is required to 224 // encode the data than symbols, all positions are used encoding 0 where required to guarantee 225 // uniqueness in case further data is added to the sequence. The value of digits [4,6] represents 226 // represents n in 2^n, which defines how much randomness flows into the algorithm: 4 -- every value 227 // can be represented by 4 symbols in the alphabet (permitting at most 16 values), 5 -- every value 228 // can be represented by 2 symbols in the alphabet (permitting at most 32 values), 6 -- every value 229 // is represented by exactly 1 symbol with no randomness (permitting 64 values). 230 func (abc *Abc) Encode(val, symbols, digits uint) ([]rune, error) { 231 if digits < 4 || 6 < digits { 232 return nil, fmt.Errorf("allowed digits range [4,6], found %v", digits) 233 } 234 235 var computedSize uint = 1 236 if val >= 1 { 237 computedSize = uint(math.Log2(float64(val)))/digits + 1 238 } 239 if symbols == 0 { 240 symbols = computedSize 241 } else if symbols < computedSize { 242 return nil, fmt.Errorf("cannot accommodate data, need %v digits, got %v", computedSize, symbols) 243 } 244 245 mask := 1<<digits - 1 246 247 rdm := make([]int, int(symbols)) 248 // no random component if digits == 6 249 if digits < 6 { 250 copy(rdm, maskedRandomInt(len(rdm), 0x3f-mask)) 251 } 252 253 res := make([]rune, int(symbols)) 254 for i := range res { 255 shift := digits * uint(i) 256 index := (int(val>>shift) & mask) | rdm[i] 257 if 62 <= index { 258 index = random.R.Intn(60) 259 } 260 res[i] = abc.alphabet[index] 261 } 262 return res, nil 263 } 264 265 // MustEncode acts just like Encode, but panics instead of returning errors. 266 func (abc *Abc) MustEncode(val, size, digits uint) []rune { 267 res, err := abc.Encode(val, size, digits) 268 if err == nil { 269 return res 270 } 271 panic(err) 272 } 273 274 func maskedRandomInt(size, mask int) []int { 275 s := make([]int, size) 276 bytes := make([]byte, size) 277 if _, err := rand.Read(bytes); err == nil { 278 for i, b := range bytes { 279 s[i] = int(b) & mask 280 } 281 } else { 282 for i := range s { 283 s[i] = random.R.Intn(0xff) & mask 284 } 285 } 286 return s 287 } 288 289 // String returns a string representation of the Abc instance. 290 func (abc Abc) String() string { 291 return fmt.Sprintf("Abc{alphabet='%v')", abc.Alphabet()) 292 } 293 294 // Alphabet returns the alphabet used as an immutable string. 295 func (abc Abc) Alphabet() string { 296 return string(abc.alphabet) 297 }