Package 'zuid'

Title: Universally Unique Identifiers, Their Encodings and Their Kin
Description: Parses, validates, inspects and generates universally unique identifiers (UUIDs) of every version defined by RFC 9562 <doi:10.17487/RFC9562>, and re-encodes them in alternative text forms such as Crockford base32, base36, base58, base62, base64url, Proquint and Niceware words. The same functions read the fields and creation time of related identifier formats: Universally Unique Lexicographically Sortable Identifiers (ULID), TypeID, Universally Unique Prefixed Lexicographically Sortable Identifiers (UPID), SCRU128 and SCRU64 (Sortable, Clock and Random number-based Unique identifiers), K-Sortable Unique Identifiers (KSUID), Snowflake, XID, 'MongoDB' ObjectId, NanoID, Cuid2, Sqids and content identifiers (CID). Detection never assumes a format that the input does not prove. Identifiers are generated from the operating system's entropy source, never from R's random number generator. No other package is needed at run time.
Authors: Pedro Baltazar [aut, cre, cph], yan [cph] (Author of the Niceware word list, compiled into src/zuid_tables.c), Sqids [cph] (Authors of the Sqids blocklist, compiled into src/zuid_tables.c)
Maintainer: Pedro Baltazar <[email protected]>
License: MIT + file LICENSE
Version: 0.1.0
Built: 2026-11-12 10:10:03 UTC
Source: https://github.com/pedrobtz/zuid

Help Index


Convert identifiers between formats

Description

id_convert() moves values between formats that hold the same bits: "uuid", "ulid", "typeid" and "upid" (128 bits), and "xid" and "objectid" (96 bits, laid out alike). The bytes are kept and the text is rewritten.

Usage

id_convert(x, to, prefix = NULL)

Arguments

x

A zuid vector.

to

The format to convert to.

prefix

For to = "typeid", the prefix of every value, "" for none. NULL keeps the prefixes of a TypeID and means "" otherwise.

Details

  • A UUID becomes a TypeID under prefix, and a TypeID becomes a UUID by dropping it.

  • A UPID becomes a UUID as the reference converts it, keeping the bits.

  • A ULID and a UUID convert by reinterpreting the bits. id_fields() then reports what the bits say: most ULIDs read as UUIDs of the "future" variant, and a UUID read as a ULID has its first 48 bits as a time, which is meaningful for version 7 only.

Any other pair is a zuid_convert_error: the target would need a value the source does not have. To change a UUID's text form, use id_format().

Value

A zuid vector of format to.

Examples

x <- id_parse("01890a5d-ac96-774b-bcce-b302099a8057", "uuid")
t <- id_convert(x, "typeid", prefix = "user")
t
id_convert(t, "uuid")
id_convert(x, "ulid")

Detect the format of identifiers

Description

id_detect() names the format of each element, or gives NA when the evidence does not settle it. Detection never guesses:

Usage

id_detect(x, hint = NULL, layout = NULL)

Arguments

x

A character vector.

hint

NULL, or the formats to try.

layout

An id_layout() for Snowflake or SCRU64.

Details

  • Without a hint, only structured formats are tried, since an encoding or a syntactic format (NanoID, Cuid2, Sqids) matches any string over its alphabet. A UUID written in Crockford base32 is textually a ULID, and the ULID is what is detected; id_parse(x, "uuid", form = "base32") is how to say otherwise.

  • When exactly one format passes at the "structure" level, it is the answer. When several pass, the answer is NA, and the candidates attribute lists them. A 26-character lowercase Crockford string, for one, is a ULID or a TypeID without a prefix.

  • A Snowflake is considered only under a Snowflake layout, since every layout reads the digits differently. A SCRU64 is listed among the candidates, but chosen only under id_layout("scru64", node_bits = ).

  • hint restricts the formats tried to those named, and is how a syntactic format or an encoding can be detected at all.

Formats are recognised in their canonical text, with their default alphabets.

Value

A character vector of formats, NA where none or several fit, with the attribute candidates: a list of the formats each element passes, structured formats first.

Examples

id_detect(c(
  "018f6b1c-2d3e-7a4b-8c5d-6e7f8091a2b3",
  "01ARZ3NDEKTSV4RRFFQ69G5FAV",
  "01arz3ndektsv4rrffq69g5fav",
  "not an id"
))
id_detect("01arz3ndektsv4rrffq69g5fav", hint = "typeid")
id_detect("175928847299117063", layout = id_layout("discord"))

