// Copyright 2016 The Oklog Authors// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.package ulidimport ()/*An ULID is a 16 byte Universally Unique Lexicographically Sortable Identifier The components are encoded as 16 octets. Each component is encoded with the MSB first (network byte order). 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 32_bit_uint_time_high | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 16_bit_uint_time_low | 16_bit_uint_random | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 32_bit_uint_random | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 32_bit_uint_random | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/typeULID [16]bytevar (// ErrDataSize is returned when parsing or unmarshaling ULIDs with the wrong // data size.ErrDataSize = errors.New("ulid: bad data size when unmarshaling")// ErrInvalidCharacters is returned when parsing or unmarshaling ULIDs with // invalid Base32 encodings.ErrInvalidCharacters = errors.New("ulid: bad data characters when unmarshaling")// ErrBufferSize is returned when marshalling ULIDs to a buffer of insufficient // size.ErrBufferSize = errors.New("ulid: bad buffer size when marshaling")// ErrBigTime is returned when constructing an ULID with a time that is larger // than MaxTime.ErrBigTime = errors.New("ulid: time too big")// ErrOverflow is returned when unmarshaling a ULID whose first character is // larger than 7, thereby exceeding the valid bit depth of 128.ErrOverflow = errors.New("ulid: overflow when unmarshaling")// ErrMonotonicOverflow is returned by a Monotonic entropy source when // incrementing the previous ULID's entropy bytes would result in overflow.ErrMonotonicOverflow = errors.New("ulid: monotonic entropy overflow")// ErrScanValue is returned when the value passed to scan cannot be unmarshaled // into the ULID.ErrScanValue = errors.New("ulid: source value must be a string or byte slice"))// MonotonicReader is an interface that should yield monotonically increasing// entropy into the provided slice for all calls with the same ms parameter. If// a MonotonicReader is provided to the New constructor, its MonotonicRead// method will be used instead of Read.typeMonotonicReaderinterface {io.ReaderMonotonicRead(ms uint64, p []byte) error}// New returns an ULID with the given Unix milliseconds timestamp and an// optional entropy source. Use the Timestamp function to convert// a time.Time to Unix milliseconds.//// ErrBigTime is returned when passing a timestamp bigger than MaxTime.// Reading from the entropy source may also return an error.//// Safety for concurrent use is only dependent on the safety of the// entropy source.func ( uint64, io.Reader) ( ULID, error) {if = .SetTime(); != nil {return , }switch e := .(type) {casenil:return , caseMonotonicReader: = .MonotonicRead(, [6:])default: _, = io.ReadFull(, [6:]) }return , }// MustNew is a convenience function equivalent to New that panics on failure// instead of returning an error.func ( uint64, io.Reader) ULID { , := New(, )if != nil {panic() }return}var ( entropy io.Reader entropyOnce sync.Once)// DefaultEntropy returns a thread-safe per process monotonically increasing// entropy source.func () io.Reader {entropyOnce.Do(func() { := rand.New(rand.NewSource(time.Now().UnixNano()))entropy = &LockedMonotonicReader{MonotonicReader: Monotonic(, 0), } })returnentropy}// Make returns an ULID with the current time in Unix milliseconds and// monotonically increasing entropy for the same millisecond.// It is safe for concurrent use, leveraging a sync.Pool underneath for minimal// contention.func () ( ULID) {// NOTE: MustNew can't panic since DefaultEntropy never returns an error.returnMustNew(Now(), DefaultEntropy())}// Parse parses an encoded ULID, returning an error in case of failure.//// ErrDataSize is returned if the len(ulid) is different from an encoded// ULID's length. Invalid encodings produce undefined ULIDs. For a version that// returns an error instead, see ParseStrict.func ( string) ( ULID, error) {return , parse([]byte(), false, &)}// ParseStrict parses an encoded ULID, returning an error in case of failure.//// It is like Parse, but additionally validates that the parsed ULID consists// only of valid base32 characters. It is slightly slower than Parse.//// ErrDataSize is returned if the len(ulid) is different from an encoded// ULID's length. Invalid encodings return ErrInvalidCharacters.func ( string) ( ULID, error) {return , parse([]byte(), true, &)}func parse( []byte, bool, *ULID) error {// Check if a base32 encoded ULID is the right length.iflen() != EncodedSize {returnErrDataSize }// Check if all the characters in a base32 encoded ULID are part of the // expected base32 character set.if && (dec[[0]] == 0xFF ||dec[[1]] == 0xFF ||dec[[2]] == 0xFF ||dec[[3]] == 0xFF ||dec[[4]] == 0xFF ||dec[[5]] == 0xFF ||dec[[6]] == 0xFF ||dec[[7]] == 0xFF ||dec[[8]] == 0xFF ||dec[[9]] == 0xFF ||dec[[10]] == 0xFF ||dec[[11]] == 0xFF ||dec[[12]] == 0xFF ||dec[[13]] == 0xFF ||dec[[14]] == 0xFF ||dec[[15]] == 0xFF ||dec[[16]] == 0xFF ||dec[[17]] == 0xFF ||dec[[18]] == 0xFF ||dec[[19]] == 0xFF ||dec[[20]] == 0xFF ||dec[[21]] == 0xFF ||dec[[22]] == 0xFF ||dec[[23]] == 0xFF ||dec[[24]] == 0xFF ||dec[[25]] == 0xFF) {returnErrInvalidCharacters }// Check if the first character in a base32 encoded ULID will overflow. This // happens because the base32 representation encodes 130 bits, while the // ULID is only 128 bits. // // See https://github.com/oklog/ulid/issues/9 for details.if [0] > '7' {returnErrOverflow }// Use an optimized unrolled loop (from https://github.com/RobThree/NUlid) // to decode a base32 ULID.// 6 bytes timestamp (48 bits) (*)[0] = (dec[[0]] << 5) | dec[[1]] (*)[1] = (dec[[2]] << 3) | (dec[[3]] >> 2) (*)[2] = (dec[[3]] << 6) | (dec[[4]] << 1) | (dec[[5]] >> 4) (*)[3] = (dec[[5]] << 4) | (dec[[6]] >> 1) (*)[4] = (dec[[6]] << 7) | (dec[[7]] << 2) | (dec[[8]] >> 3) (*)[5] = (dec[[8]] << 5) | dec[[9]]// 10 bytes of entropy (80 bits) (*)[6] = (dec[[10]] << 3) | (dec[[11]] >> 2) (*)[7] = (dec[[11]] << 6) | (dec[[12]] << 1) | (dec[[13]] >> 4) (*)[8] = (dec[[13]] << 4) | (dec[[14]] >> 1) (*)[9] = (dec[[14]] << 7) | (dec[[15]] << 2) | (dec[[16]] >> 3) (*)[10] = (dec[[16]] << 5) | dec[[17]] (*)[11] = (dec[[18]] << 3) | dec[[19]]>>2 (*)[12] = (dec[[19]] << 6) | (dec[[20]] << 1) | (dec[[21]] >> 4) (*)[13] = (dec[[21]] << 4) | (dec[[22]] >> 1) (*)[14] = (dec[[22]] << 7) | (dec[[23]] << 2) | (dec[[24]] >> 3) (*)[15] = (dec[[24]] << 5) | dec[[25]]returnnil}// MustParse is a convenience function equivalent to Parse that panics on failure// instead of returning an error.func ( string) ULID { , := Parse()if != nil {panic() }return}// MustParseStrict is a convenience function equivalent to ParseStrict that// panics on failure instead of returning an error.func ( string) ULID { , := ParseStrict()if != nil {panic() }return}// Bytes returns bytes slice representation of ULID.func ( ULID) () []byte {return [:]}// String returns a lexicographically sortable string encoded ULID// (26 characters, non-standard base 32) e.g. 01AN4Z07BY79KA1307SR9X4MV3.// Format: tttttttttteeeeeeeeeeeeeeee where t is time and e is entropy.func ( ULID) () string { := make([]byte, EncodedSize) _ = .MarshalTextTo()returnstring()}// MarshalBinary implements the encoding.BinaryMarshaler interface by// returning the ULID as a byte slice.func ( ULID) () ([]byte, error) { := make([]byte, len())return , .MarshalBinaryTo()}// MarshalBinaryTo writes the binary encoding of the ULID to the given buffer.// ErrBufferSize is returned when the len(dst) != 16.func ( ULID) ( []byte) error {iflen() != len() {returnErrBufferSize }copy(, [:])returnnil}// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface by// copying the passed data and converting it to an ULID. ErrDataSize is// returned if the data length is different from ULID length.func ( *ULID) ( []byte) error {iflen() != len(*) {returnErrDataSize }copy((*)[:], )returnnil}// Encoding is the base 32 encoding alphabet used in ULID strings.constEncoding = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"// MarshalText implements the encoding.TextMarshaler interface by// returning the string encoded ULID.func ( ULID) () ([]byte, error) { := make([]byte, EncodedSize)return , .MarshalTextTo()}// MarshalTextTo writes the ULID as a string to the given buffer.// ErrBufferSize is returned when the len(dst) != 26.func ( ULID) ( []byte) error {// Optimized unrolled loop ahead. // From https://github.com/RobThree/NUlidiflen() != EncodedSize {returnErrBufferSize }// 10 byte timestamp [0] = Encoding[([0]&224)>>5] [1] = Encoding[[0]&31] [2] = Encoding[([1]&248)>>3] [3] = Encoding[(([1]&7)<<2)|(([2]&192)>>6)] [4] = Encoding[([2]&62)>>1] [5] = Encoding[(([2]&1)<<4)|(([3]&240)>>4)] [6] = Encoding[(([3]&15)<<1)|(([4]&128)>>7)] [7] = Encoding[([4]&124)>>2] [8] = Encoding[(([4]&3)<<3)|(([5]&224)>>5)] [9] = Encoding[[5]&31]// 16 bytes of entropy [10] = Encoding[([6]&248)>>3] [11] = Encoding[(([6]&7)<<2)|(([7]&192)>>6)] [12] = Encoding[([7]&62)>>1] [13] = Encoding[(([7]&1)<<4)|(([8]&240)>>4)] [14] = Encoding[(([8]&15)<<1)|(([9]&128)>>7)] [15] = Encoding[([9]&124)>>2] [16] = Encoding[(([9]&3)<<3)|(([10]&224)>>5)] [17] = Encoding[[10]&31] [18] = Encoding[([11]&248)>>3] [19] = Encoding[(([11]&7)<<2)|(([12]&192)>>6)] [20] = Encoding[([12]&62)>>1] [21] = Encoding[(([12]&1)<<4)|(([13]&240)>>4)] [22] = Encoding[(([13]&15)<<1)|(([14]&128)>>7)] [23] = Encoding[([14]&124)>>2] [24] = Encoding[(([14]&3)<<3)|(([15]&224)>>5)] [25] = Encoding[[15]&31]returnnil}// Byte to index table for O(1) lookups when unmarshaling.// We use 0xFF as sentinel value for invalid indexes.var dec = [...]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF,0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, 0x1D, 0x1E,0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C,0x0D, 0x0E, 0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14,0x15, 0xFF, 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C,0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,}// EncodedSize is the length of a text encoded ULID.constEncodedSize = 26// UnmarshalText implements the encoding.TextUnmarshaler interface by// parsing the data as string encoded ULID.//// ErrDataSize is returned if the len(v) is different from an encoded// ULID's length. Invalid encodings produce undefined ULIDs.func ( *ULID) ( []byte) error {returnparse(, false, )}// Time returns the Unix time in milliseconds encoded in the ULID.// Use the top level Time function to convert the returned value to// a time.Time.func ( ULID) () uint64 {returnuint64([5]) | uint64([4])<<8 |uint64([3])<<16 | uint64([2])<<24 |uint64([1])<<32 | uint64([0])<<40}// maxTime is the maximum Unix time in milliseconds that can be// represented in an ULID.var maxTime = ULID{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}.Time()// MaxTime returns the maximum Unix time in milliseconds that// can be encoded in an ULID.func () uint64 { returnmaxTime }// Now is a convenience function that returns the current// UTC time in Unix milliseconds. Equivalent to:// Timestamp(time.Now().UTC())func () uint64 { returnTimestamp(time.Now().UTC()) }// Timestamp converts a time.Time to Unix milliseconds.//// Because of the way ULID stores time, times from the year// 10889 produces undefined results.func ( time.Time) uint64 {returnuint64(.Unix())*1000 +uint64(.Nanosecond()/int(time.Millisecond))}// Time converts Unix milliseconds in the format// returned by the Timestamp function to a time.Time.func ( uint64) time.Time { := int64( / 1e3) := int64(( % 1e3) * 1e6)returntime.Unix(, )}// SetTime sets the time component of the ULID to the given Unix time// in milliseconds.func ( *ULID) ( uint64) error {if > maxTime {returnErrBigTime } (*)[0] = byte( >> 40) (*)[1] = byte( >> 32) (*)[2] = byte( >> 24) (*)[3] = byte( >> 16) (*)[4] = byte( >> 8) (*)[5] = byte()returnnil}// Entropy returns the entropy from the ULID.func ( ULID) () []byte { := make([]byte, 10)copy(, [6:])return}// SetEntropy sets the ULID entropy to the passed byte slice.// ErrDataSize is returned if len(e) != 10.func ( *ULID) ( []byte) error {iflen() != 10 {returnErrDataSize }copy((*)[6:], )returnnil}// Compare returns an integer comparing id and other lexicographically.// The result will be 0 if id==other, -1 if id < other, and +1 if id > other.func ( ULID) ( ULID) int {returnbytes.Compare([:], [:])}// Scan implements the sql.Scanner interface. It supports scanning// a string or byte slice.func ( *ULID) ( interface{}) error {switch x := .(type) {casenil:returnnilcasestring:return .UnmarshalText([]byte())case []byte:return .UnmarshalBinary() }returnErrScanValue}// Value implements the sql/driver.Valuer interface, returning the ULID as a// slice of bytes, by invoking MarshalBinary. If your use case requires a string// representation instead, you can create a wrapper type that calls String()// instead.//// type stringValuer ulid.ULID//// func (v stringValuer) Value() (driver.Value, error) {// return ulid.ULID(v).String(), nil// }//// // Example usage.// db.Exec("...", stringValuer(id))//// All valid ULIDs, including zero-value ULIDs, return a valid Value with a nil// error. If your use case requires zero-value ULIDs to return a non-nil error,// you can create a wrapper type that special-cases this behavior.//// var zeroValueULID ulid.ULID//// type invalidZeroValuer ulid.ULID//// func (v invalidZeroValuer) Value() (driver.Value, error) {// if ulid.ULID(v).Compare(zeroValueULID) == 0 {// return nil, fmt.Errorf("zero value")// }// return ulid.ULID(v).Value()// }//// // Example usage.// db.Exec("...", invalidZeroValuer(id))//func ( ULID) () (driver.Value, error) {return .MarshalBinary()}// Monotonic returns an entropy source that is guaranteed to yield// strictly increasing entropy bytes for the same ULID timestamp.// On conflicts, the previous ULID entropy is incremented with a// random number between 1 and `inc` (inclusive).//// The provided entropy source must actually yield random bytes or else// monotonic reads are not guaranteed to terminate, since there isn't// enough randomness to compute an increment number.//// When `inc == 0`, it'll be set to a secure default of `math.MaxUint32`.// The lower the value of `inc`, the easier the next ULID within the// same millisecond is to guess. If your code depends on ULIDs having// secure entropy bytes, then don't go under this default unless you know// what you're doing.//// The returned type isn't safe for concurrent use.func ( io.Reader, uint64) *MonotonicEntropy { := MonotonicEntropy{Reader: bufio.NewReader(),inc: , }if .inc == 0 { .inc = math.MaxUint32 }if , := .(rng); { .rng = }return &}type rng interface{ Int63n(n int64) int64 }// LockedMonotonicReader wraps a MonotonicReader with a sync.Mutex for// safe concurrent use.typeLockedMonotonicReaderstruct { mu sync.MutexMonotonicReader}// MonotonicRead synchronizes calls to the wrapped MonotonicReader.func ( *LockedMonotonicReader) ( uint64, []byte) ( error) { .mu.Lock() = .MonotonicReader.MonotonicRead(, ) .mu.Unlock()return}// MonotonicEntropy is an opaque type that provides monotonic entropy.typeMonotonicEntropystruct {io.Reader ms uint64 inc uint64 entropy uint80 rand [8]byte rng rng}// MonotonicRead implements the MonotonicReader interface.func ( *MonotonicEntropy) ( uint64, []byte) ( error) {if !.entropy.IsZero() && .ms == { = .increment() .entropy.AppendTo() } elseif _, = io.ReadFull(.Reader, ); == nil { .ms = .entropy.SetBytes() }return}// increment the previous entropy number with a random number// of up to m.inc (inclusive).func ( *MonotonicEntropy) () error {if , := .random(); != nil {return } elseif .entropy.Add() {returnErrMonotonicOverflow }returnnil}// random returns a uniform random value in [1, m.inc), reading entropy// from m.Reader. When m.inc == 0 || m.inc == 1, it returns 1.// Adapted from: https://golang.org/pkg/crypto/rand/#Intfunc ( *MonotonicEntropy) () ( uint64, error) {if .inc <= 1 {return1, nil }// Fast path for using a underlying rand.Rand directly.if .rng != nil {// Range: [1, m.inc)return1 + uint64(.rng.Int63n(int64(.inc))), nil }// bitLen is the maximum bit length needed to encode a value < m.inc. := bits.Len64(.inc)// byteLen is the maximum byte length needed to encode a value < m.inc. := uint(+7) / 8// msbitLen is the number of bits in the most significant byte of m.inc-1. := uint( % 8)if == 0 { = 8 }for == 0 || >= .inc {if _, = io.ReadFull(.Reader, .rand[:]); != nil {return0, }// Clear bits in the first byte to increase the probability // that the candidate is < m.inc. .rand[0] &= uint8(int(1<<) - 1)// Convert the read bytes into an uint64 with byteLen // Optimized unrolled loop.switch {case1: = uint64(.rand[0])case2: = uint64(binary.LittleEndian.Uint16(.rand[:2]))case3, 4: = uint64(binary.LittleEndian.Uint32(.rand[:4]))case5, 6, 7, 8: = uint64(binary.LittleEndian.Uint64(.rand[:8])) } }// Range: [1, m.inc)return1 + , nil}type uint80 struct { Hi uint16 Lo uint64}func ( *uint80) ( []byte) { .Hi = binary.BigEndian.Uint16([:2]) .Lo = binary.BigEndian.Uint64([2:])}func ( *uint80) ( []byte) {binary.BigEndian.PutUint16([:2], .Hi)binary.BigEndian.PutUint64([2:], .Lo)}func ( *uint80) ( uint64) ( bool) { , := .Lo, .Hiif .Lo += ; .Lo < { .Hi++ }return .Hi < }func ( uint80) () bool {return .Hi == 0 && .Lo == 0}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.