Shared runtime catalog of codec implementations (ETS-backed).
Populated at application start (and again if this process restarts). Entries
carry a category and interface shape: binary codecs use the top-level
registry API, while spatial entries are dispatched through
ExCodecs.Spatial.
Crash behavior
The ETS table is owned by this Agent process. If the Agent crashes, the
table is destroyed and only the :register callback (built-ins) is replayed
on restart. Runtime third-party registrations made via register/3 or
register/5 are lost and must be re-registered by the caller. If the
Agent restarts while the table still exists (e.g. via a supervised
:restart_for_type), existing entries are preserved and only overwritten
by the callback.
Typical use
iex> ExCodecs.available_codecs()
[:blosc2, :bzip2, :gsplat, :lz4, :ply, :snappy, :spatial_binary, :zstd]
iex> ExCodecs.supports?(:zstd)
true
Summary
Functions
Sorted list of all registered names (including unavailable).
Sorted list of codec atoms with a non-nil module.
Sorted available catalog names in one category.
Returns %ExCodecs.Codec{} for name.
Lists %ExCodecs.Codec{} for a category atom (e.g. :compression).
Looks up {module, category, info} for name.
Registers a binary-interface module that exports encode/2 and decode/2.
Registers a module in the shared catalog with an explicit interface.
Registers a module with an explicit interface and optional metadata overrides.
Registers a known codec with module: nil (unavailable).
Registers a known codec as unavailable with an explicit interface.
Starts the registry Agent and optional re-registration callback.
Returns true if registered and module != nil.
Deletes a registry entry (tests / hot reload).
Functions
@spec all_codecs() :: [atom()]
Sorted list of all registered names (including unavailable).
Arguments
None.
Returns
A sorted [atom()], including entries whose module is nil.
Raises
May raise ArgumentError if the registry ETS table does not exist.
Example
iex> :ok = ExCodecs.CodecRegistry.register_unavailable(:documented_optional, :compression)
iex> :documented_optional in ExCodecs.CodecRegistry.all_codecs()
true
iex> ExCodecs.CodecRegistry.unregister(:documented_optional)
:ok
@spec available_codecs() :: [atom()]
Sorted list of codec atoms with a non-nil module.
Arguments
None.
Returns
A sorted [atom()]. Unavailable entries registered with
register_unavailable/2 are omitted.
Raises
May raise ArgumentError if the registry ETS table does not exist.
Example
iex> codecs = ExCodecs.CodecRegistry.available_codecs()
iex> codecs == Enum.sort(codecs) and :zstd in codecs
true
Sorted available catalog names in one category.
Arguments
category— category atom such as:compressionor:spatial
Returns
Available names with non-nil modules, sorted by name.
Raises
May raise ArgumentError if the registry table has not started.
Examples
iex> ExCodecs.CodecRegistry.available_codecs(:spatial)
[:gsplat, :ply, :spatial_binary]
@spec codec_info(atom()) :: {:ok, ExCodecs.Codec.t()} | {:error, :unsupported_codec}
Returns %ExCodecs.Codec{} for name.
Arguments
name(atom()) — codec registry key
Returns
{:ok, ExCodecs.Codec.t()}— metadata for a registered codec, including unavailable codecs{:error, :unsupported_codec}— no registry entry exists
Raises
Raises FunctionClauseError when name is not an atom. May raise
ArgumentError if the registry ETS table does not exist.
Example
iex> {:ok, %ExCodecs.Codec{name: :zstd, category: :compression}} =
...> ExCodecs.CodecRegistry.codec_info(:zstd)
iex> true
true
@spec codecs_by_category(atom()) :: [ExCodecs.Codec.t()]
Lists %ExCodecs.Codec{} for a category atom (e.g. :compression).
Arguments
category(atom()) — category to select, such as:compression
Returns
A [ExCodecs.Codec.t()] sorted by each struct's name. The list includes
unavailable entries in that category and is empty when none match.
Raises
Raises FunctionClauseError when category is not an atom. May raise
ArgumentError if the registry ETS table does not exist.
Example
iex> codecs = ExCodecs.CodecRegistry.codecs_by_category(:compression)
iex> Enum.all?(codecs, &match?(%ExCodecs.Codec{category: :compression}, &1))
true
iex> Enum.map(codecs, & &1.name) == Enum.sort(Enum.map(codecs, & &1.name))
true
@spec lookup(atom()) :: {:ok, {module() | nil, atom(), ExCodecs.Codec.t()}} | {:error, :unsupported_codec}
Looks up {module, category, info} for name.
Arguments
name(atom()) — codec registry key
Returns
{:ok, {module() | nil, atom(), ExCodecs.Codec.t()}}— implementation, category, and metadata for a registered name{:error, :unsupported_codec}— no entry exists forname
Raises
Raises FunctionClauseError when name is not an atom. May raise
ArgumentError if the registry ETS table does not exist.
Example
iex> {:ok, {module, :compression, info}} = ExCodecs.CodecRegistry.lookup(:zstd)
iex> {module, info.name}
{ExCodecs.Compression.Zstd, :zstd}
Registers a binary-interface module that exports encode/2 and decode/2.
Arguments
name(atom()) — registry key used for lookupsmodule(module()) — loaded module exportingencode/2anddecode/2category(atom()) — grouping key, such as:compression
Returns
:ok— metadata was stored, replacing any entry with the samename{:error, {:invalid_codec_module, module}}— the module cannot be loaded or does not export both codec callbacks
Raises
May raise ArgumentError if the registry ETS table does not exist. A codec's
optional public __codec_info__/0 function is called during registration and
any exception it raises propagates.
Examples
iex> :ok = ExCodecs.CodecRegistry.register(
...> :zstd,
...> ExCodecs.Compression.Zstd,
...> :compression
...> )
iex> ExCodecs.CodecRegistry.supports?(:zstd)
true
Registers a module in the shared catalog with an explicit interface.
:binary entries are dispatched by ExCodecs.encode/3 / decode/3.
:spatial entries are discoverable from the same catalog but dispatched by
ExCodecs.Spatial.
Arguments
name— catalog keymodule— module exportingencode/2anddecode/2category— grouping atom such as:compressionor:spatialinterface—:binaryor:spatial
Returns
:ok on registration or {:error, {:invalid_codec_module, module}}.
Raises
May raise ArgumentError if the registry table has not started, or propagate
an exception from a module's optional __codec_info__/0.
Examples
iex> :ok = ExCodecs.CodecRegistry.register(
...> :documented_ply,
...> ExCodecs.Spatial.Codec.PLY,
...> :spatial,
...> :spatial
...> )
iex> {:ok, info} = ExCodecs.CodecRegistry.codec_info(:documented_ply)
iex> {info.category, info.interface}
{:spatial, :spatial}
iex> ExCodecs.CodecRegistry.unregister(:documented_ply)
:ok
Registers a module with an explicit interface and optional metadata overrides.
Builds the stored %ExCodecs.Codec{} from name, module, category, and
interface, then merges capability fields from the module's optional
ExCodecs.Codec.__codec_info__/0 (when exported). Each key in metadata
overrides the corresponding field from __codec_info__/0.
Arguments
name(atom()) — catalog key (always stored; not taken from metadata)module(module()) — module exportingencode/2anddecode/2category(atom()) — grouping atom such as:compressionor:spatialinterface(:binary | :spatial) — public API shape for the entrymetadata(keyword()) — optional overrides for capability fields::native?(boolean()) — NIF-backed implementation:streaming?(boolean()) — incremental API available:configurable?(boolean()) — meaningful codec-specific options:version(String.t() | nil) — backend version string
Unknown keys are ignored. Omitted keys keep the value from
__codec_info__/0, ornilwhen that function is not exported.
Returns
:ok— metadata was stored, replacing any entry with the samename{:error, {:invalid_codec_module, module}}— the module cannot be loaded or does not export both codec callbacks
Raises
May raise ArgumentError if the registry ETS table does not exist. A codec's
optional __codec_info__/0 is called during registration and any exception
it raises propagates.
Persistence
This entry is stored in an ETS table owned by the registry Agent. If the
Agent crashes, runtime registrations are not replayed — only the
:register callback supplied at start_link/1 runs on restart. Re-register
third-party codecs from your own supervision tree if you need crash
survivability.
Examples
iex> :ok = ExCodecs.CodecRegistry.register(
...> :documented_spatial_binary,
...> ExCodecs.Spatial.Codec.Binary,
...> :spatial,
...> :spatial,
...> native?: false,
...> streaming?: false,
...> configurable?: false,
...> version: "EXCP 1"
...> )
iex> {:ok, info} = ExCodecs.CodecRegistry.codec_info(:documented_spatial_binary)
iex> {info.interface, info.version, info.native?}
{:spatial, "EXCP 1", false}
iex> ExCodecs.CodecRegistry.unregister(:documented_spatial_binary)
:ok
@spec start_link(keyword()) :: Agent.on_start()
Starts the registry Agent and optional re-registration callback.
Arguments
opts(keyword()) — accepts:register, a zero-arity function invoked after the named ETS table is created or cleared; it defaults tofn -> :ok end
Returns
{:ok, pid()}— the named registry Agent started and initialization ran{:error, {:already_started, pid()}}— the registry is already running{:error, reason}— Agent startup or the registration callback failed
Raises
With a valid keyword list, startup failures are returned by Agent. Passing
a non-keyword value can raise FunctionClauseError while reading options.
Example
A supervision tree normally starts the registry and supplies the callback:
children = [
{ExCodecs.CodecRegistry, register: &MyApp.Codecs.register_all/0}
]
Supervisor.start_link(children, strategy: :one_for_one)
Returns true if registered and module != nil.
Arguments
name(atom()) — registry key to test
Returns
true only when name is registered with a non-nil module; otherwise
false.
Raises
Raises FunctionClauseError when name is not an atom. May raise
ArgumentError if the registry ETS table does not exist.
Example
iex> ExCodecs.CodecRegistry.supports?(:zstd)
true
iex> ExCodecs.CodecRegistry.supports?(:unknown_codec)
false
@spec unregister(atom()) :: :ok
Deletes a registry entry (tests / hot reload).
Arguments
name(atom()) — registry key to remove
Returns
Always :ok, whether or not an entry existed.
Raises
Raises FunctionClauseError when name is not an atom. May raise
ArgumentError if the registry ETS table does not exist.
Example
iex> :ok = ExCodecs.CodecRegistry.register_unavailable(:temporary_codec, :compression)
iex> :ok = ExCodecs.CodecRegistry.unregister(:temporary_codec)
iex> ExCodecs.CodecRegistry.lookup(:temporary_codec)
{:error, :unsupported_codec}