Encode and decode bytes

Description

id_encode() writes bytes of any length as text in a form, and id_decode() reads them back. A UUID's text forms are the 16-byte case: id_format(x, form) is id_encode(id_bytes(x), form).

Usage

id_encode(bytes, form, alphabet = NULL, sep = "-")

id_decode(text, form, alphabet = NULL, width = NULL)

Arguments

bytes

A raw vector (one element), a list of raw vectors (NULL for a missing element), or a raw matrix with one element per column. At most 65536 bytes per element.

form

The form.

alphabet

For form = "alphabet", its symbols in digit order: 2 to 94 distinct printable ASCII characters other than space. NULL for ShortUUID's.

sep

The separator between units for "proquint" and "words": ASCII characters other than letters.

text

A character vector.

width

NULL, or the number of bytes each element must decode to.

Details

Each form writes what the mainstream Go and Python libraries write, so text made elsewhere decodes here and the other way round:

  • "hex": lowercase hexadecimal. Decoding takes either case and ignores hyphens.

  • "base32": Crockford's alphabet, with the spare bits in front as zero bits, as ULID and TypeID do. Sixteen bytes give 26 characters starting 0 to 7, so a UUID in this form is textually a ULID. Uppercase, and either case on input; the letters I, L, O and U are rejected.

  • "base32rfc", "base32hex": RFC 4648 sections 6 and 7, with the spare bits at the end and no padding. Decoding also takes = padding.

  • "base36": ⁠0-9a-z⁠, fixed width; 16 bytes are Uuid25's 25 characters.

  • "base58": base58btc. Each leading zero byte is one 1, so the length varies, as in Bitcoin and Go's and Python's base58.

  • "base62", "base62sort": ⁠0-9A-Za-z⁠, fixed width, padded with 0; sorts as the bytes do. The two names are one form.

  • "base64url": RFC 4648 section 5, no padding. Decoding also takes = padding.

  • "base64sort": base64url's bits in the IETF draft's alphabet, in ASCII order, so it sorts as the bytes do.

  • "alphabet": the caller's symbols, most significant digit first, fixed width, padded with the first symbol. The default is ShortUUID's 57 symbols, as ShortUUID 1.0 and later write them.

  • "proquint": each 16 bits as five pronounceable letters.

  • "words": each 16 bits as a Niceware word. The Niceware list was not checked for offensive words, and some text in this form may offend.

The fixed-width forms ("base32", "base36", "base62", "alphabet") write the digits the byte count needs, so the length gives the byte count back. "proquint" and "words" take an even number of bytes, and their decoding ignores case and any non-letter between units.

Value

id_encode(): a character vector, NA where bytes is NULL. id_decode(): a list of raw vectors, with NULL where text is NA or not text of the form.

Examples

b <- as.raw(c(0xf8, 0x1d, 0x4f, 0xae))
id_encode(b, "base58")
id_decode("7R3N7TW", "base32")
x <- id_parse("f81d4fae-7dec-11d0-a765-00a0c91e6bf6", "uuid")
id_encode(id_bytes(x), "base62")
id_format(x, "proquint")
id_encode(id_bytes(x), "alphabet", alphabet = "0123456789")

Read the fields of identifiers

Description

id_fields() reports what each identifier carries, one row per element. id_time() returns its time field alone, and id_version() its version.

Usage

id_fields(x)

id_time(x, class = c("POSIXct", "ms"))

id_version(x)

Arguments

x

A zuid vector from id_parse().

class

For id_time(), "POSIXct" (the default), or "ms" for the whole number of milliseconds since 1970 as a double, the sub-millisecond part dropped. POSIXct is exact to the microsecond; the 100 ns ticks of UUID versions 1 and 6 are exact in neither.

Details

For a UUID, the fields depend on the version and are read only when the variant is RFC 9562's:

  • versions 1 and 6: the time in 100 ns ticks from 1582-10-15, the 14-bit clock sequence (sequence) and the 48-bit node;

  • version 4: the 122 random bits;

  • version 7: the millisecond time and the 74 random bits;

  • versions 2, 3, 5 and 8: the version only.

A ULID has its millisecond time and 80 random bits. A TypeID has its UUID's fields and its prefix, "" when it has none. A UPID has its time in 256 ms units, 64 random bits, its prefix and its version nibble (6, the reference's "a", is the current one).

A SCRU128 has its millisecond time, counter_hi in node (as hex), counter_lo in sequence and its 32 entropy bits in random. A SCRU64 has its time at 256 ms, and its node and counter in sequence when it was parsed with id_layout("scru64", node_bits = ). A KSUID has its time in seconds and its 128-bit payload in random. An XID has its time in seconds, its machine id in node, its process and its counter in sequence; an ObjectId the same, but its middle five bytes are random, as the current BSON specification makes them. A Snowflake has what its layout says: the time at the layout's unit and epoch, the node fields in node as name=value pairs, and the sequence. A CID has its CID version, its content codec and hash function by multicodec name (or ⁠0x⁠ and the code when zuid does not know the name) and its digest as hex. A Sqid has its numbers. NanoID and Cuid2 have no fields: a Cuid2's time is hashed in and cannot be read back.

The nil and max UUIDs report versions 0 and 15 and no variant. random is the random bits joined in order, as hex, left-padded with zero bits to a whole number of hex digits.

Value

id_fields(): a data frame with columns format, time, time_unit, version, variant, node, process, sequence, random, prefix, codec, hash, digest and numbers, NA where the format or the element has no such field. id_time(): a POSIXct in UTC or a double. id_version(): an integer vector.

Examples

x <- id_parse(c(
  "018f6b1c-2d3e-7a4b-8c5d-6e7f8091a2b3",
  "c232ab00-9414-11ec-b3c8-9f6bdeced846"
), "uuid")
id_fields(x)
id_time(x)
id_version(x)

Text forms and bytes

Description

id_format() writes identifiers in their canonical text or another text form. id_bytes() returns their bytes, and id_from_bytes() reads them back.

Usage

id_format(x, form = NULL)

id_bytes(x)

id_from_bytes(bytes, format, layout = NULL)

Arguments

x

A zuid vector from id_parse().

form

A text form of the vector's format (see id_formats()), or NULL for the canonical text.

bytes

A raw matrix with one column per element, a list of raw vectors (NULL for a missing element), or one raw vector holding the elements back to back.

format

The format the bytes are in. Required.

layout

For "snowflake" (required) and "scru64" (optional), an id_layout().

Details

Every encoding of id_encode() is a form of a UUID too: id_format(x, "base62") is id_encode(id_bytes(x), "base62").

id_from_bytes() has no default format: sixteen bytes are not a UUID until the caller says so.

Value

id_format(): a character vector. id_bytes(): a raw matrix with the format's width in rows and one column per element, big-endian, with missing elements as columns of zeros listed in the attribute na. A CID has no fixed width, so for a CID it is a list of raw vectors instead, NULL for a missing element. Names become column names, or list names. id_from_bytes(): a zuid vector, named by the column names or list names of bytes.

Examples

x <- id_parse("018f6b1c-2d3e-7a4b-8c5d-6e7f8091a2b3", "uuid")
id_format(x, "urn")
id_format(x, "compact")
id_format(x, "base32")
b <- id_bytes(x)
b[, 1]
id_from_bytes(b, "uuid")

The identifier formats zuid knows

Description

The identifier formats zuid knows

Usage

id_formats()

Value

A data frame with one row per format: its name; its class (structured, encoding or syntactic); its width in bits; the length of its canonical text; its alphabet and case rule; the unit and epoch of its time field; and the text forms id_format() accepts.

Examples

id_formats()

Snowflake and SCRU64 layouts

Description

A layout says how a 64-bit identifier splits into a time, node fields and a sequence. It is data: the time field's bits, unit and epoch, the node fields with their widths in order, the sequence width, and whether the top bit is a sign bit. zuid cannot discover a Snowflake's layout from the number, so its fields are readable only when the layout is given.

Usage

id_layout(
  name = NULL,
  epoch = NULL,
  node_bits = NULL,
  time = NULL,
  fields = NULL,
  sequence = NULL,
  sign_bit = TRUE
)

## S3 method for class 'zuid_layout'
print(x, ...)

## S3 method for class 'zuid_layout'
format(x, ...)

Arguments

name

A built-in layout, or NULL for a custom one.

epoch

For "sonyflake" (required) or a custom layout, the time the time field counts from: a POSIXct or milliseconds since 1970.

node_bits

For "scru64", the node id's bits, 1 to 23.

time

For a custom layout, list(bits =, unit =, epoch =), unit one of "ms", "10ms", "256ms" and "s".

fields

For a custom layout, the node fields as a named list or vector of widths, most significant first.

sequence

For a custom layout, the sequence's bits.

sign_bit

For a custom layout, whether the top bit is reserved.

x

A layout.

...

Unused.

Details

The built-in layouts:

Name Time Node fields Sequence
twitter 41 bits, ms, from 2010-11-04T01:42:54.657Z datacenter 5, worker 5 12
discord 42 bits, ms, from 2015-01-01 worker 5, process 5 12
instagram 41 bits, ms, from 2011-08-24T21:07:01.721Z shard 13 10
sonyflake 39 bits, 10 ms, from epoch machine 16, after the sequence 8
scru64 39 bits, 256 ms, from 1970 node of node_bits 24 - node_bits

Twitter, Sonyflake and SCRU64 keep the top bit as a sign bit; Discord and Instagram use all 64 bits. Sonyflake's reference has changed its default start time between releases, so epoch is required for it.

A custom layout gives time, fields, sequence and sign_bit. The bits must add up to 64, or 63 with the sign bit, and each part must have fewer than 54 bits, so that it reads exactly as a double. The sequence has at most 31 bits, so that id_fields() returns it as an integer.

Value

A zuid_layout.

Examples

id_layout("twitter")
id_layout("scru64", node_bits = 8)
id_layout(
  time = list(bits = 41, unit = "ms", epoch = 0),
  fields = list(worker = 10),
  sequence = 12
)

Parse and validate identifiers

Description

id_parse() turns text into a zuid vector of one format, holding each element's canonical text. id_valid() is the vectorised predicate.

Usage

id_parse(
  x,
  format = NULL,
  form = NULL,
  layout = NULL,
  level = c("structure", "syntax", "strict"),
  strict = FALSE,
  alphabet = NULL,
  min_length = 0
)

id_valid(
  x,
  format,
  form = NULL,
  layout = NULL,
  level = c("structure", "syntax", "strict"),
  alphabet = NULL,
  min_length = 0
)

Arguments

x

A character vector.

format

The format, such as "uuid". See id_formats(). NULL detects it with id_detect(): every element that is not missing must resolve to the same format, or the call is a zuid_ambiguous_error naming the candidates or a zuid_mixed_error naming the formats found. Elements that fit no format are NA, or an error with strict = TRUE. When no element fits, or none is present (x is empty or all NA), there is no format to detect, and the call is a zuid_parse_error: give format.

form

A text form of format, or NULL for its canonical text.

layout

For "snowflake", required, and for "scru64", optional: an id_layout(). It travels with the vector and says how to read its fields. A Snowflake whose layout has a sign bit must have it clear.

level

The validation level elements must reach.

strict

If TRUE, an element that fails level is an error of class zuid_parse_error. If FALSE, it becomes NA.

alphabet

For "nanoid" and "sqids", the alphabet the values were made with, or NULL for the format's default. It travels with the vector.

min_length

For "sqids", the min_length the values were made with. A Sqids string is valid only when its numbers encode back to it, which depends on the alphabet, min_length and the blocklist.

Details

Validation is cumulative over three levels:

  • "syntax": the alphabet, length, case rule and separators of the form.

  • "structure": syntax, and the value's own rules. For a UUID, the variant bits are the RFC's (10), except for the nil and max UUIDs.

  • "strict": structure, and the value is one its specification defines. For a UUID, the version is 1 to 8 (or nil or max), and a time field is no later than now plus the option zuid.time_tolerance (seconds, one day by default).

A UUID's canonical text is lowercase and hyphenated. On input, either case is accepted, and form selects another of the RFC 9562 text forms: "compact" (32 hex digits), "urn" (⁠urn:uuid:⁠ prefix), "braced" or "uppercase", or one of the encodings of id_encode() over the 16 bytes, such as "base32", "base58" or "words".

