ExCodecs.CodecRegistry (ex_codecs v0.2.0)

Copy Markdown View Source

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.

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 known codec with module: nil (unavailable).

Starts the registry Agent and optional re-registration callback.

Returns true if registered and module != nil.

Deletes a registry entry (tests / hot reload).

Functions

all_codecs()

@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

available_codecs()

@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

available_codecs(category)

@spec available_codecs(atom()) :: [atom()]

Sorted available catalog names in one category.

Arguments

  • category — category atom such as :compression or :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]

codec_info(name)

@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

codecs_by_category(category)

@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

lookup(name)

@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 for name

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}

register(name, module, category)

@spec register(atom(), module(), atom()) :: :ok | {:error, term()}

Registers a binary-interface module that exports encode/2 and decode/2.

Arguments

  • name (atom()) — registry key used for lookups
  • module (module()) — loaded module exporting encode/2 and decode/2
  • category (atom()) — grouping key, such as :compression

Returns

  • :ok — metadata was stored, replacing any entry with the same name
  • {: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

register(name, module, category, interface)

@spec register(atom(), module(), atom(), :binary | :spatial) :: :ok | {:error, term()}

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 key
  • module — module exporting encode/2 and decode/2
  • category — grouping atom such as :compression or :spatial
  • interface:binary or :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

register_unavailable(name, category)

@spec register_unavailable(atom(), atom()) :: :ok

Registers a known codec with module: nil (unavailable).

Arguments

  • name (atom()) — known codec's registry key
  • category (atom()) — grouping key, such as :compression

Returns

Always :ok after storing a %ExCodecs.Codec{module: nil} entry.

Raises

May raise ArgumentError if the registry ETS table does not exist.

Example

iex> :ok = ExCodecs.CodecRegistry.register_unavailable(:example_optional, :compression)
iex> {:ok, info} = ExCodecs.CodecRegistry.codec_info(:example_optional)
iex> {info.module, ExCodecs.CodecRegistry.supports?(:example_optional)}
{nil, false}
iex> ExCodecs.CodecRegistry.unregister(:example_optional)
:ok

start_link(opts \\ [])

@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 to fn -> :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)

supports?(name)

@spec supports?(atom()) :: boolean()

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

unregister(name)

@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}