package ksuid import ( "encoding/binary" "errors" "math" ) // Sequence is a KSUID generator which produces a sequence of ordered KSUIDs // from a seed. // // Up to 65536 KSUIDs can be generated by for a single seed. // // A typical usage of a Sequence looks like this: // // seq := ksuid.Sequence{ // Seed: ksuid.New(), // } // id, err := seq.Next() // // Sequence values are not safe to use concurrently from multiple goroutines. type Sequence struct { // The seed is used as base for the KSUID generator, all generated KSUIDs // share the same leading 18 bytes of the seed. Seed KSUID count uint32 // uint32 for overflow, only 2 bytes are used } // Next produces the next KSUID in the sequence, or returns an error if the // sequence has been exhausted. func (seq *Sequence) Next() (KSUID, error) { id := seq.Seed // copy count := seq.count if count > math.MaxUint16 { return Nil, errors.New("too many IDs were generated") } seq.count++ return withSequenceNumber(id, uint16(count)), nil } // Bounds returns the inclusive min and max bounds of the KSUIDs that may be // generated by the sequence. If all ids have been generated already then the // returned min value is equal to the max. func (seq *Sequence) Bounds() (min KSUID, max KSUID) { count := seq.count if count > math.MaxUint16 { count = math.MaxUint16 } return withSequenceNumber(seq.Seed, uint16(count)), withSequenceNumber(seq.Seed, math.MaxUint16) } func withSequenceNumber(id KSUID, n uint16) KSUID { binary.BigEndian.PutUint16(id[len(id)-2:], n) return id }