/cl-ulid

ULID implementation in Common Lisp

Primary LanguageCommon LispApache License 2.0Apache-2.0

ULID implementation in Common Lisp

A ULID is a universally unique lexicographically sortable identifier.

It is:

  • 128-bit compatible with UUID
  • 1.21e+24 unique ULIDs per millisecond
  • Lexicographically sortable!
  • Canonically encoded as a 26 character string, as opposed to the 36 character UUID
  • Uses Crockford’s base32 for better efficiency and readability (5 bits per character)
  • Case insensitive
  • No special characters (URL safe)

In general the structure of a ULID is as follows:

01AN4Z07BY79KA1307SR9X4MV3
TimestampRandomness
48bits80bits

For more information have a look at the original specification.

Installation

cl-ulid is not in quicklisp. It will need to be installed in the local-projects quicklisp directory:

> cd /$USER_HOME/quicklisp/local-projects/
> git clone https://github.com/jolby/cl-ulid.git

Basic Usage at the REPL

CL-USER>(ql:quickload :cl-ulid)
> (:CL-ULID)
CL-USER> ;; (ulid:ulid) returns the values of a ULID encoded as a string as well as a byte array
CL-USER> (ulid::ulid)
>"01H7NR28J0FEDWV9G66ZRKJY4V"
#(1 137 235 129 34 64 123 155 205 166 6 55 241 57 120 155)
CL-USER> ;; (Retrieve the encoded values from the string or byte array
CL-USER> (let* ((ulid-generator (ulid:make-ulid-generator :random-number-fn (lambda (x) 1)))
                (time (ulid:get-unix-time-ms)))
           (multiple-value-bind (ulid-str ulid-bytes) (funcall ulid-generator time)
             (multiple-value-bind (ts random) (ulid:decode-to-values ulid-str)
               (assert (= ts time))
               (assert (= random 1)))
             (multiple-value-bind (ts random) (ulid:decode-to-values ulid-bytes)
               (assert (= ts time))
               (assert (= random 1))))
           (format nil "DONE~%"))

Strong Random

The default cl-ulid system uses ironclad’s strong-random for the RNG. It is very easy to provide another RNG source if desired. Look at the ironclad-random.lisp file to see how it is done.

Other Common Lisp implementations.

There is at least one other common lisp implementation that I know of: https://gitlab.com/colinstrickland/cms-ulid.git

Unfortunately, I was already in the middle of this implementation when I found that one. The code in that implementation seems cleaner than this project, but it probably never hurts to have more than one implementation to choose from.