···11+v0.9.10 2025-03-10 La Forclaz (VS)
22+----------------------------------
33+44+- Install forgotten `index.mld` file.
55+- `uuidtrip`: handle `cmdliner` deprecations.
66+77+v0.9.9 2024-09-26 Zagreb
88+------------------------
99+1010+- Add `Uuidm.{v7,v7_ns}` to create time and random based V7 UUIDs.
1111+ Thanks to Robin Newton for the patch (#14) and Christian Linding
1212+ and Pau Ruiz Safont for the help.
1313+- Add `Uuidm.v7_[non_]monotonic_gen` V7 UUID generators.
1414+- Add `Uuidm.v8` to create V8 custom UUIDs.
1515+- Add `Uuidm.max` the RFC 9569 Max UUID.
1616+- Add `Uuidm.{variant,version,time_ms}` UUID property accessors.
1717+- Change `Uuidm.v4_gen` generation strategy.
1818+- Call `Random.State.make_self_init` lazily rather than during module
1919+ initialisation.
2020+- Documentation: clarified that `Random` based UUID generators are not stable
2121+ accross OCaml and Uuidm versions.
2222+- Deprecate `Uuidm.v`, use individual version constructors instead.
2323+- Deprecate type `Uuidm.version`.
2424+- Deprecate `Uuidm.pp_string` to `Uuidm.pp'`.
2525+- Deprecate `Uuidm.{to,of}_[mixed_endian_]bytes` to
2626+ `Uuidm.{to,of}_[mixed_endian_]binary_string` (follow `Stdlib` terminology).
2727+- Require OCaml 4.14.
2828+- `uuidtrip` set standard output to binary when outputing binary uuids.
2929+- `uuidtrip` add options `--v3`, `--v4`, `--v5`, `--v7`.
3030+- `uuidtrip` add support for time and random based v7 UUIDs generation.
3131+3232+v0.9.8 2022-02-09 La Forclaz (VS)
3333+---------------------------------
3434+3535+- Add deprecation warnings on what is already deprecated.
3636+- Require OCaml 4.08 and support 5.00 (Thanks to Kate @ki-ty-kate
3737+ for the patch).
3838+3939+4040+v0.9.7 2019-03-08 La Forclaz (VS)
4141+---------------------------------
4242+4343+- Add `Uuidm.v4`, creates random based V4 UUID using client provided
4444+ random bytes (#8). Thanks to François-René Rideau for suggesting and
4545+ David Kaloper Meršinjak for additional comments.
4646+- Add `Uuidm.{to,of}_mixed_endian_bytes`. Support for UEFI and
4747+ Microsoft's binary serialization of UUIDs.
4848+4949+5050+v0.9.6 2016-08-12 Zagreb
5151+------------------------
5252+5353+- Safe-string support. Thanks to Josh Allmann for the help.
5454+- Deprecate `Uuidm.create` in favor of `Uuidm.v`.
5555+- Deprecate `Uuidm.print` in favor of `Uuidm.pp_string`
5656+- Add `Uuidm.pp`.
5757+- Relicensed from BSD3 to ISC.
5858+- Build depend on topkg.
5959+- `uuidtrip` uses `Cmdliner` which becomes an optional dependency of
6060+ the package. The command line interface is unchanged except for long
6161+ options which have to be written with a double dash. Binary output
6262+ no longer adds an ending newline.
6363+6464+6565+v0.9.5 2012-08-05 Lausanne
6666+--------------------------
6767+6868+- OASIS 0.3.0 support.
6969+7070+7171+v0.9.4 2012-03-15 La Forclaz (VS)
7272+---------------------------------
7373+7474+- OASIS support.
7575+- New functions `Uuidm.v3` and `Uuidm.v5` that generate directly these
7676+ kinds of UUIDs.
7777+- New function `Uuidm.v4_gen` returns a function that generates
7878+ version 4 UUIDs with a client provided random state. Thanks to Lauri
7979+ Alanko for suggesting that `Random.make_self_init` may be too weak
8080+ for certain usages.
8181+8282+8383+v0.9.3 2008-08-01 Lausanne
8484+--------------------------
8585+8686+- POSIX compliant build shell script.
8787+8888+8989+v0.9.2 2008-07-30 Lausanne
9090+--------------------------
9191+9292+- Support for debian packaging. Thanks to Sylvain Le Gall.
9393+9494+9595+v0.9.1 2008-06-18 Lausanne
9696+--------------------------
9797+9898+- Minor internal cleanings.
9999+100100+101101+v0.9.0 2008-06-11 Lausanne
102102+--------------------------
103103+104104+- First release.
+6
vendor/opam/uuidm/DEVEL.md
···11+This project uses (perhaps the development version of) [`b0`] for
22+development. Consult [b0 occasionally] for quick hints on how to
33+perform common development tasks.
44+55+[`b0`]: https://erratique.ch/software/b0
66+[b0 occasionally]: https://erratique.ch/software/b0/doc/occasionally.html
+13
vendor/opam/uuidm/LICENSE.md
···11+Copyright (c) 2008 The uuidm programmers
22+33+Permission to use, copy, modify, and/or distribute this software for any
44+purpose with or without fee is hereby granted, provided that the above
55+copyright notice and this permission notice appear in all copies.
66+77+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
88+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
99+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1010+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1111+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1212+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1313+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+41
vendor/opam/uuidm/README.md
···11+Uuidm — Universally unique identifiers (UUIDs) for OCaml
22+========================================================
33+44+Uuidm is an OCaml library implementing 128 bits universally unique
55+identifiers version 3, 5 (named based with MD5, SHA-1 hashing), 4
66+(random based), 7 (time and random based) and 8 (custom) according to
77+[RFC 9562].
88+99+Uuidm has no dependency. It is distributed under the ISC license.
1010+1111+[RFC 9562]: https://www.rfc-editor.org/rfc/rfc9562
1212+1313+Homepage: <https://erratique.ch/software/uuidm>
1414+1515+## Installation
1616+1717+Uuidm can be installed with `opam`:
1818+1919+ opam install uuidm
2020+2121+If you don't use `opam` consult the [`opam`](opam) file for build
2222+instructions.
2323+2424+## Documentation
2525+2626+The documentation can be consulted [online] or via `odig doc uuidm`.
2727+2828+Questions are welcome but better asked on the [OCaml forum][ocaml-forum]
2929+than on the issue tracker.
3030+3131+[online]: https://erratique.ch/software/uuidm/doc/
3232+[ocaml-forum]: https://discuss.ocaml.org/
3333+3434+## Sample programs
3535+3636+The [`uuidtrip`] tool generates UUIDs and outputs them on stdout.
3737+3838+See also code in the [`test`] directory.
3939+4040+[`uuidtrip`]: test/uuidtrip.ml
4141+[`test`]: test/
···11+{0 Uuidm {%html: <span class="version">%%VERSION%%</span>%}}
22+33+{!Uuidm} implements 128 bits universally unique identifiers version 3,
44+5 (named based with MD5, SHA-1 hashing), 4 (random based), 7 (time and
55+random based) and 8 (custom) according according to
66+{{:https://www.rfc-editor.org/rfc/rfc9562} RFC 9562}.
77+88+See the {{!quick}quick start}.
99+1010+{1:uuidm_lib Library [uuidm]}
1111+1212+{!modules: Uuidm}
1313+1414+{1:quick Quick start}
1515+1616+{2:random_based Random V4 UUIDs}
1717+1818+The following [uuid] function generates V4 random UUIDs.
1919+2020+{[
2121+let uuid = Uuidm.v4_gen (Random.State.make_self_init ())
2222+let () = print_endline (Uuidm.to_string (uuid ()))
2323+let () = print_endline (Uuidm.to_string (uuid ()))
2424+]}
2525+2626+Make sure to read the {{!Uuidm.gen}warnings} about random generators.
2727+2828+{2:name_based Name based V5 UUIDs}
2929+3030+Name based V5 UUIDs can be used to generate [urn:uuid] URIs for atom
3131+feed {{:https://www.rfc-editor.org/rfc/rfc4287#section-4.2.6}entry
3232+IDs} to minimize the chances of feed replays.
3333+3434+First generate a random V4 UUID for the feed. For example with
3535+the code of the previous section or with:
3636+{@shell[
3737+> uuidtrip
3838+6228c5f9-7069-4519-9bf4-0b6e865f4c42
3939+]}
4040+4141+Store this UUID preciously and use it as your feed ID:
4242+4343+{[
4444+let feed_id ~feed_id = "urn:uuid:" ^ (Uuid.to_string feed_id)
4545+]}
4646+4747+For feed entry IDs, use the feed UUID as a V5 namespace and the immutable
4848+{{:https://www.rfc-editor.org/rfc/rfc4287#section-4.2.9}[atom:published]}
4949+value of the entry as the data to hash:
5050+5151+{[
5252+let entry_id ~feed_id ~rfc3339_stamp =
5353+ "urn:uuid:" ^ (Uuidm.to_string @@ Uuidm.v5 feed_id rfc3339_stamp)
5454+]}
5555+5656+This assumes that
5757+5858+{ol
5959+{- You do not publish two entries at exactly the same time.
6060+ {{:https://www.rfc-editor.org/rfc/rfc3339}RFC 3339} has
6161+ enough time granularity to ensure that.}
6262+{- You do not change your publication dates. In atom they must in fact
6363+ not change, updates to entries must be specified
6464+ in {{:https://www.rfc-editor.org/rfc/rfc4287#section-4.2.15}[atom:updated]}.}
6565+{- If you store publication dates as a raw POSIX timestamp be careful
6666+ to render them to RFC 3339 with a fixed time zone. Alternatively
6767+ you can directly use the decimal representation of the timestamp
6868+ as the data to hash.}}
6969+7070+{2:time_based Monotonic time based V7 UUIDs}
7171+7272+In order to generate monotonic time based V7 UUIDs we need to:
7373+7474+{ul
7575+{- Provide a millisecond precision monotonic POSIX clock. {!Unix.gettimeofday}
7676+ can provide a reasonable one but if your monotonicity requirements are
7777+ paramount, remember that it can go back in time.}
7878+{- Do something if the clock doesn't move between two UUID
7979+ generations. The {!Uuidm.v7_monotonic_gen} generator uses a counter which
8080+ allows to generate up to 4096 UUID per millisecond and returns [None] in case
8181+ of rollover during the millisecond. In the code below we {!Unix.sleepf}
8282+ for a millisecond if we reach the limit.}}
8383+8484+{[
8585+let uuid_monotonic =
8686+ let now_ms () = Int64.of_float (Unix.gettimeofday () *. 1000.) in
8787+ Uuidm.v7_monotonic_gen ~now_ms (Random.State.make_self_init ())
8888+8989+let rec uuid () = match uuid_monotonic () with
9090+| None -> (* Too many UUIDs generated in a ms *) Unix.sleepf 1e-3; uuid ()
9191+| Some uuid -> uuid
9292+9393+let () = print_endline (Uuidm.to_string (uuid ()))
9494+let () = print_endline (Uuidm.to_string (uuid ()))
9595+]}
9696+9797+Depending on your application {!Uuidm.v7_monotonic_gen} may be a bit
9898+too simplistic, you can easily implement all sorts of other
9999+{{:https://www.rfc-editor.org/rfc/rfc9562#name-monotonicity-and-counters}
100100+generation schemes} by using {!Uuidm.v7} or {!Uuidm.v7_ns} directly. Also, make
101101+sure to read the {{!Uuidm.gen}warnings} about generators.
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2008 The uuidm programmers. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+66+(* Bits *)
77+88+type bits62 = int64
99+type bits4 = int
1010+type bits12 = int
1111+1212+(* Hashing *)
1313+1414+let md5 = Digest.string
1515+let sha_1 s =
1616+ (* Based on pseudo-code of RFC 3174. Slow and ugly but does the job. *)
1717+ let sha_1_pad s =
1818+ let len = String.length s in
1919+ let blen = 8 * len in
2020+ let rem = len mod 64 in
2121+ let mlen = if rem > 55 then len + 128 - rem else len + 64 - rem in
2222+ let m = Bytes.create mlen in
2323+ Bytes.blit_string s 0 m 0 len;
2424+ Bytes.fill m len (mlen - len) '\x00';
2525+ Bytes.set m len '\x80';
2626+ if Sys.word_size > 32 then begin
2727+ Bytes.set_uint8 m (mlen - 8) (blen lsr 56 land 0xFF);
2828+ Bytes.set_uint8 m (mlen - 7) (blen lsr 48 land 0xFF);
2929+ Bytes.set_uint8 m (mlen - 6) (blen lsr 40 land 0xFF);
3030+ Bytes.set_uint8 m (mlen - 5) (blen lsr 32 land 0xFF);
3131+ end;
3232+ Bytes.set_uint8 m (mlen - 4) (blen lsr 24 land 0xFF);
3333+ Bytes.set_uint8 m (mlen - 3) (blen lsr 16 land 0xFF);
3434+ Bytes.set_uint8 m (mlen - 2) (blen lsr 8 land 0xFF);
3535+ Bytes.set_uint8 m (mlen - 1) (blen land 0xFF);
3636+ m
3737+ in
3838+ (* Operations on int32 *)
3939+ let ( &&& ) = ( land ) in
4040+ let ( lor ) = Int32.logor in
4141+ let ( lxor ) = Int32.logxor in
4242+ let ( land ) = Int32.logand in
4343+ let ( ++ ) = Int32.add in
4444+ let lnot = Int32.lognot in
4545+ let sl = Int32.shift_left in
4646+ let cls n x = (sl x n) lor (Int32.shift_right_logical x (32 - n)) in
4747+ (* Start *)
4848+ let m = sha_1_pad s in
4949+ let w = Array.make 16 0l in
5050+ let h0 = ref 0x67452301l in
5151+ let h1 = ref 0xEFCDAB89l in
5252+ let h2 = ref 0x98BADCFEl in
5353+ let h3 = ref 0x10325476l in
5454+ let h4 = ref 0xC3D2E1F0l in
5555+ let a = ref 0l in
5656+ let b = ref 0l in
5757+ let c = ref 0l in
5858+ let d = ref 0l in
5959+ let e = ref 0l in
6060+ for i = 0 to ((Bytes.length m) / 64) - 1 do (* For each block *)
6161+ (* Fill w *)
6262+ let base = i * 64 in
6363+ for j = 0 to 15 do w.(j) <- Bytes.get_int32_be m (base + (j * 4)); done;
6464+ (* Loop *)
6565+ a := !h0; b := !h1; c := !h2; d := !h3; e := !h4;
6666+ for t = 0 to 79 do
6767+ let f, k =
6868+ if t <= 19 then (!b land !c) lor ((lnot !b) land !d), 0x5A827999l else
6969+ if t <= 39 then !b lxor !c lxor !d, 0x6ED9EBA1l else
7070+ if t <= 59 then
7171+ (!b land !c) lor (!b land !d) lor (!c land !d), 0x8F1BBCDCl
7272+ else
7373+ !b lxor !c lxor !d, 0xCA62C1D6l
7474+ in
7575+ let s = t &&& 0xF in
7676+ if (t >= 16) then begin
7777+ w.(s) <- cls 1 begin
7878+ w.((s + 13) &&& 0xF) lxor
7979+ w.((s + 8) &&& 0xF) lxor
8080+ w.((s + 2) &&& 0xF) lxor
8181+ w.(s)
8282+ end
8383+ end;
8484+ let temp = (cls 5 !a) ++ f ++ !e ++ w.(s) ++ k in
8585+ e := !d;
8686+ d := !c;
8787+ c := cls 30 !b;
8888+ b := !a;
8989+ a := temp;
9090+ done;
9191+ (* Update *)
9292+ h0 := !h0 ++ !a;
9393+ h1 := !h1 ++ !b;
9494+ h2 := !h2 ++ !c;
9595+ h3 := !h3 ++ !d;
9696+ h4 := !h4 ++ !e
9797+ done;
9898+ let h = Bytes.create 20 in
9999+ let i2s h k i = Bytes.set_int32_be h k i in
100100+ i2s h 0 !h0;
101101+ i2s h 4 !h1;
102102+ i2s h 8 !h2;
103103+ i2s h 12 !h3;
104104+ i2s h 16 !h4;
105105+ Bytes.unsafe_to_string h
106106+107107+(* Uuids *)
108108+109109+type t = string (* 16 bytes *)
110110+111111+let make u ~version =
112112+ let b6 = (version lsl 4) lor ((Bytes.get_uint8 u 6) land 0b0000_1111) in
113113+ let b8 = 0b1000_0000 lor ((Bytes.get_uint8 u 8) land 0b0011_1111) in
114114+ Bytes.set_uint8 u 6 b6;
115115+ Bytes.set_uint8 u 8 b8;
116116+ Bytes.unsafe_to_string u
117117+118118+let make_named ~version digest ns n =
119119+ let hash = Bytes.unsafe_of_string (digest (ns ^ n)) in
120120+ make (Bytes.sub hash 0 16) ~version
121121+122122+let v3 ns n = make_named ~version:3 md5 ns n
123123+let v5 ns n = make_named ~version:5 sha_1 ns n
124124+let v4 b = make (Bytes.sub b 0 16) ~version:4
125125+let v7 ~time_ms ~rand_a ~rand_b =
126126+ let u = Bytes.create 16 in
127127+ Bytes.set_int64_be u 0 (Int64.shift_left time_ms 16);
128128+ Bytes.set_int16_be u 6 rand_a;
129129+ Bytes.set_int64_be u 8 rand_b;
130130+ make u ~version:7
131131+132132+let v7_ns ~time_ns ~rand_b =
133133+ let ns_in_ms = 1_000_000L in
134134+ let sub_ms_frac_multiplier = Int64.unsigned_div Int64.minus_one ns_in_ms in
135135+ let u = Bytes.create 16 in
136136+ (* RFC 9562 requires we use 48 bits for a timestamp in milliseconds, and
137137+ allows for 12 bits to store a sub-millisecond fraction. We get the
138138+ latter by multiplying to put the fraction in a 64-bit range, then
139139+ shifting into 12 bits. *)
140140+ let ms = Int64.unsigned_div time_ns ns_in_ms in
141141+ let ns = Int64.unsigned_rem time_ns ns_in_ms in
142142+ let sub_ms_frac =
143143+ Int64.shift_right_logical (Int64.mul ns sub_ms_frac_multiplier) 52
144144+ in
145145+ Bytes.set_int64_be u 0 (Int64.shift_left ms 16);
146146+ Bytes.set_int16_be u 6 (Int64.to_int sub_ms_frac);
147147+ Bytes.set_int64_be u 8 rand_b;
148148+ make u ~version:7
149149+150150+let v8 s =
151151+ let l = String.length s in
152152+ if l = 16 then make (Bytes.of_string s) ~version:8 else
153153+ invalid_arg (Printf.sprintf "expected 16 bytes but found: %d" l)
154154+155155+(* Generators *)
156156+157157+type posix_ms_clock = unit -> int64
158158+159159+let v4_random rstate =
160160+ let r0 = Random.State.bits64 rstate in
161161+ let r1 = Random.State.bits64 rstate in
162162+ let u = Bytes.create 16 in
163163+ Bytes.set_int64_be u 0 r0;
164164+ Bytes.set_int64_be u 8 r1;
165165+ make u ~version:4
166166+167167+let v4_gen rstate = function () -> v4_random rstate
168168+169169+let v7_non_monotonic_gen ~now_ms rstate =
170170+ fun () ->
171171+ let time_ms = now_ms () in
172172+ let rand_a = Random.State.bits (* 30 bits *) rstate in
173173+ let rand_b = Random.State.bits64 rstate in
174174+ v7 ~time_ms ~rand_a ~rand_b
175175+176176+let v7_monotonic_gen ~now_ms rstate =
177177+ let last_ms = ref 0L in
178178+ let count = ref 0 in
179179+ fun () ->
180180+ let time_ms = now_ms () in
181181+ let rand_b = Random.State.bits64 rstate in
182182+ if Int64.equal time_ms !last_ms then
183183+ let rand_a = incr count; !count in
184184+ if rand_a >= 4096 then None else Some (v7 ~time_ms ~rand_a ~rand_b)
185185+ else
186186+ (count := 0; last_ms := time_ms; Some (v7 ~time_ms ~rand_a:0 ~rand_b))
187187+188188+(* Constants *)
189189+190190+let nil = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
191191+let max = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
192192+let ns_dns = "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8"
193193+let ns_url = "\x6b\xa7\xb8\x11\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8"
194194+let ns_oid = "\x6b\xa7\xb8\x12\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8"
195195+let ns_X500 ="\x6b\xa7\xb8\x14\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8"
196196+197197+(* Properties *)
198198+199199+let variant u = (String.get_uint8 u 8) lsr 4
200200+let version u = (String.get_uint8 u 6) lsr 4
201201+let time_ms u =
202202+ let variant = variant u in
203203+ if not (0x8 <= variant && variant <= 0xB && version u = 7) then None else
204204+ Some (Int64.shift_right_logical (String.get_int64_be u 0) 16)
205205+206206+(* Predicates and comparisons *)
207207+208208+let equal = String.equal
209209+let compare = String.compare
210210+211211+(* Standard binary format *)
212212+213213+let to_binary_string s = s
214214+let of_binary_string ?(pos = 0) s =
215215+ let len = String.length s in
216216+ if pos + 16 > len then None else
217217+ if pos = 0 && len = 16 then Some s else
218218+ Some (String.sub s pos 16)
219219+220220+(* Mixed endian binary format *)
221221+222222+let mixed_swaps s =
223223+ let swap b i j =
224224+ let t = Bytes.get b i in
225225+ Bytes.set b i (Bytes.get b j);
226226+ Bytes.set b j t
227227+ in
228228+ let b = Bytes.of_string s in
229229+ swap b 0 3; swap b 1 2;
230230+ swap b 4 5; swap b 6 7;
231231+ Bytes.unsafe_to_string b
232232+233233+let to_mixed_endian_binary_string s = mixed_swaps s
234234+let of_mixed_endian_binary_string ?pos s =
235235+ Option.map mixed_swaps (of_binary_string ?pos s)
236236+237237+(* Unsafe conversions *)
238238+239239+let unsafe_of_binary_string u = u
240240+let unsafe_to_binary_string u = u
241241+242242+(* US-ASCII format *)
243243+244244+let of_string ?(pos = 0) s =
245245+ let len = String.length s in
246246+ if
247247+ pos + 36 > len || s.[pos + 8] <> '-' || s.[pos + 13] <> '-' ||
248248+ s.[pos + 18] <> '-' || s.[pos + 23] <> '-'
249249+ then
250250+ None
251251+ else try
252252+ let u = Bytes.create 16 in
253253+ let i = ref 0 in
254254+ let j = ref pos in
255255+ let ihex c =
256256+ let i = Char.code c in
257257+ if i < 0x30 then raise Exit else
258258+ if i <= 0x39 then i - 0x30 else
259259+ if i < 0x41 then raise Exit else
260260+ if i <= 0x46 then i - 0x37 else
261261+ if i < 0x61 then raise Exit else
262262+ if i <= 0x66 then i - 0x57 else
263263+ raise Exit
264264+ in
265265+ let byte s j = Char.unsafe_chr (ihex s.[j] lsl 4 lor ihex s.[j + 1]) in
266266+ while (!i < 4) do Bytes.set u !i (byte s !j); j := !j + 2; incr i done;
267267+ incr j;
268268+ while (!i < 6) do Bytes.set u !i (byte s !j); j := !j + 2; incr i done;
269269+ incr j;
270270+ while (!i < 8) do Bytes.set u !i (byte s !j); j := !j + 2; incr i done;
271271+ incr j;
272272+ while (!i < 10) do Bytes.set u !i (byte s !j); j := !j + 2; incr i done;
273273+ incr j;
274274+ while (!i < 16) do Bytes.set u !i (byte s !j); j := !j + 2; incr i done;
275275+ Some (Bytes.unsafe_to_string u)
276276+ with Exit -> None
277277+278278+let to_string ?(upper = false) u =
279279+ let hbase = if upper then 0x37 else 0x57 in
280280+ let hex hbase i = Char.unsafe_chr (if i < 10 then 0x30 + i else hbase + i) in
281281+ let s = Bytes.of_string "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" in
282282+ let i = ref 0 in
283283+ let j = ref 0 in
284284+ let byte s i c =
285285+ Bytes.set s i @@ hex hbase (c lsr 4);
286286+ Bytes.set s (i + 1) @@ hex hbase (c land 0x0F)
287287+ in
288288+ while (!j < 4) do byte s !i (Char.code u.[!j]); i := !i + 2; incr j; done;
289289+ incr i;
290290+ while (!j < 6) do byte s !i (Char.code u.[!j]); i := !i + 2; incr j; done;
291291+ incr i;
292292+ while (!j < 8) do byte s !i (Char.code u.[!j]); i := !i + 2; incr j; done;
293293+ incr i;
294294+ while (!j < 10) do byte s !i (Char.code u.[!j]); i := !i + 2; incr j; done;
295295+ incr i;
296296+ while (!j < 16) do byte s !i (Char.code u.[!j]); i := !i + 2; incr j; done;
297297+ Bytes.unsafe_to_string s
298298+299299+(* Pretty-printing *)
300300+301301+let pp ppf u = Format.pp_print_string ppf (to_string u)
302302+let pp' ~upper ppf u = Format.pp_print_string ppf (to_string ~upper u)
303303+304304+(* Deprecated *)
305305+306306+let default_seed = lazy (Random.State.make_self_init ())
307307+308308+type version = [ `V3 of t * string | `V4 | `V5 of t * string ]
309309+let v = function
310310+| `V4 -> v4_random (Lazy.force default_seed)
311311+| `V3 (ns, n) -> v3 ns n
312312+| `V5 (ns, n) -> v5 ns n
313313+314314+let create = v (* deprecated *)
315315+let pp_string ?upper ppf u = Format.pp_print_string ppf (to_string ?upper u)
316316+let print = pp_string (* deprecated *)
317317+let to_bytes = to_binary_string
318318+let of_bytes = of_binary_string
319319+let to_mixed_endian_bytes = to_mixed_endian_binary_string
320320+let of_mixed_endian_bytes = of_mixed_endian_binary_string
321321+let unsafe_of_bytes = unsafe_of_binary_string
322322+let unsafe_to_bytes = unsafe_to_binary_string
+272
vendor/opam/uuidm/src/uuidm.mli
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2008 The uuidm programmers. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+66+(** Universally unique identifiers (UUIDs).
77+88+ [Uuidm] implements 128 bits universally unique identifiers version
99+ 3, 5 (name based with MD5, SHA-1 hashing), 4 (random based), 7
1010+ (random and timestamp based) and 8 (custom) according to
1111+ {{:https://www.rfc-editor.org/rfc/rfc9562}RFC 9562}.
1212+1313+ See the {{!page-index.quick}quick start}. *)
1414+1515+(** {1:bits Bits} *)
1616+1717+type bits4 = int
1818+(** The type for 4 bits stored in the 4 lower bits of an [int] value.
1919+ The higher bits are either set to zero or ignored on use. *)
2020+2121+type bits12 = int
2222+(** The type for 12 bits stored in the 12 lower bits of an [int] value.
2323+ The higher bits are either set to zero or ignored on use. *)
2424+2525+type bits62 = int64
2626+(** The type for 62 bits stored in the 62 lower bits of an [int64] value.
2727+ The higher bits are either set to zero or ignored on use. *)
2828+2929+(** {1:uuids UUIDs} *)
3030+3131+type t
3232+(** The type for UUIDs. *)
3333+3434+val v3 : t -> string -> t
3535+(** [v3 ns n] is a
3636+ {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-3}V3 UUID}
3737+ (name based with MD5 hashing) named by [n] and namespaced by [ns]. *)
3838+3939+val v4 : bytes -> t
4040+(** [v4 b] is a {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-4}
4141+ V4 UUID} (random based) that uses the first 16 bytes of
4242+ [b] for randomness. See also {!v4_gen}.
4343+4444+ {b Warning.} The randomness is seen literally in the result. *)
4545+4646+val v5 : t -> string -> t
4747+(** [v5 ns n] is a
4848+ {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-5}V5 UUID}
4949+ (name based with SHA-1 hashing) named by [n] and
5050+ namespaced by [ns]. See {{!page-index.name_based}this example}. *)
5151+5252+val v7 : time_ms:int64 -> rand_a:bits12 -> rand_b:bits62 -> t
5353+(** [v7 ~time_ms ~rand_a ~rand_b] is a
5454+ {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-7}V7 UUID}
5555+ (time and random based) using the 64-bit millisecond POSIX timestamp
5656+ [time_ms] and random bits [rand_a] and [rand_b]. See also {!v7_ns},
5757+ {!v7_non_monotonic_gen} and {!v7_monotonic_gen}.
5858+5959+ {b Warning.} The timestamp and the randomness are seen literally
6060+ in the result. *)
6161+6262+val v7_ns : time_ns:int64 -> rand_b:bits62 -> t
6363+(** [v7_ns ~time_ns ~rand_b] is a
6464+ {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-7}V7
6565+ UUID} (time and random based) using the {e unsigned} 64-bit
6666+ nanosecond POSIX timestamp [time_ns] and random bits [rand_b]. The
6767+ [rand_a] field is used with the timestamp's submillisecond precision
6868+ with about 244 nanoseconds resolution. See also {!v7}.
6969+7070+ {b Warning.} The timestamp and the randomness are seen literally in
7171+ the result. *)
7272+7373+val v8 : string -> t
7474+(** [v8 s] is a {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-8}
7575+ V8 UUID} (custom) that uses the 16 bytes of [s] but overwrites the
7676+ {!version} and {!variant} bits to make it a propert V8 UUID. Raises
7777+ [Invalid_argument] if the length of [s] is not [16]. *)
7878+7979+(** {1:gen Generators}
8080+8181+ {b Warning.} If you use the generators take into account the following
8282+ points:
8383+8484+ {ul
8585+ {- Sequences of UUIDs are generated with {!Random}. This is
8686+ suitably random but {e predictable} by an observer. Use the
8787+ base constuctors with random bytes generated by a
8888+ cryptographically secure pseudorandom number generator (CSPRNG) if that
8989+ is an issue.}
9090+ {- Sequences of UUIDs generated from a given {!Random.State.t}
9191+ value are not guaranteed to be stable across OCaml or Uuidm versions.
9292+ Use the base constructors with your own
9393+ pseudorandom number generator if that is an issue.}
9494+ {- Sequences of UUIDs generated using a {!posix_ms_clock} assume
9595+ the clock is monotonic in order to generate monotonic UUIDs.
9696+ If you derive it from {!Unix.gettimeofday} this may not be the case.}} *)
9797+9898+type posix_ms_clock = unit -> int64
9999+(** The type for millisecond precision POSIX time clocks. *)
100100+101101+val v4_gen : Random.State.t -> (unit -> t)
102102+(** [v4_gen state] is a function generating {!v4} UUIDs using
103103+ random [state]. See {{!page-index.random_based}this example}. *)
104104+105105+val v7_non_monotonic_gen :
106106+ now_ms:posix_ms_clock -> Random.State.t -> (unit -> t)
107107+(** [v7_non_monotonic_gen ~now_ms state] is a function generating
108108+ {!v7} UUIDs using [now_ms] for the timestamp [time_ms] and random [state]
109109+ for [rand_a] and [rand_b]. UUIDs generated in the same millisecond
110110+ may not be be monotonic. Use {!v7_monotonic_gen} for that. *)
111111+112112+val v7_monotonic_gen :
113113+ now_ms:posix_ms_clock -> Random.State.t -> (unit -> t option)
114114+(** [v7_monotonic_gen ~posix_now_ms state] is a function that
115115+ generates monotonic {!v7} UUIDs using [now_ms] for the timestamp
116116+ [time_ms], [rand_a] as a counter if the clock did not move between
117117+ two UUID generations and [random] state for [rand_b]. This allows
118118+ to generate up to 4096 monotonic UUIDs per millisecond. [None] is
119119+ returned if the counter rolls over before the millisecond
120120+ increments. See {{!page-index.time_based}this example}.*)
121121+122122+(** {1:constants Constants} *)
123123+124124+val nil : t
125125+(** [nil] is the
126126+ {{:https://www.rfc-editor.org/rfc/rfc9562#name-nil-uuid}nil} UUID. *)
127127+128128+val max : t
129129+(** [max] is the {{:https://www.rfc-editor.org/rfc/rfc9562#name-max-uuid}max}
130130+ UUID. *)
131131+132132+val ns_dns : t
133133+(** [ns_dns] is the DNS namespace UUID. *)
134134+135135+val ns_url : t
136136+(** [ns_url] is the URL namespace UUID. *)
137137+138138+val ns_oid : t
139139+(** [ns_oid] is the ISO OID namespace UUID. *)
140140+141141+val ns_X500 : t
142142+(** [ns_dn] is the X.500 DN namespace UUID. *)
143143+144144+(** {1:properties Properties} *)
145145+146146+val variant : t -> bits4
147147+(** [variant u] is the
148148+ {{:https://www.rfc-editor.org/rfc/rfc9562#name-variant-field}variant field}
149149+ of [u], including the "don't-care" values. *)
150150+151151+val version : t -> bits4
152152+(** [version u] is the
153153+ {{:https://www.rfc-editor.org/rfc/rfc9562#name-version-field}version field}
154154+ of [u]. *)
155155+156156+val time_ms : t -> int64 option
157157+(** [time_ms u] is the
158158+ {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-version-7}
159159+ [unit_ts_ms]} millisecond POSIX timestamp of [u] as a 64-bit
160160+ integer. This is [None] if [u] is not a V7 UUID. *)
161161+162162+(** {1:preds Predicates and comparisons} *)
163163+164164+val equal : t -> t -> bool
165165+(** [equal u u'] is [true] iff [u] and [u'] are equal. *)
166166+167167+val compare : t -> t -> int
168168+(** [compare] is the binary order on UUIDs. *)
169169+170170+(** {1:fmt_binary Standard binary format}
171171+172172+ This is the binary format mandated by
173173+ {{:https://www.rfc-editor.org/rfc/rfc9562#name-uuid-format}RFC 9562}. *)
174174+175175+val of_binary_string : ?pos:int -> string -> t option
176176+(** [of_binary_string pos s] is the UUID represented by the 16 bytes starting
177177+ at [pos] (defaults to [0]) in [s]. No particular checks are
178178+ performed on the bytes. The result is [None] if the string is not
179179+ long enough. *)
180180+181181+val to_binary_string : t -> string
182182+(** [to_binary_string u] is [u] as a 16 bytes long string. *)
183183+184184+(** {1:fmt_binary_mixed Mixed-endian binary format}
185185+186186+ This is the binary format in which the three first fields of UUIDs
187187+ (which are oblivious to this module) are read and written in
188188+ little-endian. This corresponds to how UEFI or Microsoft formats
189189+ UUIDs. *)
190190+191191+val of_mixed_endian_binary_string : ?pos:int -> string -> t option
192192+(** [of_mixed_endian_binary_string] is like {!of_bytes} but decodes
193193+ the mixed endian serialization. *)
194194+195195+val to_mixed_endian_binary_string : t -> string
196196+(** [to_mixed_endian_binary_string] is like {!to_bytes} but encodes
197197+ the mixed endian serialization. *)
198198+199199+(**/**)
200200+val unsafe_of_binary_string : string -> t
201201+val unsafe_to_binary_string : t -> string
202202+(**/**)
203203+204204+(** {1:fmt_ascii US-ASCII format} *)
205205+206206+val of_string : ?pos:int -> string -> t option
207207+(** [of_string pos s] converts the substring of [s] starting at [pos]
208208+ (defaults to [0]) of the form ["XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"]
209209+ where X is a lower or upper case hexadecimal number to an
210210+ UUID. The result is [None] if a parse error occurs. Any extra
211211+ characters after are ignored. *)
212212+213213+val to_string : ?upper:bool -> t -> string
214214+(** [to_string u] is [u] as a string of the form
215215+ ["XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"] where X is a lower
216216+ (or upper if [upper] is [true]) case hexadecimal number. *)
217217+218218+val pp : Format.formatter -> t -> unit
219219+(** [pp ppf u] formats [u] with {!to_string} on [ppf]. *)
220220+221221+val pp' : upper:bool -> Format.formatter -> t -> unit
222222+(** [pp' ~upper ppf u] formats [u] with {!to_string}[ ~upper] on [ppf]. *)
223223+224224+(** {1:deprecated Deprecated} *)
225225+226226+type[@ocaml.deprecated "Use the version specific Uuidm.v* functions."] version =
227227+[ `V3 of t * string (** Name based with MD5 hashing *)
228228+| `V4 (** Random based *)
229229+| `V5 of t * string (** Name based with SHA-1 hasing *) ]
230230+(** The type for UUID versions and generation parameters.
231231+ {ul
232232+ {- [`V3] and [`V5] specify a namespace and a name for the generation.}
233233+ {- [`V4] is random based with a private state seeded with
234234+ {!Stdlib.Random.State.make_self_init}. Use {!v4_gen} to specify
235235+ your own seed. Use {!v4} to specify your own randomness.
236236+237237+ {b Warning.} The sequence resulting from repeatedly calling
238238+ [v `V4] is random but predictable see {!v4_gen}.}} *)
239239+240240+[@@@alert "-deprecated"]
241241+242242+val v : version -> t
243243+[@@ocaml.deprecated "Use the version specific Uuidm.v* functions."]
244244+245245+val pp_string : ?upper:bool -> Format.formatter -> t -> unit
246246+[@@ocaml.deprecated "Use Uuidm.pp' instead"]
247247+248248+val of_bytes : ?pos:int -> string -> t option
249249+[@@ocaml.deprecated "Use Uuidm.of_binary_string instead"]
250250+251251+val to_bytes : t -> string
252252+[@@ocaml.deprecated "Use Uuidm.to_binary_string instead"]
253253+254254+val of_mixed_endian_bytes : ?pos:int -> string -> t option
255255+[@@ocaml.deprecated "Use Uuidm.of_mixed_endian_binary_string instead"]
256256+257257+val to_mixed_endian_bytes : t -> string
258258+[@@ocaml.deprecated "Use Uuidm.to_mixed_endian_binary_string instead"]
259259+260260+(**/**)
261261+val print : ?upper:bool -> Format.formatter -> t -> unit (* deprecated *)
262262+[@@ocaml.deprecated "Use Uuidm.pp_string instead"]
263263+264264+val create : version -> t (* deprecated *)
265265+[@@ocaml.deprecated "Use Uuidm.v instead"]
266266+267267+val unsafe_of_bytes : string -> t
268268+[@@ocaml.deprecated "Use Uuidm.unsafe_of_binary_string instead"]
269269+270270+val unsafe_to_bytes : t -> string
271271+[@@ocaml.deprecated "Use Uuidm.unsafe_to_binary_string instead"]
272272+(**/**)
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2024 The uuidm programmers. All rights reserved.
33+ SPDX-License-Identifier: CC0-1.0
44+ ---------------------------------------------------------------------------*)
55+66+(* Code from the quick start *)
77+88+let uuid = Uuidm.v4_gen (Random.State.make_self_init ())
99+let () = print_endline (Uuidm.to_string (uuid ()))
1010+let () = print_endline (Uuidm.to_string (uuid ()))
1111+1212+let feed_id ~feed_id = "urn:uuid:" ^ (Uuidm.to_string feed_id)
1313+let entry_id ~feed_id ~rfc3339_stamp =
1414+ "urn:uuid:" ^ (Uuidm.to_string @@ Uuidm.v5 feed_id rfc3339_stamp)
1515+1616+let uuid_monotonic =
1717+ let now_ms () = Int64.of_float (Unix.gettimeofday () *. 1000.) in
1818+ Uuidm.v7_monotonic_gen ~now_ms (Random.State.make_self_init ())
1919+2020+let rec uuid () = match uuid_monotonic () with
2121+| None -> (* Too many UUIDs generated in a ms *) Unix.sleepf 1e-3; uuid ()
2222+| Some uuid -> uuid
2323+2424+let () = print_endline (Uuidm.to_string (uuid ()))
2525+let () = print_endline (Uuidm.to_string (uuid ()))
+39
vendor/opam/uuidm/test/perf.ml
···11+(* This code is in the public domain *)
22+33+let str = Printf.sprintf
44+let exec = Filename.basename Sys.executable_name
55+66+let main () =
77+ let usage =
88+ str "Usage: %s [OPTION]...\n\
99+ \ UUID performance tests.\n\
1010+ Options:" exec
1111+ in
1212+ let n = ref 10_000_000 in
1313+ let v = ref `V4 in
1414+ let cstr = ref false in
1515+ let options = [
1616+ "-n", Arg.Set_int n,
1717+ "<int> Number of ids to generate";
1818+ "-str", Arg.Set cstr,
1919+ " Also convert UUIDs to strings";
2020+ "-r", Arg.Unit (fun () -> v := `V4),
2121+ " Random based UUID version 4 (default)";
2222+ "-md5", Arg.Unit (fun () -> v := `V3 (Uuidm.ns_dns,"www.example.org")),
2323+ " MD5 name based UUID version 3";
2424+ "-sha1", Arg.Unit (fun () -> v := `V5 (Uuidm.ns_dns,"www.example.org")),
2525+ " SHA-1 name based UUID version 5"; ]
2626+ in
2727+ Arg.parse (Arg.align options) (fun _ -> ()) usage;
2828+ let uuid = match !v with
2929+ | `V4 -> Uuidm.v4_gen (Random.State.make_self_init ())
3030+ | `V3 (ns, n) -> fun () -> Uuidm.v3 ns n
3131+ | `V5 (ns, n) -> fun () -> Uuidm.v5 ns n
3232+ in
3333+ let f = match !cstr with
3434+ | true -> fun version -> ignore (Uuidm.to_string (uuid ()))
3535+ | false -> fun version -> ignore (uuid ())
3636+ in
3737+ for i = 1 to !n do f v done
3838+3939+let () = main ()
···11+(*---------------------------------------------------------------------------
22+ Copyright (c) 2008 The uuidm programmers. All rights reserved.
33+ SPDX-License-Identifier: ISC
44+ ---------------------------------------------------------------------------*)
55+66+let strf = Printf.sprintf
77+88+let gen ~version ~ns ~name ~upper ~binary =
99+ let u = match version with
1010+ | `V3 -> Uuidm.v3 ns name
1111+ | `V4 -> Uuidm.v4_gen (Random.State.make_self_init ()) ()
1212+ | `V5 -> Uuidm.v5 ns name
1313+ | `V7 ->
1414+ let now_ms () = Int64.of_float (Unix.gettimeofday () *. 1000.) in
1515+ Uuidm.v7_non_monotonic_gen ~now_ms (Random.State.make_self_init ()) ()
1616+ in
1717+ let s = match binary with
1818+ | true -> Uuidm.to_binary_string u
1919+ | false -> strf "%s\n" (Uuidm.to_string ~upper u)
2020+ in
2121+ let () = Out_channel.set_binary_mode stdout binary in
2222+ print_string s; flush stdout
2323+2424+(* Command line interface *)
2525+2626+open Cmdliner
2727+open Cmdliner.Term.Syntax
2828+2929+let version =
3030+ let v3 =
3131+ let doc =
3232+ "Generate a MD5 name based UUID version 3, see option $(b,--name)." in
3333+ `V3, Arg.info ["v3"; "md5"] ~doc
3434+ in
3535+ let v4 =
3636+ let doc = "Generate a random based UUID version 4 (default)." in
3737+ `V4, Arg.info ["v4"; "r"; "random"] ~doc
3838+ in
3939+ let v5 =
4040+ let doc =
4141+ "Generate a SHA-1 name based UUID version 5, see option $(b,--name)."
4242+ in
4343+ `V5, Arg.info ["v5"; "sha1"] ~doc
4444+ in
4545+ let v7 =
4646+ let doc = "Generate a time and random based UUID version 7." in
4747+ `V7, Arg.info ["v7"] ~doc
4848+ in
4949+ Arg.(value & vflag `V4 [v3; v4; v5; v7])
5050+5151+let ns =
5252+ let ns_arg =
5353+ let parse s = match Uuidm.of_string s with
5454+ | None -> Error (strf "%S: could not parse namespace UUID" s)
5555+ | Some ns -> Ok ns
5656+ in
5757+ Arg.conv' ~docv:"UUID" (parse, Uuidm.pp)
5858+ in
5959+ let doc = "Namespace UUID for name based UUIDs (version 4 or 5).
6060+ Defaults to the DNS namespace UUID."
6161+ in
6262+ Arg.(value & opt ns_arg Uuidm.ns_dns & info ["ns"; "namespace"] ~doc)
6363+6464+let name =
6565+ let doc = "Name for name based UUIDs (version 4 or 5)." in
6666+ Arg.(value & opt string "www.example.org" & info ["name"] ~doc)
6767+6868+let upper =
6969+ let doc = "Output hexadecimal letters in uppercase" in
7070+ Arg.(value & flag & info ["u"; "uppercase"] ~doc)
7171+7272+let binary =
7373+ let doc = "Output the UUID as its 16 bytes binary representation." in
7474+ Arg.(value & flag & info ["b"; "binary"] ~doc)
7575+7676+let cmd =
7777+ let doc = "Generates universally unique identifiers (UUIDs)" in
7878+ let man = [
7979+ `S "DESCRIPTION";
8080+ `P "$(tname) generates 128 bits universally unique identifiers version
8181+ 3, 5 (name based with MD5, SHA-1 hashing), 4 (random based) and
8282+ 7 (time and random based) according to RFC 9562.";
8383+ `P "Invoked without any option, a random based version 4 UUID is \
8484+ generated and written on stdout.";
8585+ `S "SEE ALSO";
8686+ `P "P. Leach et al. Universally Unique IDentifiers (UUIDs),
8787+ 2024. $(i,https://www.rfc-editor.org/rfc/rfc9562)";
8888+ `S "BUGS";
8989+ `P "This program is distributed with the Uuidm OCaml library. \
9090+ See $(i,https://erratique.ch/software/uuidm) for contact \
9191+ information."; ]
9292+ in
9393+ Cmd.v (Cmd.info "uuidtrip" ~version:"%%VERSION%%" ~doc ~man) @@
9494+ let+ version and+ ns and+ name and+ upper and+ binary in
9595+ gen ~version ~ns ~name ~upper ~binary
9696+9797+let main () = Cmd.eval cmd
9898+9999+let () = if !Sys.interactive then () else exit (main ())