Documentation
¶
Index ¶
- Constants
- Variables
- func DefaultEntropy() io.Reader
- func MaxTime() uint64
- func Now() uint64
- func Time(ms uint64) time.Time
- func Timestamp(t time.Time) uint64
- type LockedMonotonicReader
- type MonotonicEntropy
- type MonotonicReader
- type SULID
- func Make() (id SULID)
- func MustNew(ms uint64, entropy io.Reader) SULID
- func MustNewDefault(t time.Time) SULID
- func MustParse(sulid string) SULID
- func MustParseStrict(sulid string) SULID
- func New(ms uint64, entropy io.Reader) (id SULID, err error)
- func Parse(sulid string) (id SULID, err error)
- func ParseStrict(sulid string) (id SULID, err error)
- func (id SULID) Bytes() []byte
- func (id SULID) Compare(other SULID) int
- func (id SULID) Entropy() []byte
- func (id SULID) IsZero() bool
- func (id SULID) MarshalBinary() ([]byte, error)
- func (id SULID) MarshalBinaryTo(dst []byte) error
- func (id SULID) MarshalText() ([]byte, error)
- func (id SULID) MarshalTextTo(dst []byte) error
- func (id *SULID) Scan(src interface{}) error
- func (id *SULID) SetEntropy(e []byte) error
- func (id *SULID) SetTime(ms uint64) error
- func (id SULID) String() string
- func (id SULID) Time() uint64
- func (id SULID) Timestamp() time.Time
- func (id *SULID) UnmarshalBinary(data []byte) error
- func (id *SULID) UnmarshalText(v []byte) error
- func (id SULID) Value() (driver.Value, error)
Examples ¶
Constants ¶
const EncodedSize = 20
EncodedSize is the length of a text encoded SULID.
const Encoding = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
Encoding is the base 32 encoding alphabet used in SULID strings.
Variables ¶
var ( // ErrDataSize is returned when parsing or unmarshaling SULIDs with the wrong // data size. ErrDataSize = errors.New("sulid: bad data size when unmarshaling") // ErrInvalidCharacters is returned when parsing or unmarshaling SULIDs with // invalid Base32 encodings. ErrInvalidCharacters = errors.New("sulid: bad data characters when unmarshaling") // ErrBufferSize is returned when marshalling SULIDs to a buffer of insufficient // size. ErrBufferSize = errors.New("sulid: bad buffer size when marshaling") // ErrBigTime is returned when constructing a SULID with a time that is larger // than MaxTime. ErrBigTime = errors.New("sulid: time too big") // ErrOverflow is returned when unmarshaling a SULID whose first character is // larger than 7, thereby exceeding the valid bit depth of 128. ErrOverflow = errors.New("sulid: overflow when unmarshaling") // ErrMonotonicOverflow is returned by a Monotonic entropy source when // incrementing the previous SULID's entropy bytes would result in overflow. ErrMonotonicOverflow = errors.New("sulid: monotonic entropy overflow") // ErrScanValue is returned when the value passed to scan cannot be unmarshaled // into the SULID. ErrScanValue = errors.New("sulid: source value must be a string or byte slice") // Zero is a zero-value SULID. Zero SULID )
Functions ¶
func DefaultEntropy ¶
DefaultEntropy returns a thread-safe per process monotonically increasing entropy source.
func MaxTime ¶
func MaxTime() uint64
MaxTime returns the maximum Unix time in milliseconds that can be encoded in a SULID.
func Now ¶
func Now() uint64
Now is a convenience function that returns the current UTC time in Unix milliseconds. Equivalent to:
Timestamp(time.Now().UTC())
Types ¶
type LockedMonotonicReader ¶
type LockedMonotonicReader struct {
MonotonicReader
// contains filtered or unexported fields
}
LockedMonotonicReader wraps a MonotonicReader with a sync.Mutex for safe concurrent use.
func (*LockedMonotonicReader) MonotonicRead ¶
func (r *LockedMonotonicReader) MonotonicRead(ms uint64, p []byte) (err error)
MonotonicRead synchronizes calls to the wrapped MonotonicReader.
type MonotonicEntropy ¶
MonotonicEntropy is an opaque type that provides monotonic entropy.
func Monotonic ¶
func Monotonic(entropy io.Reader, inc uint32) *MonotonicEntropy
Monotonic returns a source of entropy that yields strictly increasing entropy bytes, to a limit governeed by the `inc` parameter.
Specifically, calls to MonotonicRead within the same SULID timestamp return entropy incremented by a random number between 1 and `inc` inclusive. If an increment results in entropy that would overflow available space, MonotonicRead returns ErrMonotonicOverflow.
Passing `inc == 0` results in the reasonable default `math.MaxUint16`. Lower values of `inc` provide more monotonic entropy in a single millisecond, at the cost of easier "guessability" of generated SULIDs. If your code depends on SULIDs having secure entropy bytes, then it's recommended to use the secure default value of `inc == 0`, unless you know what you're doing.
The provided entropy source must actually yield random bytes. Otherwise, monotonic reads are not guaranteed to terminate, since there isn't enough randomness to compute an increment number.
The returned type isn't safe for concurrent use.
func (*MonotonicEntropy) MonotonicRead ¶
func (m *MonotonicEntropy) MonotonicRead(ms uint64, entropy []byte) (err error)
MonotonicRead implements the MonotonicReader interface.
type MonotonicReader ¶
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.
type SULID ¶
type SULID [12]byte
A SULID is a 12 byte Universally Unique Lexicographically Sortable Identifier
The components are encoded as 12 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 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Example ¶
package main
import (
"encoding/binary"
"fmt"
"io"
mrand "math/rand/v2"
"time"
"github.com/cyberxnomad/sulid"
)
func newMathV2Rng(t time.Time) io.Reader {
seed := [32]byte{}
binary.LittleEndian.PutUint64(seed[24:], uint64(t.UnixNano()))
return mrand.NewChaCha8(seed)
}
func main() {
t := time.Unix(1000000, 0)
entropy := sulid.Monotonic(newMathV2Rng(t), 0)
fmt.Println(sulid.MustNew(sulid.Timestamp(t), entropy))
}
Output: 0000XSNJG05BSJZW5PA8
func Make ¶
func Make() (id SULID)
Make returns a SULID 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 MustNew ¶
MustNew is a convenience function equivalent to New that panics on failure instead of returning an error.
func MustNewDefault ¶
MustNewDefault is a convenience function equivalent to MustNew with DefaultEntropy as the entropy. It may panic if the given time.Time is too large or too small.
func MustParse ¶
MustParse is a convenience function equivalent to Parse that panics on failure instead of returning an error.
func MustParseStrict ¶
MustParseStrict is a convenience function equivalent to ParseStrict that panics on failure instead of returning an error.
func New ¶
New returns a SULID 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 Parse ¶
Parse parses an encoded SULID, returning an error in case of failure.
ErrDataSize is returned if the len(sulid) is different from an encoded SULID's length. Invalid encodings produce undefined SULIDs. For a version that returns an error instead, see ParseStrict.
func ParseStrict ¶
ParseStrict parses an encoded SULID, returning an error in case of failure.
It is like Parse, but additionally validates that the parsed SULID consists only of valid base32 characters. It is slightly slower than Parse.
ErrDataSize is returned if the len(sulid) is different from an encoded SULID's length. Invalid encodings return ErrInvalidCharacters.
func (SULID) Compare ¶
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 (SULID) MarshalBinary ¶
MarshalBinary implements the encoding.BinaryMarshaler interface by returning the SULID as a byte slice.
func (SULID) MarshalBinaryTo ¶
MarshalBinaryTo writes the binary encoding of the SULID to the given buffer. ErrBufferSize is returned when the len(dst) != 12.
func (SULID) MarshalText ¶
MarshalText implements the encoding.TextMarshaler interface by returning the string encoded SULID.
func (SULID) MarshalTextTo ¶
MarshalTextTo writes the SULID as a string to the given buffer. ErrBufferSize is returned when the len(dst) != 20.
func (*SULID) Scan ¶
Scan implements the sql.Scanner interface. It supports scanning a string or byte slice.
func (*SULID) SetEntropy ¶
SetEntropy sets the SULID entropy to the passed byte slice. ErrDataSize is returned if len(e) != 6.
func (*SULID) SetTime ¶
SetTime sets the time component of the SULID to the given Unix time in milliseconds.
func (SULID) String ¶
String returns a lexicographically sortable string encoded SULID (20 characters, non-standard base 32) e.g. 01AN4Z07BY79KA1307SR9X4MV3. Format: tttttttttteeeeeeeeee where t is time and e is entropy.
func (SULID) Time ¶
Time returns the Unix time in milliseconds encoded in the SULID. Use the top level Time function to convert the returned value to a time.Time.
func (*SULID) UnmarshalBinary ¶
UnmarshalBinary implements the encoding.BinaryUnmarshaler interface by copying the passed data and converting it to a SULID. ErrDataSize is returned if the data length is different from SULID length.
func (*SULID) UnmarshalText ¶
UnmarshalText implements the encoding.TextUnmarshaler interface by parsing the data as string encoded SULID.
ErrDataSize is returned if the len(v) is different from an encoded SULID's length. Invalid encodings produce undefined SULIDs.
func (SULID) Value ¶
Value implements the sql/driver.Valuer interface, returning the SULID 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 sulid.SULID
func (v stringValuer) Value() (driver.Value, error) {
return sulid.SULID(v).String(), nil
}
// Example usage.
db.Exec("...", stringValuer(id))
All valid SULIDs, including zero-value SULIDs, return a valid Value with a nil error. If your use case requires zero-value SULIDs to return a non-nil error, you can create a wrapper type that special-cases this behavior.
var zeroValueSULID sulid.SULID
type invalidZeroValuer sulid.SULID
func (v invalidZeroValuer) Value() (driver.Value, error) {
if sulid.SULID(v).Compare(zeroValueSULID) == 0 {
return nil, fmt.Errorf("zero value")
}
return sulid.SULID(v).Value()
}
// Example usage.
db.Exec("...", invalidZeroValuer(id))