1:- module(uuid, [random_uuid/1, uuid_atom/2, uuid/1, uuid/2]).    2:- use_module(library(crypto), [crypto_n_random_bytes/2, hex_bytes/2]).    3:- use_module(library(list_util), [split/3]).    4
    5% given a list of bytes in big-endian form, convert them to an integer
    6bytes_integer(Bs, N) :-
    7    foldl([B, N0, N1]>>(N1 is N0<<8 + B), Bs, 0, N).
    8
    9unsigned64_signed64(Un, Si) :-
   10    integer(Un),
   11    Un >= 0x8000_0000_0000_0000,
   12    !,
   13    Inv is 0xffff_ffff_ffff_ffff - Un,
   14    Si is -Inv - 1.
   15unsigned64_signed64(Un, Si) :-
   16    integer(Si),
   17    Si < 0,
   18    !,
   19    Inv is -Si - 1,
   20    Un is 0xffff_ffff_ffff_ffff - Inv.
   21unsigned64_signed64(Un, Un).
 random_uuid(-UUID) is det
UUID is a random version-4 UUID, represented as uuid(High64, Low64).
   25random_uuid(uuid(Hi, Lo)) :-
   26    crypto_n_random_bytes(8, HiBytes),
   27    bytes_integer(HiBytes, Hi64),
   28    % Set version in 4 sig bits of time_hi_and_version
   29    Hi_ is Hi64 /\ \ (0b1111 << 12 ),
   30    HiUn is Hi_ \/ (4 << 12),
   31    unsigned64_signed64(HiUn, Hi),
   32
   33    crypto_n_random_bytes(8, LoBytes),
   34    bytes_integer(LoBytes, Lo64),
   35    % Set 2 sig bits of clock_seq_hi_res to 0 & 1
   36    Lo_ is Lo64 /\ \ (1 << (64-6)),
   37    LoUn is Lo_ \/ (1 << (64-7)),
   38    unsigned64_signed64(LoUn, Lo).
 uuid_atom(-UUID, +Atom) is semidet
uuid_atom(+UUID, -Atom) is det
Atom is equal to the hexadecimal representation of the version-4 UUID
   43uuid_atom(uuid(Hi_, Lo_), A) :-
   44    integer(Hi_), integer(Lo_), !,
   45    unsigned64_signed64(Hi, Hi_),
   46    unsigned64_signed64(Lo, Lo_),
   47    TimeLow is (Hi >> 32),
   48    TimeMid is (Hi >> 16) /\ 0xffff,
   49    TimeHi is Hi /\ 0xffff,
   50    ClockSeq is (Lo >> 48) /\ 0xffff,
   51    Node is Lo /\ 0xffff_ffff_ffff,
   52    format(atom(TL), '~`0t~16r~8|', [TimeLow]),
   53    format(atom(TM), '~`0t~16r~4|', [TimeMid]),
   54    format(atom(TH), '~`0t~16r~4|', [TimeHi]),
   55    format(atom(CS), '~`0t~16r~4|', [ClockSeq]),
   56    format(atom(N), '~`0t~16r~12|', [Node]),
   57    atomic_list_concat([TL, TM, TH, CS, N], '-', A).
   58uuid_atom(uuid(Hi, Lo), A) :-
   59    atom(A), !,
   60    atom_chars(A, Chars),
   61    split(Chars, '-', CharParts),
   62    maplist(atom_chars, AtomParts, CharParts),
   63    maplist(hex_bytes, AtomParts, Bytes),
   64    maplist(bytes_integer, Bytes, Nums),
   65    [TimeLow, TimeMid, TimeHi, ClockSeq, Node] = Nums,
   66    Hi_ is TimeLow << 32 + TimeMid << 16 + TimeHi,
   67    Lo_ is ClockSeq << 48 + Node,
   68    unsigned64_signed64(Hi_, Hi),
   69    unsigned64_signed64(Lo_, Lo).
 uuid(-UUID) is det
Create a new, random v4 UUID as the atom representation. Copying the API of the built-in library(uuid)
   74uuid(UUID) :-
   75    random_uuid(U),
   76    uuid_atom(U, UUID).
 uuid(-UUID, +Options) is det
Copying the API of the built-in library(uuid)
   80uuid(_UUID, Options) :-
   81    member(version(V), Options),
   82    V \= 4, !,
   83    throw(error(domain_error(4, V),
   84                context(uuid/2, 'Only version 4 UUIDs supported'))).
   85uuid(UUID, Options) :-
   86    memberchk(format(integer), Options), !,
   87    random_uuid(uuid(SHi, SLo)),
   88    unsigned64_signed64(Hi, SHi),
   89    unsigned64_signed64(Lo, SLo),
   90    UUID is Hi << 64 + Lo.
   91uuid(UUID, _Options) :-
   92    uuid(UUID)