CrockfordBase32

Module VersionHex Docs

Crockford Base32 encoding and decoding for integers and bitstrings in Elixir. It supports non-negative integers, arbitrary bitstrings, optional check symbols, and fixed-width encoders.

See Crockford's Base32 specification for the format.

Installation

def deps do
[
{:crockford_base32, "~> 0.9"}
]
end

Quick start

iex> CrockfordBase32.encode(1234)
"16J"
iex> CrockfordBase32.encode("abc", checksum: true, split_size: 3)
"C5H-66C"
iex> CrockfordBase32.decode_to_integer("16-j")
{:ok, 1234}
iex> CrockfordBase32.decode_to_bitstring("C5H66C", checksum: true)
{:ok, "abc"}
iex> CrockfordBase32.encode(<<5::size(3)>>)
"M"

Options and decoding

The default output alphabet is 0123456789ABCDEFGHJKMNPQRSTVWXYZ. Check symbols additionally use *~$=U.

Fixed-width encoding

Generate fixed-width encode/1 and decode/1 functions when the input has a known bit width. decode/1 always returns a bitstring with the configured width.

ULID: a 128-bit integer

A ULID combines a 48-bit Unix timestamp in milliseconds with 80 bits of randomness. Use type: :integer to preserve the numeric leading-zero padding required by its 26-character representation.

defmodule MyApp.ULID.Base32 do
use CrockfordBase32,
bits_size: 128,
type: :integer
end
timestamp_ms = 1_648_103_085_000
randomness = <<0::size(80)>>
ulid = <<timestamp_ms::unsigned-size(48), randomness::bitstring>>
encoded = MyApp.ULID.Base32.encode(ulid)
# "01FYX9JMY80000000000000000"
{:ok, ^ulid} = MyApp.ULID.Base32.decode(encoded)

TypeID: a 130-bit bitstring

A TypeID suffix is 26 lowercase Base32 symbols. It represents two leading zero bits followed by a 128-bit UUID, so use a fixed-width bitstring codec with TypeID's lowercase alphabet:

defmodule MyApp.TypeID.Base32 do
use CrockfordBase32,
bits_size: 130,
alphabet: ~c"0123456789abcdefghjkmnpqrstvwxyz"
end

The variable-length decoder cannot infer this 130-bit width and returns 128 bits for the sample suffix. The fixed-width decoder preserves all 130 bits:

suffix = "01hy3b3hq5fmevjn8me7c4hzdm"
{:ok, variable_width} = CrockfordBase32.decode_to_bitstring(suffix)
bit_size(variable_width)
# 128
{:ok, type_id} = MyApp.TypeID.Base32.decode(suffix)
bit_size(type_id)
# 130
MyApp.TypeID.Base32.encode(type_id)
# "01hy3b3hq5fmevjn8me7c4hzdm"

Credits

Thanks to these implementations and references: