summaryrefslogtreecommitdiff
path: root/vendor/github.com/oklog/ulid/ulid.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/oklog/ulid/ulid.go')
-rw-r--r--vendor/github.com/oklog/ulid/ulid.go614
1 files changed, 614 insertions, 0 deletions
diff --git a/vendor/github.com/oklog/ulid/ulid.go b/vendor/github.com/oklog/ulid/ulid.go
new file mode 100644
index 000000000..c5d0d66fd
--- /dev/null
+++ b/vendor/github.com/oklog/ulid/ulid.go
@@ -0,0 +1,614 @@
+// 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 ulid
+
+import (
+ "bufio"
+ "bytes"
+ "database/sql/driver"
+ "encoding/binary"
+ "errors"
+ "io"
+ "math"
+ "math/bits"
+ "math/rand"
+ "time"
+)
+
+/*
+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 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+type ULID [16]byte
+
+var (
+ // 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")
+)
+
+// 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.
+func New(ms uint64, entropy io.Reader) (id ULID, err error) {
+ if err = id.SetTime(ms); err != nil {
+ return id, err
+ }
+
+ switch e := entropy.(type) {
+ case nil:
+ return id, err
+ case *monotonic:
+ err = e.MonotonicRead(ms, id[6:])
+ default:
+ _, err = io.ReadFull(e, id[6:])
+ }
+
+ return id, err
+}
+
+// MustNew is a convenience function equivalent to New that panics on failure
+// instead of returning an error.
+func MustNew(ms uint64, entropy io.Reader) ULID {
+ id, err := New(ms, entropy)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// 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 Parse(ulid string) (id ULID, err error) {
+ return id, parse([]byte(ulid), false, &id)
+}
+
+// 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 ParseStrict(ulid string) (id ULID, err error) {
+ return id, parse([]byte(ulid), true, &id)
+}
+
+func parse(v []byte, strict bool, id *ULID) error {
+ // Check if a base32 encoded ULID is the right length.
+ if len(v) != EncodedSize {
+ return ErrDataSize
+ }
+
+ // Check if all the characters in a base32 encoded ULID are part of the
+ // expected base32 character set.
+ if strict &&
+ (dec[v[0]] == 0xFF ||
+ dec[v[1]] == 0xFF ||
+ dec[v[2]] == 0xFF ||
+ dec[v[3]] == 0xFF ||
+ dec[v[4]] == 0xFF ||
+ dec[v[5]] == 0xFF ||
+ dec[v[6]] == 0xFF ||
+ dec[v[7]] == 0xFF ||
+ dec[v[8]] == 0xFF ||
+ dec[v[9]] == 0xFF ||
+ dec[v[10]] == 0xFF ||
+ dec[v[11]] == 0xFF ||
+ dec[v[12]] == 0xFF ||
+ dec[v[13]] == 0xFF ||
+ dec[v[14]] == 0xFF ||
+ dec[v[15]] == 0xFF ||
+ dec[v[16]] == 0xFF ||
+ dec[v[17]] == 0xFF ||
+ dec[v[18]] == 0xFF ||
+ dec[v[19]] == 0xFF ||
+ dec[v[20]] == 0xFF ||
+ dec[v[21]] == 0xFF ||
+ dec[v[22]] == 0xFF ||
+ dec[v[23]] == 0xFF ||
+ dec[v[24]] == 0xFF ||
+ dec[v[25]] == 0xFF) {
+ return ErrInvalidCharacters
+ }
+
+ // 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 v[0] > '7' {
+ return ErrOverflow
+ }
+
+ // Use an optimized unrolled loop (from https://github.com/RobThree/NUlid)
+ // to decode a base32 ULID.
+
+ // 6 bytes timestamp (48 bits)
+ (*id)[0] = ((dec[v[0]] << 5) | dec[v[1]])
+ (*id)[1] = ((dec[v[2]] << 3) | (dec[v[3]] >> 2))
+ (*id)[2] = ((dec[v[3]] << 6) | (dec[v[4]] << 1) | (dec[v[5]] >> 4))
+ (*id)[3] = ((dec[v[5]] << 4) | (dec[v[6]] >> 1))
+ (*id)[4] = ((dec[v[6]] << 7) | (dec[v[7]] << 2) | (dec[v[8]] >> 3))
+ (*id)[5] = ((dec[v[8]] << 5) | dec[v[9]])
+
+ // 10 bytes of entropy (80 bits)
+ (*id)[6] = ((dec[v[10]] << 3) | (dec[v[11]] >> 2))
+ (*id)[7] = ((dec[v[11]] << 6) | (dec[v[12]] << 1) | (dec[v[13]] >> 4))
+ (*id)[8] = ((dec[v[13]] << 4) | (dec[v[14]] >> 1))
+ (*id)[9] = ((dec[v[14]] << 7) | (dec[v[15]] << 2) | (dec[v[16]] >> 3))
+ (*id)[10] = ((dec[v[16]] << 5) | dec[v[17]])
+ (*id)[11] = ((dec[v[18]] << 3) | dec[v[19]]>>2)
+ (*id)[12] = ((dec[v[19]] << 6) | (dec[v[20]] << 1) | (dec[v[21]] >> 4))
+ (*id)[13] = ((dec[v[21]] << 4) | (dec[v[22]] >> 1))
+ (*id)[14] = ((dec[v[22]] << 7) | (dec[v[23]] << 2) | (dec[v[24]] >> 3))
+ (*id)[15] = ((dec[v[24]] << 5) | dec[v[25]])
+
+ return nil
+}
+
+// MustParse is a convenience function equivalent to Parse that panics on failure
+// instead of returning an error.
+func MustParse(ulid string) ULID {
+ id, err := Parse(ulid)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// MustParseStrict is a convenience function equivalent to ParseStrict that
+// panics on failure instead of returning an error.
+func MustParseStrict(ulid string) ULID {
+ id, err := ParseStrict(ulid)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// 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 (id ULID) String() string {
+ ulid := make([]byte, EncodedSize)
+ _ = id.MarshalTextTo(ulid)
+ return string(ulid)
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface by
+// returning the ULID as a byte slice.
+func (id ULID) MarshalBinary() ([]byte, error) {
+ ulid := make([]byte, len(id))
+ return ulid, id.MarshalBinaryTo(ulid)
+}
+
+// MarshalBinaryTo writes the binary encoding of the ULID to the given buffer.
+// ErrBufferSize is returned when the len(dst) != 16.
+func (id ULID) MarshalBinaryTo(dst []byte) error {
+ if len(dst) != len(id) {
+ return ErrBufferSize
+ }
+
+ copy(dst, id[:])
+ return nil
+}
+
+// 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 (id *ULID) UnmarshalBinary(data []byte) error {
+ if len(data) != len(*id) {
+ return ErrDataSize
+ }
+
+ copy((*id)[:], data)
+ return nil
+}
+
+// Encoding is the base 32 encoding alphabet used in ULID strings.
+const Encoding = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
+
+// MarshalText implements the encoding.TextMarshaler interface by
+// returning the string encoded ULID.
+func (id ULID) MarshalText() ([]byte, error) {
+ ulid := make([]byte, EncodedSize)
+ return ulid, id.MarshalTextTo(ulid)
+}
+
+// MarshalTextTo writes the ULID as a string to the given buffer.
+// ErrBufferSize is returned when the len(dst) != 26.
+func (id ULID) MarshalTextTo(dst []byte) error {
+ // Optimized unrolled loop ahead.
+ // From https://github.com/RobThree/NUlid
+
+ if len(dst) != EncodedSize {
+ return ErrBufferSize
+ }
+
+ // 10 byte timestamp
+ dst[0] = Encoding[(id[0]&224)>>5]
+ dst[1] = Encoding[id[0]&31]
+ dst[2] = Encoding[(id[1]&248)>>3]
+ dst[3] = Encoding[((id[1]&7)<<2)|((id[2]&192)>>6)]
+ dst[4] = Encoding[(id[2]&62)>>1]
+ dst[5] = Encoding[((id[2]&1)<<4)|((id[3]&240)>>4)]
+ dst[6] = Encoding[((id[3]&15)<<1)|((id[4]&128)>>7)]
+ dst[7] = Encoding[(id[4]&124)>>2]
+ dst[8] = Encoding[((id[4]&3)<<3)|((id[5]&224)>>5)]
+ dst[9] = Encoding[id[5]&31]
+
+ // 16 bytes of entropy
+ dst[10] = Encoding[(id[6]&248)>>3]
+ dst[11] = Encoding[((id[6]&7)<<2)|((id[7]&192)>>6)]
+ dst[12] = Encoding[(id[7]&62)>>1]
+ dst[13] = Encoding[((id[7]&1)<<4)|((id[8]&240)>>4)]
+ dst[14] = Encoding[((id[8]&15)<<1)|((id[9]&128)>>7)]
+ dst[15] = Encoding[(id[9]&124)>>2]
+ dst[16] = Encoding[((id[9]&3)<<3)|((id[10]&224)>>5)]
+ dst[17] = Encoding[id[10]&31]
+ dst[18] = Encoding[(id[11]&248)>>3]
+ dst[19] = Encoding[((id[11]&7)<<2)|((id[12]&192)>>6)]
+ dst[20] = Encoding[(id[12]&62)>>1]
+ dst[21] = Encoding[((id[12]&1)<<4)|((id[13]&240)>>4)]
+ dst[22] = Encoding[((id[13]&15)<<1)|((id[14]&128)>>7)]
+ dst[23] = Encoding[(id[14]&124)>>2]
+ dst[24] = Encoding[((id[14]&3)<<3)|((id[15]&224)>>5)]
+ dst[25] = Encoding[id[15]&31]
+
+ return nil
+}
+
+// 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.
+const EncodedSize = 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 (id *ULID) UnmarshalText(v []byte) error {
+ return parse(v, false, id)
+}
+
+// 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 (id ULID) Time() uint64 {
+ return uint64(id[5]) | uint64(id[4])<<8 |
+ uint64(id[3])<<16 | uint64(id[2])<<24 |
+ uint64(id[1])<<32 | uint64(id[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 MaxTime() uint64 { return maxTime }
+
+// Now is a convenience function that returns the current
+// UTC time in Unix milliseconds. Equivalent to:
+// Timestamp(time.Now().UTC())
+func Now() uint64 { return Timestamp(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 Timestamp(t time.Time) uint64 {
+ return uint64(t.Unix())*1000 +
+ uint64(t.Nanosecond()/int(time.Millisecond))
+}
+
+// Time converts Unix milliseconds in the format
+// returned by the Timestamp function to a time.Time.
+func Time(ms uint64) time.Time {
+ s := int64(ms / 1e3)
+ ns := int64((ms % 1e3) * 1e6)
+ return time.Unix(s, ns)
+}
+
+// SetTime sets the time component of the ULID to the given Unix time
+// in milliseconds.
+func (id *ULID) SetTime(ms uint64) error {
+ if ms > maxTime {
+ return ErrBigTime
+ }
+
+ (*id)[0] = byte(ms >> 40)
+ (*id)[1] = byte(ms >> 32)
+ (*id)[2] = byte(ms >> 24)
+ (*id)[3] = byte(ms >> 16)
+ (*id)[4] = byte(ms >> 8)
+ (*id)[5] = byte(ms)
+
+ return nil
+}
+
+// Entropy returns the entropy from the ULID.
+func (id ULID) Entropy() []byte {
+ e := make([]byte, 10)
+ copy(e, id[6:])
+ return e
+}
+
+// SetEntropy sets the ULID entropy to the passed byte slice.
+// ErrDataSize is returned if len(e) != 10.
+func (id *ULID) SetEntropy(e []byte) error {
+ if len(e) != 10 {
+ return ErrDataSize
+ }
+
+ copy((*id)[6:], e)
+ return nil
+}
+
+// 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 (id ULID) Compare(other ULID) int {
+ return bytes.Compare(id[:], other[:])
+}
+
+// Scan implements the sql.Scanner interface. It supports scanning
+// a string or byte slice.
+func (id *ULID) Scan(src interface{}) error {
+ switch x := src.(type) {
+ case nil:
+ return nil
+ case string:
+ return id.UnmarshalText([]byte(x))
+ case []byte:
+ return id.UnmarshalBinary(x)
+ }
+
+ return ErrScanValue
+}
+
+// Value implements the sql/driver.Valuer interface. This returns the value
+// represented as a byte slice. If instead a string is desirable, a wrapper
+// type can be created that calls String().
+//
+// // stringValuer wraps a ULID as a string-based driver.Valuer.
+// type stringValuer ULID
+//
+// func (id stringValuer) Value() (driver.Value, error) {
+// return ULID(id).String(), nil
+// }
+//
+// // Example usage.
+// db.Exec("...", stringValuer(id))
+func (id ULID) Value() (driver.Value, error) {
+ return id.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 io.Reader isn't safe for concurrent use.
+func Monotonic(entropy io.Reader, inc uint64) io.Reader {
+ m := monotonic{
+ Reader: bufio.NewReader(entropy),
+ inc: inc,
+ }
+
+ if m.inc == 0 {
+ m.inc = math.MaxUint32
+ }
+
+ if rng, ok := entropy.(*rand.Rand); ok {
+ m.rng = rng
+ }
+
+ return &m
+}
+
+type monotonic struct {
+ io.Reader
+ ms uint64
+ inc uint64
+ entropy uint80
+ rand [8]byte
+ rng *rand.Rand
+}
+
+func (m *monotonic) MonotonicRead(ms uint64, entropy []byte) (err error) {
+ if !m.entropy.IsZero() && m.ms == ms {
+ err = m.increment()
+ m.entropy.AppendTo(entropy)
+ } else if _, err = io.ReadFull(m.Reader, entropy); err == nil {
+ m.ms = ms
+ m.entropy.SetBytes(entropy)
+ }
+ return err
+}
+
+// increment the previous entropy number with a random number
+// of up to m.inc (inclusive).
+func (m *monotonic) increment() error {
+ if inc, err := m.random(); err != nil {
+ return err
+ } else if m.entropy.Add(inc) {
+ return ErrMonotonicOverflow
+ }
+ return nil
+}
+
+// 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/#Int
+func (m *monotonic) random() (inc uint64, err error) {
+ if m.inc <= 1 {
+ return 1, nil
+ }
+
+ // Fast path for using a underlying rand.Rand directly.
+ if m.rng != nil {
+ // Range: [1, m.inc)
+ return 1 + uint64(m.rng.Int63n(int64(m.inc))), nil
+ }
+
+ // bitLen is the maximum bit length needed to encode a value < m.inc.
+ bitLen := bits.Len64(m.inc)
+
+ // byteLen is the maximum byte length needed to encode a value < m.inc.
+ byteLen := uint(bitLen+7) / 8
+
+ // msbitLen is the number of bits in the most significant byte of m.inc-1.
+ msbitLen := uint(bitLen % 8)
+ if msbitLen == 0 {
+ msbitLen = 8
+ }
+
+ for inc == 0 || inc >= m.inc {
+ if _, err = io.ReadFull(m.Reader, m.rand[:byteLen]); err != nil {
+ return 0, err
+ }
+
+ // Clear bits in the first byte to increase the probability
+ // that the candidate is < m.inc.
+ m.rand[0] &= uint8(int(1<<msbitLen) - 1)
+
+ // Convert the read bytes into an uint64 with byteLen
+ // Optimized unrolled loop.
+ switch byteLen {
+ case 1:
+ inc = uint64(m.rand[0])
+ case 2:
+ inc = uint64(binary.LittleEndian.Uint16(m.rand[:2]))
+ case 3, 4:
+ inc = uint64(binary.LittleEndian.Uint32(m.rand[:4]))
+ case 5, 6, 7, 8:
+ inc = uint64(binary.LittleEndian.Uint64(m.rand[:8]))
+ }
+ }
+
+ // Range: [1, m.inc)
+ return 1 + inc, nil
+}
+
+type uint80 struct {
+ Hi uint16
+ Lo uint64
+}
+
+func (u *uint80) SetBytes(bs []byte) {
+ u.Hi = binary.BigEndian.Uint16(bs[:2])
+ u.Lo = binary.BigEndian.Uint64(bs[2:])
+}
+
+func (u *uint80) AppendTo(bs []byte) {
+ binary.BigEndian.PutUint16(bs[:2], u.Hi)
+ binary.BigEndian.PutUint64(bs[2:], u.Lo)
+}
+
+func (u *uint80) Add(n uint64) (overflow bool) {
+ lo, hi := u.Lo, u.Hi
+ if u.Lo += n; u.Lo < lo {
+ u.Hi++
+ }
+ return u.Hi < hi
+}
+
+func (u uint80) IsZero() bool {
+ return u.Hi == 0 && u.Lo == 0
+}