spectra_codec behaviour (spectra v0.13.0)

View Source

Summary

Functions

Decodes Data via a registered codec for TargetModule, or returns continue.

Encodes Data via a registered codec for TargetModule, or returns continue.

Returns the schema for TargetModule via a registered codec, or continue.

Callbacks

decode(Format, CallerTypeInfo, TargetTypeRef, TargetType, Input, Config)

-callback decode(Format :: atom(),
                 CallerTypeInfo :: spectra:type_info(),
                 TargetTypeRef :: spectra:sp_type_reference(),
                 TargetType :: spectra:sp_type(),
                 Input :: dynamic(),
                 Config :: spectra:sp_config()) ->
                    spectra:codec_decode_result().

encode(Format, CallerTypeInfo, TargetTypeRef, TargetType, Data, Config)

-callback encode(Format :: atom(),
                 CallerTypeInfo :: spectra:type_info(),
                 TargetTypeRef :: spectra:sp_type_reference(),
                 TargetType :: spectra:sp_type(),
                 Data :: dynamic(),
                 Config :: spectra:sp_config()) ->
                    spectra:codec_encode_result().

Behaviour for custom codecs that extend spectra's encoding, decoding, and schema generation for specific types and formats.

Registering a codec

Codecs are registered in the application environment before use:

application:set_env(spectra, codecs, #{
    {my_module, {type, my_type, 0}} => my_codec
}).

Alternatively, add -behaviour(spectra_codec) to the module that defines the type and spectra will discover the codec automatically at load time.

Callback arguments

Every callback receives two type-related arguments for inspecting the type in context.

CallerTypeInfo :: spectra:type_info() — caller's module type information

CallerTypeInfo is the type information of the module where the type traversal is currently taking place. This allows the codec to recursively encode/decode user-defined generic arguments that might be defined locally in that module.

TargetType :: spectra:sp_type() — instantiation node with type-variable bindings

TargetType is the type node from the traversal at the point where the codec was invoked. For generic types this is the reference node — #sp_user_type_ref{} or #sp_remote_type{} — and it carries the concrete type-variable bindings of that specific instantiation. Use spectra_type:type_args/1 to extract them. Values supplied via -spectra(#{type_parameters => ...}) are not propagated onto reference nodes (#sp_user_type_ref{} / #sp_remote_type{}), so spectra_type:parameters/1 on TargetType returns undefined during mid-traversal dispatch. It is only reliable when TargetType is the resolved type definition (i.e. the codec is invoked from the spectra:encode/decode/schema entry points directly).

For a type written as dict:dict(binary(), integer()) the codec receives the #sp_remote_type{} node and can extract [BinaryType, IntegerType] to recursively encode/decode keys and values:

encode(json, CallerTypeInfo, _TargetTypeRef, TargetType, Data, Config) ->
    [KeyType, ValueType] = spectra_type:type_args(TargetType),
    encode_pairs(CallerTypeInfo, KeyType, ValueType, dict:to_list(Data), #{}, Config).

Note: when a codec is invoked from the spectra:encode/decode/schema entry points (rather than via mid-traversal dispatch), TargetType is the resolved type definition and spectra_type:type_args/1 returns []. In practice this only affects codecs for generic types — they are naturally called from the traversal where the reference node is available.

schema(Format, CallerTypeInfo, TargetTypeRef, TargetType, Config)

(optional)
-callback schema(Format :: atom(),
                 CallerTypeInfo :: spectra:type_info(),
                 TargetTypeRef :: spectra:sp_type_reference(),
                 TargetType :: spectra:sp_type(),
                 Config :: spectra:sp_config()) ->
                    dynamic().

Functions

try_codec_decode(Format, CallerTypeInfo, TargetModule, TargetTypeRef, TargetType, Data, Config)

-spec try_codec_decode(Format :: atom(),
                       CallerTypeInfo :: spectra:type_info(),
                       TargetModule :: module(),
                       TargetTypeRef :: spectra:sp_type_reference(),
                       TargetType :: spectra:sp_type(),
                       Data :: dynamic(),
                       Config :: spectra:sp_config()) ->
                          spectra:codec_decode_result().

Decodes Data via a registered codec for TargetModule, or returns continue.

try_codec_encode(Format, CallerTypeInfo, TargetModule, TargetTypeRef, TargetType, Data, Config)

-spec try_codec_encode(Format :: atom(),
                       CallerTypeInfo :: spectra:type_info(),
                       TargetModule :: module(),
                       TargetTypeRef :: spectra:sp_type_reference(),
                       TargetType :: spectra:sp_type(),
                       Data :: dynamic(),
                       Config :: spectra:sp_config()) ->
                          spectra:codec_encode_result().

Encodes Data via a registered codec for TargetModule, or returns continue.

try_codec_schema(Format, CallerTypeInfo, TargetModule, TargetTypeRef, TargetType, Config)

-spec try_codec_schema(Format :: atom(),
                       CallerTypeInfo :: spectra:type_info(),
                       TargetModule :: module(),
                       TargetTypeRef :: spectra:sp_type_reference(),
                       TargetType :: spectra:sp_type(),
                       Config :: spectra:sp_config()) ->
                          dynamic() | continue.

Returns the schema for TargetModule via a registered codec, or continue.