spectra_codec behaviour (spectra v0.13.0)
View SourceSummary
Callbacks
Behaviour for custom codecs that extend spectra's encoding, decoding, and schema generation for specific types and formats.
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
-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().
-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.
-callback schema(Format :: atom(), CallerTypeInfo :: spectra:type_info(), TargetTypeRef :: spectra:sp_type_reference(), TargetType :: spectra:sp_type(), Config :: spectra:sp_config()) -> dynamic().
Functions
-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.
-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.
-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.