ulid

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 7, 2023 License: MIT Imports: 11 Imported by: 2

README

ULID

Universally Unique Lexicographically Sortable Identifier.

A GUID/UUID can be suboptimal for many use-cases because:

  • it isn't the most character efficient way of encoding 128 bits

  • provides no information other than randomness (depending on revision)

A ULID however:

  • compatible with UUID/GUID's

  • 1.21e+24 unique ULIDs per millisecond (1,208,925,819,614,629,174,706,176 to be exact)

  • lexicographically sortable

  • canonically encoded as a 26 character string

  • uses Crockford's base32 for better efficiency and readability (5 bits per character)

  • case insensitive

  • no special characters (URL safe)

  • monotonic sort order

Specification

Below is the current specification of ULID as implemented in this repository:

 01AN4Z07BY      79KA1307SR9X4MV3
|----------|    |----------------|
 Timestamp           Entropy
  10 chars           16 chars
   48bits             80bits
   base32             base32

Components

Timestamp:

  • 48 bit integer

  • UNIX-time in milliseconds

  • won't run out of space till the year 10895 AD (specified by ulid.MaxTime())

Entropy:

  • 80 random (dependent on io.Reader implementation you provide) bits

  • Monotonicity within same millisecond

Encoding

Crockford's Base32 is used as shown. This alphabet excludes the letters I, L, O, and U to avoid confusion and abuse.

0123456789ABCDEFGHJKMNPQRSTVWXYZ

Binary Layout and Byte Order

The components are encoded as 16 octets. Each component is encoded with the Most Significant Byte 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                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Tests

This module's tests can be run with ITERATIONS=100 go test ./. where $ITERATIONS specifies the number of test iterations to perform, i.e. how many ULIDs to generate and validate. By default this value is 10,000,000.

Thanks

This module initially started as work to fix some issues in oklog's ULID package, but soon gathered enough changes that I rewrote it from scratch.

Documentation

Index

Constants

View Source
const (
	// CrockfordBase32 is the ULID encoding alphabet, missing I,L,O,U
	// to avoid confusion and abuse. See: http://www.crockford.com/wrmg/base32.html
	CrockfordBase32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"

	// EncodedLen is the length of a text encoded ULID.
	EncodedLen = (BinaryLen*8 + 4) / 5

	// BinaryLen is the length of a binary ULID.
	BinaryLen = len(ULID{})
)

Variables

View Source
var (
	// ErrTimeOverflow is returned if a timestamp >= max time is provided to MonotonicReader.
	ErrTimeOverflow = errors.New("ulid: timestamp overflows max time")

	// ErrNegativeTime is returned if a timestamp predating the previous is provided to MonotonicReader.
	ErrNegativeTime = errors.New("ulid: timestamp predates previous")

	// ErrMonotonicOverflow is returned when incrementing previous ULID's entropy bytes would result
	// in an entropy overflow. The solution is to call .Next() again with a later timestamp.
	ErrMonotonicOverflow = errors.New("ulid: monotonic entropy overflow")
)
View Source
var (
	// ErrInvalidLength is returned when a parse/unmarshal is attempted on data of incorrect length.
	ErrInvalidLength = errors.New("ulid: invalid data length")

	// ErrInvalidULID is returned when an invalid text encoding of of a ULID is attempted to be parsed
	// or unmarshaled. Either due to illegal crockford base32 input data, or due to final character being
	// outside the possible decodable range of a binary ULID*.
	//
	// * due to the 130bit base32 -> 128bit binary decoding losing the
	// final 2 bits of data, only the following are possible final chars:
	//
	// 0   4   8   12  16  20  24  28
	// 0123456789ABCDEFGHJKMNPQRSTVWXYZ
	// 0,  4,  8,  C,  G,  M,  R,  W
	//
	// 0:  00000
	// 4:  00100
	// 8:  01000
	// 12: 01100
	// 16: 10000
	// 20: 10100
	// 24: 11000
	// 28: 11100
	//
	// All credit to https://codeberg.org/fansipans for catching and suggesting this fix <3.
	ErrInvalidULID = errors.New("ulid: invalid ulid data")

	// ErrBadScanSource is returned when an SQL scan is attempted with a non string/[]byte source.
	ErrBadScanSource = errors.New("ulid: scan src must be string or []byte")
)