A ULID is 26 Crockford base32 characters, uppercase, either case on input, starting 0 to 7. A TypeID is a lowercase prefix, ⁠_⁠ and 26 lowercase Crockford characters, or the 26 alone; strict asks what it asks of the UUID. A UPID is four prefix characters, ⁠_⁠ and 22 lowercase characters, as the reference writes them; strict asks for the current version. SCRU128 is 25 base36 characters and SCRU64 12, lowercase, either case on input; their reserved timestamps (the first and the last) pass "syntax" only. A KSUID is 27 base62 characters, case-sensitive, at most aWgEPTl1tmebfsQzFP4bxwgy80V. Strict also asks that a time is no later than now plus the tolerance. An XID is 20 lowercase base32hex characters, an ObjectId 24 hex digits (either case on input) and a Snowflake 1 to 20 decimal digits without leading zeros. A NanoID is one or more symbols of its alphabet; a Cuid2 is 2 to 32 of ⁠0-9a-z⁠, and strict asks that it starts with a letter, as generated ones do. A Sqid is valid when it decodes and its numbers encode back to it under the alphabet, min_length and blocklist. A CID is version 0 (Qm and 44 base58btc characters) or version 1 in one of 17 multibases; structure checks its varints, and the digest length of a hash function zuid knows. These formats have one text form each.

Value

id_parse(): a zuid vector, the same length as x, with NA where an element is missing or fails level. id_valid(): a logical vector, NA where x is.

Examples

x <- id_parse("018F6B1C-2D3E-7A4B-8C5D-6E7F8091A2B3", "uuid")
x
id_valid(c("018f6b1c-2d3e-7a4b-8c5d-6e7f8091a2b3", "nope"), "uuid")
id_parse("{018f6b1c-2d3e-7a4b-8c5d-6e7f8091a2b3}", "uuid", form = "braced")

Generate NanoIDs and Sqids

Description

nanoid() generates NanoIDs: size symbols drawn uniformly from alphabet, by NanoID 6's customRandom(). Random bytes come in batches, each read from its last byte, and a byte at or above the largest multiple of the alphabet's size below 256 is rejected, so every symbol is equally likely. When rejection uses up a batch, another is drawn.

Usage

nanoid(n = 1, size = 21, alphabet = NULL, random = NULL)

sqids(numbers, alphabet = NULL, min_length = 0, blocklist = NULL)

Arguments

n

The number of NanoIDs.

size

Symbols per NanoID, 1 to 65536, 21 by default.

alphabet

The symbols, or NULL for the format's default: ⁠A-Za-z0-9_-⁠ for NanoID and a-zA-Z0-9 for Sqids. 1 to 256 printable ASCII characters for NanoID, 3 to 255 for Sqids, all distinct.

random

For nanoid(), NULL to draw from the operating system, or a raw vector read batch by batch, for reproducible values; running out is a zuid_type_error.

numbers

A numeric vector, or a list of numeric vectors, of whole numbers from 0 to 2^53 - 1. An element that is NULL or a single NA gives NA; an element with NA among other numbers is an error.

min_length

The shortest Sqid, 0 to 255.

blocklist

NULL for the default blocklist, or a character vector of words to avoid (character() for none).

Details

sqids() encodes non-negative whole numbers as Sqids, by the specification's algorithm: the default alphabet and blocklist unless given, and padded to min_length. A numeric vector gives one Sqid per number; a list gives one per element, encoding all its numbers. An ID that contains a blocklisted word is re-encoded with the next offset; when every offset is blocked, the result is a zuid_encode_error. An element with no numbers encodes as "", as the specification says, and "" parses back to no numbers.

Value

A zuid vector.

Examples

nanoid(2)
nanoid(2, size = 10, alphabet = "0123456789abcdef")
sqids(c(1, 2, 3))
sqids(list(c(1, 2, 3)), min_length = 10)

Generate SCRU128, SCRU64 and KSUID values

Description

scru128() generates SCRU128 IDs by the specification's generator: 48 bits of milliseconds, a 24-bit counter_hi renewed once a second, a 24-bit counter_lo renewed each millisecond and incremented within it, and 32 random bits. Values from one session strictly increase; a counter overflow moves the timestamp forward instead of waiting.

Usage

scru128(n = 1, random = NULL, time = NULL, rollback = c("error", "reset"))

scru64(
  n = 1,
  node,
  node_bits,
  random = NULL,
  time = NULL,
  rollback = c("error", "reset")
)

ksuid(n = 1, random = NULL, time = NULL)

Arguments

n

The number of UUIDs.

random

