defmodule ZBase32 do @moduledoc ~S""" Z-Base-32: human-oriented base-32 encoding http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt """ use Bitwise @doc ~S""" Encodes a binary string into a z-base-32 encoded string. """ @spec encode(binary) :: String.t def encode(<<>>), do: <<>> def encode(data) when is_binary(data) do split = 5 * div(byte_size(data), 5) <> = data main = for <>, into: <<>>, do: <> case rest do <> -> <> <> -> <> <> -> <> <> -> <> <<>> -> main end end @doc ~S""" Decodes a z-base-32 encoded string into a binary string. """ @spec decode(String.t) :: {:ok, binary} | :error def decode(<<>>), do: {:ok, <<>>} def decode(string) when is_binary(string) do {:ok, do_decode(string)} rescue _ in [CaseClauseError, ArgumentError] -> :error end defp do_decode(string) do split = byte_size(string) - rem(byte_size(string), 8) <> = string main = for <>, into: <<>>, do: <> case rest do <> -> <> <> -> <> <> -> <> <> -> <> <> -> <> <<>> -> main end end alphabet = Enum.with_index 'ybndrfg8ejkmcpqxot1uwisza345h769' for {encoding, value} <- alphabet do defp enc(unquote(value)), do: unquote(encoding) defp dec(unquote(encoding)), do: unquote(value) end defp dec(c) do raise ArgumentError, "non-alphabet digit found: #{<>}" end end