Functions

func Encoding

func Encoding() base32.Encoding

Encoding returns the ULID base32 encoding prepared using CrockfordBase32 and no padding.

func MaxTime

func MaxTime() time.Time

MaxTime is the largest possbile timestamp encodable within a ULID.

func SetSource

func SetSource(src io.Reader) (err error)

SetSource updates the global MonotonicReader's source. Note that the default MonotonicReader source is cryptographically safe (uses "crypto/rand.Reader").

Types

type MonotonicReader

type MonotonicReader struct {
	// contains filtered or unexported fields
}

MonotonicReader wraps a reader to provide montonically increasing ULID values.

func NewMonotonicReader

func NewMonotonicReader(src io.Reader) (*MonotonicReader, error)

NewMonotonicReader returns a new instance for given entropy source and read buffer size. Note that 'src' MUST yield random bytes or else monotonic reads are not guaranteed to terminate, since there may not be enough entropy to compute a monotonic increment.

func (*MonotonicReader) Next

func (r *MonotonicReader) Next(ts TS, dst *ULID) error

Next calculates next available ULID for given Timestamp.

type TS

type TS uint64

TS represents a Unix time in milliseconds.

func Now

func Now() TS

Now returns the current time as timestamp.

func Timestamp

func Timestamp(t time.Time) TS

Timestamp will return time t as a timestamp.

func (TS) Add

func (ts TS) Add(d time.Duration) TS

Add returns the timestamp + d.

func (TS) After

func (ts TS) After(t time.Time) bool

After returns whether the timestamp is after t.

func (TS) Before

func (ts TS) Before(t time.Time) bool

Before returns whether the timestamp is before t.

func (TS) Equal

func (ts TS) Equal(t time.Time) bool

Equal returns whether the timestamp is equal to t.

func (TS) Sub

func (ts TS) Sub(d time.Duration) TS

Sub returns the timestamp - d.

func (TS) Time

func (ts TS) Time() time.Time

Time returns this timestamp as a time.Time.

type ULID

type ULID [16]byte

ULID: Universally Unique Lexicographically Sortable Identifier.

func Max added in v1.1.0

func Max() ULID

Max returns the highest possible value ULID.

func MustNew

func MustNew() ULID

MustNew calls .New() and panics if the error is non-nil.

func New

func New() (ulid ULID, err error)

New calculates a new ULID for current time using global MonotonicReader.

func Parse

func Parse(b []byte) (ULID, error)

Parse will parse a text-encoded ULID from bytes.

func ParseString

func ParseString(s string) (ULID, error)

ParseString will parse a text-encoded ULID from string.

func (ULID) AppendFormat

func (u ULID) AppendFormat(dst []byte) []byte

AppendFormat append text encoded ULID to 'dst'.

func (ULID) Bytes

func (u ULID) Bytes() []byte

Bytes returns text encoded bytes of receiving ULID.

func (ULID) Compare

func (u ULID) Compare(o ULID) int

Compare returns integer value from comparison between receiving and argument ULID lexographically.

0 -> (u == o), -1 -> (u < o), 1 -> (u > 0).

func (ULID) MarshalBinary

func (u ULID) MarshalBinary() ([]byte, error)

MarshalBinary implements encoding.BinaryMarshaler.

func (ULID) MarshalText

func (u ULID) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.

func (*ULID) Scan

func (u *ULID) Scan(src interface{}) error

Scan implements sql.Scanner.

func (ULID) String

func (u ULID) String() string

String returns text encoded bytes of receiving ULID.

func (ULID) Timestamp

func (u ULID) Timestamp() TS

Timestamp returns the timestamp encoded in this ULID.

func (*ULID) UnmarshalBinary

func (u *ULID) UnmarshalBinary(b []byte) error

UnmarshalBinary implements encoding.BinaryUnmarshaler.

func (*ULID) UnmarshalText

func (u *ULID) UnmarshalText(b []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

func (ULID) Value

func (u ULID) Value() (driver.Value, error)

Value implements driver.Valuer.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL