ulid: Implementation of ULID, lexicographically sortable unique identifiers

[ bsd3, codec, data, database, library, program ] [ Propose Tags ]

Implementation of alizain's ULID identifier (https:/github.comalizain/ulid ). UUID can be suboptimal for many uses-cases because: It isn't the most character efficient way of encoding 128 bits of randomness UUID v1/v2 is impractical in many environments, as it requires access to a unique, stable MAC address UUID v3/v5 requires a unique seed and produces randomly distributed IDs, which can cause fragmentation in many data structures UUID v4 provides no other information than randomness which can cause fragmentation in many data structures Instead, herein is proposed ULID: 128-bit compatibility 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)


[Skip to Readme]
Versions [RSS] [faq] 0.1.0.0, 0.2.0.0, 0.3.0.0
Dependencies base (>=4.7 && <5), binary, bytestring, crockford, crypto-api, random, time, ulid [details]
License BSD-3-Clause
Copyright 2017 Steve Kollmansberger
Author Steve Kollmansberger
Maintainer steve@kolls.net
Category Data
Home page https://github.com/steven777400/ulid
Source repo head: git clone https://github.com/steven777400/ulid.git
Uploaded by steven777400 at 2017-06-10T19:42:34Z
Distributions NixOS:0.3.0.0
Executables ulid-exe
Downloads 1606 total (22 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Hackage Matrix CI
Docs available [build log]
Last success reported on 2017-06-10 [all 1 reports]

Modules

[Index]

Downloads

Maintainer's Corner

For package maintainers and hackage trustees

Candidates


Readme for ulid-0.1.0.0

[back to package description]

Ulid implementation in Haskell

Lexicographically sortable, 128-bit identifier with 48-bit timestamp and 80 random bits. Canonically encoded as a 26 character string, as opposed to the 36 character UUID.

Original implementation and spec: https://github.com/alizain/ulid/

Universally Unique Lexicographically Sortable Identifier

UUID can be suboptimal for many uses-cases because:

  • It isn't the most character efficient way of encoding 128 bits of randomness
  • UUID v1/v2 is impractical in many environments, as it requires access to a unique, stable MAC address
  • UUID v3/v5 requires a unique seed and produces randomly distributed IDs, which can cause fragmentation in many data structures
  • UUID v4 provides no other information than randomness which can cause fragmentation in many data structures

Instead, herein is proposed ULID:

  • 128-bit compatibility 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)

Usage

A simple usage example:

module Main where

import           Data.ULID

main :: IO ()
main = do
    -- Derive a ULID using the current time and default random number generator
    ulid1 <- getULID
    print ulid1

    -- Derive a ULID using a specified time and default random number generator
    ulid2 <- getULIDTime 1469918176.385 -- POSIX Time, specified to the millisecond
    print ulid2

As per the spec, it is also possible to use a cryptographically-secure random number generator to contribute the randomness. However, the programmer must manage the generator on their own. Example:

module Main where

import           Data.ULID

import qualified Crypto.Random       as CR
import qualified Data.ULID.Random    as UR
import qualified Data.ULID.TimeStamp as TS

main :: IO ()
main = do     
    -- This default instantiation may not be sufficiently secure, see the docs 
    -- https://hackage.haskell.org/package/crypto-api-0.13.2/docs/Crypto-Random.html
    g <- (CR.newGenIO :: IO CR.SystemRandom)

    -- Generate time stamp from current time
    t <- TS.getULIDTimeStamp
    
    let ulid3 = case UR.mkCryptoULIDRandom g of
            Left err        -> error $ show err
            Right (rnd, g2) -> ULID t rnd   -- use g2, etc, to continue generating secure ULIDs
    print ulid3