272 lines
10 KiB
OCaml
272 lines
10 KiB
OCaml
(*---------------------------------------------------------------------------
|
|
Copyright (c) 2008 The uuidm programmers. All rights reserved.
|
|
SPDX-License-Identifier: ISC
|
|
---------------------------------------------------------------------------*)
|
|
|
|
(** Universally unique identifiers (UUIDs).
|
|
|
|
[Uuidm] implements 128 bits universally unique identifiers version
|
|
3, 5 (name based with MD5, SHA-1 hashing), 4 (random based), 7
|
|
(random and timestamp based) and 8 (custom) according to
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562}RFC 9562}.
|
|
|
|
See the {{!page-index.quick}quick start}. *)
|
|
|
|
(** {1:bits Bits} *)
|
|
|
|
type bits4 = int
|
|
(** The type for 4 bits stored in the 4 lower bits of an [int] value.
|
|
The higher bits are either set to zero or ignored on use. *)
|
|
|
|
type bits12 = int
|
|
(** The type for 12 bits stored in the 12 lower bits of an [int] value.
|
|
The higher bits are either set to zero or ignored on use. *)
|
|
|
|
type bits62 = int64
|
|
(** The type for 62 bits stored in the 62 lower bits of an [int64] value.
|
|
The higher bits are either set to zero or ignored on use. *)
|
|
|
|
(** {1:uuids UUIDs} *)
|
|
|
|
type t
|
|
(** The type for UUIDs. *)
|
|
|
|
val v3 : t -> string -> t
|
|
(** [v3 ns n] is a
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-3}V3 UUID}
|
|
(name based with MD5 hashing) named by [n] and namespaced by [ns]. *)
|
|
|
|
val v4 : bytes -> t
|
|
(** [v4 b] is a {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-4}
|
|
V4 UUID} (random based) that uses the first 16 bytes of
|
|
[b] for randomness. See also {!v4_gen}.
|
|
|
|
{b Warning.} The randomness is seen literally in the result. *)
|
|
|
|
val v5 : t -> string -> t
|
|
(** [v5 ns n] is a
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-5}V5 UUID}
|
|
(name based with SHA-1 hashing) named by [n] and
|
|
namespaced by [ns]. See {{!page-index.name_based}this example}. *)
|
|
|
|
val v7 : time_ms:int64 -> rand_a:bits12 -> rand_b:bits62 -> t
|
|
(** [v7 ~time_ms ~rand_a ~rand_b] is a
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-7}V7 UUID}
|
|
(time and random based) using the 64-bit millisecond POSIX timestamp
|
|
[time_ms] and random bits [rand_a] and [rand_b]. See also {!v7_ns},
|
|
{!v7_non_monotonic_gen} and {!v7_monotonic_gen}.
|
|
|
|
{b Warning.} The timestamp and the randomness are seen literally
|
|
in the result. *)
|
|
|
|
val v7_ns : time_ns:int64 -> rand_b:bits62 -> t
|
|
(** [v7_ns ~time_ns ~rand_b] is a
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-7}V7
|
|
UUID} (time and random based) using the {e unsigned} 64-bit
|
|
nanosecond POSIX timestamp [time_ns] and random bits [rand_b]. The
|
|
[rand_a] field is used with the timestamp's submillisecond precision
|
|
with about 244 nanoseconds resolution. See also {!v7}.
|
|
|
|
{b Warning.} The timestamp and the randomness are seen literally in
|
|
the result. *)
|
|
|
|
val v8 : string -> t
|
|
(** [v8 s] is a {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-8}
|
|
V8 UUID} (custom) that uses the 16 bytes of [s] but overwrites the
|
|
{!version} and {!variant} bits to make it a propert V8 UUID. Raises
|
|
[Invalid_argument] if the length of [s] is not [16]. *)
|
|
|
|
(** {1:gen Generators}
|
|
|
|
{b Warning.} If you use the generators take into account the following
|
|
points:
|
|
|
|
{ul
|
|
{- Sequences of UUIDs are generated with {!Random}. This is
|
|
suitably random but {e predictable} by an observer. Use the
|
|
base constuctors with random bytes generated by a
|
|
cryptographically secure pseudorandom number generator (CSPRNG) if that
|
|
is an issue.}
|
|
{- Sequences of UUIDs generated from a given {!Random.State.t}
|
|
value are not guaranteed to be stable across OCaml or Uuidm versions.
|
|
Use the base constructors with your own
|
|
pseudorandom number generator if that is an issue.}
|
|
{- Sequences of UUIDs generated using a {!posix_ms_clock} assume
|
|
the clock is monotonic in order to generate monotonic UUIDs.
|
|
If you derive it from {!Unix.gettimeofday} this may not be the case.}} *)
|
|
|
|
type posix_ms_clock = unit -> int64
|
|
(** The type for millisecond precision POSIX time clocks. *)
|
|
|
|
val v4_gen : Random.State.t -> (unit -> t)
|
|
(** [v4_gen state] is a function generating {!v4} UUIDs using
|
|
random [state]. See {{!page-index.random_based}this example}. *)
|
|
|
|
val v7_non_monotonic_gen :
|
|
now_ms:posix_ms_clock -> Random.State.t -> (unit -> t)
|
|
(** [v7_non_monotonic_gen ~now_ms state] is a function generating
|
|
{!v7} UUIDs using [now_ms] for the timestamp [time_ms] and random [state]
|
|
for [rand_a] and [rand_b]. UUIDs generated in the same millisecond
|
|
may not be be monotonic. Use {!v7_monotonic_gen} for that. *)
|
|
|
|
val v7_monotonic_gen :
|
|
now_ms:posix_ms_clock -> Random.State.t -> (unit -> t option)
|
|
(** [v7_monotonic_gen ~posix_now_ms state] is a function that
|
|
generates monotonic {!v7} UUIDs using [now_ms] for the timestamp
|
|
[time_ms], [rand_a] as a counter if the clock did not move between
|
|
two UUID generations and [random] state for [rand_b]. This allows
|
|
to generate up to 4096 monotonic UUIDs per millisecond. [None] is
|
|
returned if the counter rolls over before the millisecond
|
|
increments. See {{!page-index.time_based}this example}.*)
|
|
|
|
(** {1:constants Constants} *)
|
|
|
|
val nil : t
|
|
(** [nil] is the
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562#name-nil-uuid}nil} UUID. *)
|
|
|
|
val max : t
|
|
(** [max] is the {{:https://www.rfc-editor.org/rfc/rfc9562#name-max-uuid}max}
|
|
UUID. *)
|
|
|
|
val ns_dns : t
|
|
(** [ns_dns] is the DNS namespace UUID. *)
|
|
|
|
val ns_url : t
|
|
(** [ns_url] is the URL namespace UUID. *)
|
|
|
|
val ns_oid : t
|
|
(** [ns_oid] is the ISO OID namespace UUID. *)
|
|
|
|
val ns_X500 : t
|
|
(** [ns_dn] is the X.500 DN namespace UUID. *)
|
|
|
|
(** {1:properties Properties} *)
|
|
|
|
val variant : t -> bits4
|
|
(** [variant u] is the
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562#name-variant-field}variant field}
|
|
of [u], including the "don't-care" values. *)
|
|
|
|
val version : t -> bits4
|
|
(** [version u] is the
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562#name-version-field}version field}
|
|
of [u]. *)
|
|
|
|
val time_ms : t -> int64 option
|
|
(** [time_ms u] is the
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-7}
|
|
[unit_ts_ms]} millisecond POSIX timestamp of [u] as a 64-bit
|
|
integer. This is [None] if [u] is not a V7 UUID. *)
|
|
|
|
(** {1:preds Predicates and comparisons} *)
|
|
|
|
val equal : t -> t -> bool
|
|
(** [equal u u'] is [true] iff [u] and [u'] are equal. *)
|
|
|
|
val compare : t -> t -> int
|
|
(** [compare] is the binary order on UUIDs. *)
|
|
|
|
(** {1:fmt_binary Standard binary format}
|
|
|
|
This is the binary format mandated by
|
|
{{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-format}RFC 9562}. *)
|
|
|
|
val of_binary_string : ?pos:int -> string -> t option
|
|
(** [of_binary_string pos s] is the UUID represented by the 16 bytes starting
|
|
at [pos] (defaults to [0]) in [s]. No particular checks are
|
|
performed on the bytes. The result is [None] if the string is not
|
|
long enough. *)
|
|
|
|
val to_binary_string : t -> string
|
|
(** [to_binary_string u] is [u] as a 16 bytes long string. *)
|
|
|
|
(** {1:fmt_binary_mixed Mixed-endian binary format}
|
|
|
|
This is the binary format in which the three first fields of UUIDs
|
|
(which are oblivious to this module) are read and written in
|
|
little-endian. This corresponds to how UEFI or Microsoft formats
|
|
UUIDs. *)
|
|
|
|
val of_mixed_endian_binary_string : ?pos:int -> string -> t option
|
|
(** [of_mixed_endian_binary_string] is like {!of_bytes} but decodes
|
|
the mixed endian serialization. *)
|
|
|
|
val to_mixed_endian_binary_string : t -> string
|
|
(** [to_mixed_endian_binary_string] is like {!to_bytes} but encodes
|
|
the mixed endian serialization. *)
|
|
|
|
(**/**)
|
|
val unsafe_of_binary_string : string -> t
|
|
val unsafe_to_binary_string : t -> string
|
|
(**/**)
|
|
|
|
(** {1:fmt_ascii US-ASCII format} *)
|
|
|
|
val of_string : ?pos:int -> string -> t option
|
|
(** [of_string pos s] converts the substring of [s] starting at [pos]
|
|
(defaults to [0]) of the form ["XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"]
|
|
where X is a lower or upper case hexadecimal number to an
|
|
UUID. The result is [None] if a parse error occurs. Any extra
|
|
characters after are ignored. *)
|
|
|
|
val to_string : ?upper:bool -> t -> string
|
|
(** [to_string u] is [u] as a string of the form
|
|
["XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"] where X is a lower
|
|
(or upper if [upper] is [true]) case hexadecimal number. *)
|
|
|
|
val pp : Format.formatter -> t -> unit
|
|
(** [pp ppf u] formats [u] with {!to_string} on [ppf]. *)
|
|
|
|
val pp' : upper:bool -> Format.formatter -> t -> unit
|
|
(** [pp' ~upper ppf u] formats [u] with {!to_string}[ ~upper] on [ppf]. *)
|
|
|
|
(** {1:deprecated Deprecated} *)
|
|
|
|
type[@ocaml.deprecated "Use the version specific Uuidm.v* functions."] version =
|
|
[ `V3 of t * string (** Name based with MD5 hashing *)
|
|
| `V4 (** Random based *)
|
|
| `V5 of t * string (** Name based with SHA-1 hasing *) ]
|
|
(** The type for UUID versions and generation parameters.
|
|
{ul
|
|
{- [`V3] and [`V5] specify a namespace and a name for the generation.}
|
|
{- [`V4] is random based with a private state seeded with
|
|
{!Stdlib.Random.State.make_self_init}. Use {!v4_gen} to specify
|
|
your own seed. Use {!v4} to specify your own randomness.
|
|
|
|
{b Warning.} The sequence resulting from repeatedly calling
|
|
[v `V4] is random but predictable see {!v4_gen}.}} *)
|
|
|
|
[@@@alert "-deprecated"]
|
|
|
|
val v : version -> t
|
|
[@@ocaml.deprecated "Use the version specific Uuidm.v* functions."]
|
|
|
|
val pp_string : ?upper:bool -> Format.formatter -> t -> unit
|
|
[@@ocaml.deprecated "Use Uuidm.pp' instead"]
|
|
|
|
val of_bytes : ?pos:int -> string -> t option
|
|
[@@ocaml.deprecated "Use Uuidm.of_binary_string instead"]
|
|
|
|
val to_bytes : t -> string
|
|
[@@ocaml.deprecated "Use Uuidm.to_binary_string instead"]
|
|
|
|
val of_mixed_endian_bytes : ?pos:int -> string -> t option
|
|
[@@ocaml.deprecated "Use Uuidm.of_mixed_endian_binary_string instead"]
|
|
|
|
val to_mixed_endian_bytes : t -> string
|
|
[@@ocaml.deprecated "Use Uuidm.to_mixed_endian_binary_string instead"]
|
|
|
|
(**/**)
|
|
val print : ?upper:bool -> Format.formatter -> t -> unit (* deprecated *)
|
|
[@@ocaml.deprecated "Use Uuidm.pp_string instead"]
|
|
|
|
val create : version -> t (* deprecated *)
|
|
[@@ocaml.deprecated "Use Uuidm.v instead"]
|
|
|
|
val unsafe_of_bytes : string -> t
|
|
[@@ocaml.deprecated "Use Uuidm.unsafe_of_binary_string instead"]
|
|
|
|
val unsafe_to_bytes : t -> string
|
|
[@@ocaml.deprecated "Use Uuidm.unsafe_to_binary_string instead"]
|
|
(**/**)
|