NULL to draw from the operating system, or exactly the bytes needed: 10 per value for SCRU128 (4 of entropy, then the seeds of counter_lo and counter_hi), 3 per value for SCRU64 (the counter's seed) and 16 per value for KSUID.

time

NULL for the current time, or a POSIXct (or a double of milliseconds since 1970) of length 1 or n.

rollback

What to do when the clock runs back further than the tolerance: "error" or "reset".

node, node_bits

The SCRU64 node id and its size in bits, 1 to 23; the counter gets the other 24 - node_bits bits.

Details

scru64() generates SCRU64 IDs for one node, as the reference generator does: 256 ms ticks, then node in node_bits bits, then a counter renewed at each tick and incremented within it. node and node_bits are required, since only the caller can know that no other generator uses the same node.

ksuid() generates KSUIDs: seconds since 2014-05-13T16:53:20Z and 128 random bits. KSUIDs are not monotonic within a second.

A clock that runs back by up to the option zuid.rollback_tolerance (seconds, 10 by default) keeps the last timestamp, as both SCRU specifications recommend. Further back, rollback = "error" raises zuid_clock_error, so that monotonicity is never silently lost, and rollback = "reset" restarts the generator at the new time. A counter overflow that would reach the reserved last timestamp is a zuid_overflow_error.

SCRU64 keeps one state per node and node_bits, so values for each node increase however the calls for different nodes interleave. As in uuid(), a call given both time and random is a pure function of its arguments.

Value

A zuid vector of n values.

Examples

scru128(2)
scru64(2, node = 42, node_bits = 8)
ksuid(2)

Generate ULIDs, TypeIDs and UPIDs

Description

ulid() generates ULIDs: 48 bits of milliseconds and 80 random bits. Values from one session strictly increase, by the specification's rule: within a millisecond, the random component of the last value plus one. That overflows only after 2^80 values in one millisecond, which is a zuid_overflow_error.

Usage

ulid(n = 1, random = NULL, time = NULL)

typeid(n = 1, prefix, random = NULL, time = NULL)

upid(n = 1, prefix, random = NULL, time = NULL)

Arguments

n

The number of UUIDs.

random

NULL to draw from the operating system, or exactly the bytes needed: 10 per value for ULIDs and TypeIDs, 8 for UPIDs.

time

NULL for the current time, or a POSIXct (or a double of milliseconds since 1970) of length 1 or n.

prefix

For typeid(), the type: up to 63 lowercase letters and underscores, starting and ending with a letter, or "" for none. For upid(), one to four characters of 234567 and a to z, padded on the right with z as the reference pads it.

Details

typeid() generates TypeIDs: a version 7 UUID, as uuid() makes it, under prefix.

upid() generates UPIDs: 40 bits of time in 256 ms units, 64 random bits, the prefix and the current version, as the reference does. UPIDs are not monotonic within 256 ms.

Entropy comes from the operating system, never from R's random number generator, and the clock rollback rule of uuid() applies to ULIDs. As there, a call given both time and random is a pure function of its arguments.

Value

A zuid vector of n values.

Examples

ulid(2)
typeid(2, "user")
upid(2, "user")

Generate UUIDs

Description

Generates n UUIDs of a version, version 7 by default, from the operating system's entropy source and clock. R's random number generator is never used, so set.seed() does not change the result.

Usage

uuid(
  n = 1,
  version = 7,
  namespace = NULL,
  name = NULL,
  node = NULL,
  random = NULL,
  time = NULL
)

Arguments

n

The number of UUIDs.

version

1, 4, 6, 7 or 8.

namespace, name

Reserved for the name-based versions 3 and 5.

node

For versions 1 and 6, six raw bytes to use as the node instead of the session's random one.

random

NULL to draw from the operating system, or exactly the bytes the version needs, for tests and reproducible fixtures (with time): 16 per value for versions 4 and 8; 10 per value for version 7 (2 seed the counter at a new millisecond, 8 fill the 62 random bits); for versions 1 and 6, 2 bytes of clock sequence and, without node, 6 bytes of node.

time

NULL for the current time, or a POSIXct (or a double of milliseconds since 1970) of length 1 or n.

Details

  • Version 7 (the default): 48 bits of milliseconds, a 12-bit counter and 62 random bits. Values from one session strictly increase (RFC 9562 section 6.2, method 1): within a millisecond the counter increments, and when it would overflow the millisecond advances by one.

  • Version 4: 122 random bits.

  • Versions 1 and 6: the time in 100 ns ticks, a 14-bit clock sequence and a 48-bit node. The clock sequence and node are random, drawn once per session, and the node has its multicast bit set so it is never mistaken for a hardware address (RFC 9562 section 6.10). Values from one session strictly increase in time.

  • Version 8: the caller's 122 bits, through random.

A clock that runs back by up to the option zuid.rollback_tolerance (seconds, 10 by default) keeps generation increasing from the last value. A time that runs back is treated as the clock is, so within the tolerance a version 7 value keeps the latest time so far. Further back, version 7 restarts at the new time and versions 1 and 6 increment the clock sequence. Values that would pass the last instant the time field holds are a zuid_overflow_error.

With both time and random given, a call is a pure function of its arguments: the same arguments give the same UUIDs, and the session's monotonic state is neither used nor changed. Values within the call still increase.

Versions 3 and 5 hash a name and are not generated yet; parsing them works. Version 2 is not generated: RFC 9562 leaves it to DCE Security.

Value

A zuid vector of n UUIDs.

Examples

uuid(3)
uuid(2, version = 4)
uuid(version = 7, time = as.POSIXct("2022-02-22 19:22:22", tz = "UTC"))

The nil and max UUIDs

Description

The nil and max UUIDs

Usage

uuid_nil()

uuid_max()

Value

A zuid vector of one UUID: all bits zero (uuid_nil()) or all bits one (uuid_max()).

Examples

uuid_nil()
uuid_max()

Generate XIDs, ObjectIds and Snowflakes

Description

xid() generates XIDs: seconds since 1970, a 3-byte machine id, a 2-byte process id and a 3-byte counter. The reference derives the machine id from the host name through MD5; zuid draws three random bytes once per session instead, and machine takes the reference's bytes when they matter. The process id is R's, masked to 16 bits. The counter starts at a random value once per session and increments, wrapping at 2^24.

Usage

xid(n = 1, machine = NULL, process = Sys.getpid(), random = NULL, time = NULL)

objectid(n = 1, random = NULL, time = NULL)

snowflake(n = 1, layout, worker, time = NULL, rollback = c("error", "reset"))

Arguments

n

The number of UUIDs.

machine

For xid(), three raw bytes, or NULL for the session's random ones.

process

For xid(), the process id, Sys.getpid() by default.

random

NULL, or for reproducible values: 6 bytes for xid() (machine, then the counter's start) and 8 for objectid() (the random value, then the counter's start), used for this call only.

time

NULL for the current time, or a POSIXct (or a double of milliseconds since 1970) of length 1 or n.

layout

An id_layout().

worker

The node fields' values: one number when the layout has one node field, else a named list, such as list(datacenter = 1, worker = 7).

rollback

For snowflake(), what to do when the clock (or time) runs back further than the tolerance: "error" or "reset".

Details

objectid() generates BSON ObjectIds: seconds, a 5-byte random value drawn once per session, and a 3-byte counter started at a random value.

snowflake() generates Snowflakes under a layout. worker sets every node field, since duplicate node ids across machines are what Snowflake exists to prevent and only the caller can rule them out. The sequence starts at zero each tick and increments within it; when it overflows, generation moves to the next tick. One sequence serves every node value of a layout, so values for different workers interleave without repeats. A clock back by up to the option zuid.clock_tolerance (seconds, 0.01 by default) keeps the last tick. Further back, rollback = "error" raises zuid_clock_error, and rollback = "reset" restarts the layout's generator at the new time, which may repeat values made before.

Value

A zuid vector of n values.

Examples

xid(2)
objectid(2)
snowflake(2, id_layout("twitter"), list(datacenter = 1, worker = 7))

Describe this build of zuid

Description

Reports the installed version, the generated tables compiled into it, the entropy source and the monotonic generation state.

Usage

zuid_info()

Value

A list with elements:

version

the package version, as a package_version.

tables

a data frame with one row per generated table: its name, the upstream repo, commit and path, the file's sha256, and the number of entries.

entropy

the operating-system entropy source in use: "getrandom", "getentropy", "BCryptGenRandom" or "arc4random_buf", or "/dev/urandom" once a Linux kernel without getrandom(2) has fallen back to it.

state

the session's monotonic generation state: the last version 7 millisecond and counter, the last version 1 and 6 tick and clock sequence, and the last ULID millisecond, NA before the first value.

Examples

zuid_info()