thrift_generator_codec (thrift_generator v0.7.0)

View Source

Specialized binary-protocol wire codecs emitted into <mod>_types.erl.

For every struct, union and exception the module gets encode_<prefix>_wire/1 and decode_<prefix>_wire/1: direct binary-pattern code over the wire representation (maps keyed by binary field names), with the same contracts as thrift_runtime_binary:encode/2 and thrift_runtime_binary:decode/2. The module-level binary_codec/1 hands the function pair out by wire struct name; thrift_runtime_binary probes that export whenever it meets a {struct, {ref, Module, Name}} descriptor and dispatches to the specialized code, falling back to its descriptor-driven engine for modules without the export (hand-written descriptors, inline RPC param/result structs).

The generated code preserves the generic engine's observable semantics: identical bytes for identical wire values and identical error terms — missing_required_fields in declaration order on encode and ascending field-id order on decode, union_empty/union_multiple, field_type_mismatch, element_type_mismatch, map_type_mismatch, bad_map_size, bad_sequence_size, bad_string_length, the more-versus-error truncation distinction — and skips unknown field ids by wire type. The thrift_codec_test equivalence properties pin all of this against the generic engine.

Nesting: same-module struct references become direct calls to the sibling wire functions; cross-module references go through thrift_runtime_binary:encode/2 and decode/2, which re-enter the codec probe. Containers get private enc_*/dec_* helpers named after the rendered element type; enum members are inlined as case clauses at every use site.

Forms are built as raw erl_parse trees — patterns, binary segment options and guards have no convenient erl_syntax constructors — so erl_pp renders them; doc and spec attributes stay syntax trees like everywhere else in the emitter.

Summary

Functions

Shared with the compact/JSON codec emitters: every container node of a wire type, outermost first.

Shared with the compact/JSON codec emitters: the namespace prefix of the module being generated.

Shared with the compact/JSON codec emitters: the element type of a list or set container.

Shared with the compact/JSON codec emitters: numbers a module's distinct inline enum descriptors.

The -export/1 entries of the wire codecs: binary_codec/1 plus one pair per struct.

Every wire-codec form of the module: per-struct encode/decode functions, container helpers, binary_codec/1.

Shared with the compact/JSON codec emitters: renders a wire type as a helper-name fragment.

Shared with the compact/JSON codec emitters: joins the namespace prefix with a snake-case name.

Types

annotations()

-type annotations() :: #{binary() := true | binary()}.

ast_node()

-type ast_node() ::
          #thrift_generator_node{line :: non_neg_integer(),
                                 col :: non_neg_integer(),
                                 doc :: doc(),
                                 annotations :: erl_annotations(),
                                 payload :: term(),
                                 type_module :: module()}.

base_type()

-type base_type() :: bool | i8 | i16 | i32 | i64 | double | string | binary | uuid.

const_value()

-type const_value() ::
          {ref, Name :: binary()} |
          boolean() |
          integer() |
          float() |
          binary() |
          {list, [const_value()]} |
          {map, [{const_value(), const_value()}]}.

constant()

-type constant() ::
          #thrift_generator_constant{name :: constant_name(),
                                     type :: thrift_type(),
                                     value :: const_value()}.

constant_name()

-nominal constant_name() :: binary().

cpp_include()

-type cpp_include() :: #thrift_generator_cpp_include{path :: include_path()}.

doc()

-type doc() :: binary() | undefined.

document()

-type document() :: #thrift_generator_document{headers :: [ast_node()], definitions :: [ast_node()]}.

enum_()

-type enum_() :: #thrift_generator_enum{name :: enum_name(), values :: [enum_value()]}.

enum_name()

-nominal enum_name() :: binary().

enum_value()

-type enum_value() :: {Name :: binary(), Value :: integer() | undefined, annotations(), doc()}.

erl_annotations()

-type erl_annotations() :: #{atom() := true | binary()}.

exception_()

-type exception_() :: #thrift_generator_exception{name :: exception_name(), fields :: [ast_node()]}.

exception_name()

-nominal exception_name() :: binary().

field_()

-type field_() ::
          #thrift_generator_field{id :: integer() | undefined,
                                  required :: requiredness(),
                                  type :: thrift_type(),
                                  name :: field_name(),
                                  default :: const_value() | undefined}.

field_name()

-nominal field_name() :: binary().

function_()

-type function_() ::
          #thrift_generator_function{oneway :: boolean(),
                                     return_type :: thrift_type() | void,
                                     name :: function_name(),
                                     fields :: [ast_node()],
                                     throws :: [ast_node()]}.

function_name()

-nominal function_name() :: binary().

include_()

-type include_() :: #thrift_generator_include{path :: include_path()}.

include_path()

-nominal include_path() :: binary().

module_key()

-type module_key() :: binary().

namespace_()

-type namespace_() :: #thrift_generator_namespace{scope :: namespace_scope(), name :: namespace_name()}.

namespace_name()

-nominal namespace_name() :: binary().

namespace_scope()

-nominal namespace_scope() :: binary().

node_payload()

-type node_payload() ::
          document() |
          include_() |
          cpp_include() |
          namespace_() |
          constant() |
          typedef() |
          enum_() |
          struct_() |
          union_def() |
          exception_() |
          service() |
          function_() |
          field_().

requiredness()

-type requiredness() :: required | optional | default.

service()

-type service() ::
          #thrift_generator_service{name :: service_name(),
                                    extends :: service_parent() | undefined,
                                    functions :: [ast_node()]}.

service_name()

-nominal service_name() :: binary().

service_parent()

-nominal service_parent() :: binary().

struct_()

-type struct_() :: #thrift_generator_struct{name :: struct_name(), fields :: [ast_node()]}.

struct_name()

-nominal struct_name() :: binary().

thrift_type()

-type thrift_type() ::
          {base, base_type(), annotations()} |
          type_ref() |
          {list, Element :: thrift_type(), annotations()} |
          {set, Element :: thrift_type(), annotations()} |
          {map, Key :: thrift_type(), Value :: thrift_type(), annotations()}.

type_ref()

-type type_ref() :: {ref, Name :: binary(), annotations()}.

typedef()

-type typedef() :: #thrift_generator_typedef{name :: typedef_name(), type :: thrift_type()}.

typedef_name()

-nominal typedef_name() :: binary().

union_def()

-type union_def() :: #thrift_generator_union{name :: union_name(), fields :: [ast_node()]}.

union_name()

-nominal union_name() :: binary().

wire_type()

-type wire_type() ::
          {base, atom()} |
          {enum, [{integer(), atom()}]} |
          {list, wire_type()} |
          {set, wire_type(), list | sets | ordset} |
          {set, wire_type()} |
          {map, wire_type(), wire_type()} |
          {struct, {ref, module(), binary()}}.

Functions

containers/1

-spec containers(wire_type()) -> [wire_type()].

Shared with the compact/JSON codec emitters: every container node of a wire type, outermost first.

current_prefix(Ctx)

-spec current_prefix(#ectx{modules ::
                               #{module_key() =>
                                     #tg_module{name :: binary(),
                                                prefix :: binary(),
                                                path :: binary(),
                                                includes :: [binary()],
                                                structs ::
                                                    [#tg_struct{kind :: struct | union | exception,
                                                                name :: binary(),
                                                                fields ::
                                                                    [#tg_field{id :: integer(),
                                                                               required ::
                                                                                   requiredness(),
                                                                               type :: thrift_type(),
                                                                               name :: binary(),
                                                                               default ::
                                                                                   const_value() |
                                                                                   undefined,
                                                                               doc :: doc()}],
                                                                erl :: erl_annotations(),
                                                                doc :: doc(),
                                                                line :: non_neg_integer(),
                                                                col :: non_neg_integer()}],
                                                enums ::
                                                    [#tg_enum{name :: binary(),
                                                              values :: [{integer(), binary()}],
                                                              doc :: doc(),
                                                              line :: non_neg_integer(),
                                                              col :: non_neg_integer()}],
                                                typedefs ::
                                                    [#tg_typedef{name :: binary(),
                                                                 type :: thrift_type(),
                                                                 erl :: erl_annotations(),
                                                                 doc :: doc(),
                                                                 line :: non_neg_integer(),
                                                                 col :: non_neg_integer()}],
                                                consts ::
                                                    [#tg_const{name :: binary(),
                                                               type :: thrift_type(),
                                                               value :: const_value(),
                                                               doc :: doc(),
                                                               line :: non_neg_integer(),
                                                               col :: non_neg_integer()}],
                                                services ::
                                                    [#tg_service{name :: binary(),
                                                                 extends :: binary() | undefined,
                                                                 functions ::
                                                                     [#tg_function{name :: binary(),
                                                                                   oneway :: boolean(),
                                                                                   return_type ::
                                                                                       thrift_type() |
                                                                                       void,
                                                                                   params ::
                                                                                       [#tg_field{id ::
                                                                                                      integer(),
                                                                                                  required ::
                                                                                                      requiredness(),
                                                                                                  type ::
                                                                                                      thrift_type(),
                                                                                                  name ::
                                                                                                      binary(),
                                                                                                  default ::
                                                                                                      const_value() |
                                                                                                      undefined,
                                                                                                  doc ::
                                                                                                      doc()}],
                                                                                   throws ::
                                                                                       [#tg_field{id ::
                                                                                                      integer(),
                                                                                                  required ::
                                                                                                      requiredness(),
                                                                                                  type ::
                                                                                                      thrift_type(),
                                                                                                  name ::
                                                                                                      binary(),
                                                                                                  default ::
                                                                                                      const_value() |
                                                                                                      undefined,
                                                                                                  doc ::
                                                                                                      doc()}],
                                                                                   doc :: doc()}],
                                                                 doc :: doc(),
                                                                 line :: non_neg_integer(),
                                                                 col :: non_neg_integer()}]}},
                           type_modules :: #{module_key() => module()},
                           include_modules :: #{module_key() => module_key()},
                           current :: undefined | module_key(),
                           qualify :: boolean()}) ->
                        binary().

Shared with the compact/JSON codec emitters: the namespace prefix of the module being generated.

elem_type/1

-spec elem_type({list, wire_type()} | {set, wire_type()}) -> wire_type().

Shared with the compact/JSON codec emitters: the element type of a list or set container.

enum_registry/2

-spec enum_registry([wire_type()], #{integer() => pos_integer()}) -> #{integer() => pos_integer()}.

Shared with the compact/JSON codec emitters: numbers a module's distinct inline enum descriptors.

export_entries(Mod, Ctx)

-spec export_entries(#tg_module{name :: binary(),
                                prefix :: binary(),
                                path :: binary(),
                                includes :: [binary()],
                                structs ::
                                    [#tg_struct{kind :: struct | union | exception,
                                                name :: binary(),
                                                fields ::
                                                    [#tg_field{id :: integer(),
                                                               required :: requiredness(),
                                                               type :: thrift_type(),
                                                               name :: binary(),
                                                               default :: const_value() | undefined,
                                                               doc :: doc()}],
                                                erl :: erl_annotations(),
                                                doc :: doc(),
                                                line :: non_neg_integer(),
                                                col :: non_neg_integer()}],
                                enums ::
                                    [#tg_enum{name :: binary(),
                                              values :: [{integer(), binary()}],
                                              doc :: doc(),
                                              line :: non_neg_integer(),
                                              col :: non_neg_integer()}],
                                typedefs ::
                                    [#tg_typedef{name :: binary(),
                                                 type :: thrift_type(),
                                                 erl :: erl_annotations(),
                                                 doc :: doc(),
                                                 line :: non_neg_integer(),
                                                 col :: non_neg_integer()}],
                                consts ::
                                    [#tg_const{name :: binary(),
                                               type :: thrift_type(),
                                               value :: const_value(),
                                               doc :: doc(),
                                               line :: non_neg_integer(),
                                               col :: non_neg_integer()}],
                                services ::
                                    [#tg_service{name :: binary(),
                                                 extends :: binary() | undefined,
                                                 functions ::
                                                     [#tg_function{name :: binary(),
                                                                   oneway :: boolean(),
                                                                   return_type :: thrift_type() | void,
                                                                   params ::
                                                                       [#tg_field{id :: integer(),
                                                                                  required ::
                                                                                      requiredness(),
                                                                                  type :: thrift_type(),
                                                                                  name :: binary(),
                                                                                  default ::
                                                                                      const_value() |
                                                                                      undefined,
                                                                                  doc :: doc()}],
                                                                   throws ::
                                                                       [#tg_field{id :: integer(),
                                                                                  required ::
                                                                                      requiredness(),
                                                                                  type :: thrift_type(),
                                                                                  name :: binary(),
                                                                                  default ::
                                                                                      const_value() |
                                                                                      undefined,
                                                                                  doc :: doc()}],
                                                                   doc :: doc()}],
                                                 doc :: doc(),
                                                 line :: non_neg_integer(),
                                                 col :: non_neg_integer()}]},
                     #ectx{modules ::
                               #{module_key() =>
                                     #tg_module{name :: binary(),
                                                prefix :: binary(),
                                                path :: binary(),
                                                includes :: [binary()],
                                                structs ::
                                                    [#tg_struct{kind :: struct | union | exception,
                                                                name :: binary(),
                                                                fields ::
                                                                    [#tg_field{id :: integer(),
                                                                               required ::
                                                                                   requiredness(),
                                                                               type :: thrift_type(),
                                                                               name :: binary(),
                                                                               default ::
                                                                                   const_value() |
                                                                                   undefined,
                                                                               doc :: doc()}],
                                                                erl :: erl_annotations(),
                                                                doc :: doc(),
                                                                line :: non_neg_integer(),
                                                                col :: non_neg_integer()}],
                                                enums ::
                                                    [#tg_enum{name :: binary(),
                                                              values :: [{integer(), binary()}],
                                                              doc :: doc(),
                                                              line :: non_neg_integer(),
                                                              col :: non_neg_integer()}],
                                                typedefs ::
                                                    [#tg_typedef{name :: binary(),
                                                                 type :: thrift_type(),
                                                                 erl :: erl_annotations(),
                                                                 doc :: doc(),
                                                                 line :: non_neg_integer(),
                                                                 col :: non_neg_integer()}],
                                                consts ::
                                                    [#tg_const{name :: binary(),
                                                               type :: thrift_type(),
                                                               value :: const_value(),
                                                               doc :: doc(),
                                                               line :: non_neg_integer(),
                                                               col :: non_neg_integer()}],
                                                services ::
                                                    [#tg_service{name :: binary(),
                                                                 extends :: binary() | undefined,
                                                                 functions ::
                                                                     [#tg_function{name :: binary(),
                                                                                   oneway :: boolean(),
                                                                                   return_type ::
                                                                                       thrift_type() |
                                                                                       void,
                                                                                   params ::
                                                                                       [#tg_field{id ::
                                                                                                      integer(),
                                                                                                  required ::
                                                                                                      requiredness(),
                                                                                                  type ::
                                                                                                      thrift_type(),
                                                                                                  name ::
                                                                                                      binary(),
                                                                                                  default ::
                                                                                                      const_value() |
                                                                                                      undefined,
                                                                                                  doc ::
                                                                                                      doc()}],
                                                                                   throws ::
                                                                                       [#tg_field{id ::
                                                                                                      integer(),
                                                                                                  required ::
                                                                                                      requiredness(),
                                                                                                  type ::
                                                                                                      thrift_type(),
                                                                                                  name ::
                                                                                                      binary(),
                                                                                                  default ::
                                                                                                      const_value() |
                                                                                                      undefined,
                                                                                                  doc ::
                                                                                                      doc()}],
                                                                                   doc :: doc()}],
                                                                 doc :: doc(),
                                                                 line :: non_neg_integer(),
                                                                 col :: non_neg_integer()}]}},
                           type_modules :: #{module_key() => module()},
                           include_modules :: #{module_key() => module_key()},
                           current :: undefined | module_key(),
                           qualify :: boolean()}) ->
                        [{atom(), arity()}].

The -export/1 entries of the wire codecs: binary_codec/1 plus one pair per struct.

module_forms(Mod, Ctx)

-spec module_forms(#tg_module{name :: binary(),
                              prefix :: binary(),
                              path :: binary(),
                              includes :: [binary()],
                              structs ::
                                  [#tg_struct{kind :: struct | union | exception,
                                              name :: binary(),
                                              fields ::
                                                  [#tg_field{id :: integer(),
                                                             required :: requiredness(),
                                                             type :: thrift_type(),
                                                             name :: binary(),
                                                             default :: const_value() | undefined,
                                                             doc :: doc()}],
                                              erl :: erl_annotations(),
                                              doc :: doc(),
                                              line :: non_neg_integer(),
                                              col :: non_neg_integer()}],
                              enums ::
                                  [#tg_enum{name :: binary(),
                                            values :: [{integer(), binary()}],
                                            doc :: doc(),
                                            line :: non_neg_integer(),
                                            col :: non_neg_integer()}],
                              typedefs ::
                                  [#tg_typedef{name :: binary(),
                                               type :: thrift_type(),
                                               erl :: erl_annotations(),
                                               doc :: doc(),
                                               line :: non_neg_integer(),
                                               col :: non_neg_integer()}],
                              consts ::
                                  [#tg_const{name :: binary(),
                                             type :: thrift_type(),
                                             value :: const_value(),
                                             doc :: doc(),
                                             line :: non_neg_integer(),
                                             col :: non_neg_integer()}],
                              services ::
                                  [#tg_service{name :: binary(),
                                               extends :: binary() | undefined,
                                               functions ::
                                                   [#tg_function{name :: binary(),
                                                                 oneway :: boolean(),
                                                                 return_type :: thrift_type() | void,
                                                                 params ::
                                                                     [#tg_field{id :: integer(),
                                                                                required ::
                                                                                    requiredness(),
                                                                                type :: thrift_type(),
                                                                                name :: binary(),
                                                                                default ::
                                                                                    const_value() |
                                                                                    undefined,
                                                                                doc :: doc()}],
                                                                 throws ::
                                                                     [#tg_field{id :: integer(),
                                                                                required ::
                                                                                    requiredness(),
                                                                                type :: thrift_type(),
                                                                                name :: binary(),
                                                                                default ::
                                                                                    const_value() |
                                                                                    undefined,
                                                                                doc :: doc()}],
                                                                 doc :: doc()}],
                                               doc :: doc(),
                                               line :: non_neg_integer(),
                                               col :: non_neg_integer()}]},
                   #ectx{modules ::
                             #{module_key() =>
                                   #tg_module{name :: binary(),
                                              prefix :: binary(),
                                              path :: binary(),
                                              includes :: [binary()],
                                              structs ::
                                                  [#tg_struct{kind :: struct | union | exception,
                                                              name :: binary(),
                                                              fields ::
                                                                  [#tg_field{id :: integer(),
                                                                             required :: requiredness(),
                                                                             type :: thrift_type(),
                                                                             name :: binary(),
                                                                             default ::
                                                                                 const_value() |
                                                                                 undefined,
                                                                             doc :: doc()}],
                                                              erl :: erl_annotations(),
                                                              doc :: doc(),
                                                              line :: non_neg_integer(),
                                                              col :: non_neg_integer()}],
                                              enums ::
                                                  [#tg_enum{name :: binary(),
                                                            values :: [{integer(), binary()}],
                                                            doc :: doc(),
                                                            line :: non_neg_integer(),
                                                            col :: non_neg_integer()}],
                                              typedefs ::
                                                  [#tg_typedef{name :: binary(),
                                                               type :: thrift_type(),
                                                               erl :: erl_annotations(),
                                                               doc :: doc(),
                                                               line :: non_neg_integer(),
                                                               col :: non_neg_integer()}],
                                              consts ::
                                                  [#tg_const{name :: binary(),
                                                             type :: thrift_type(),
                                                             value :: const_value(),
                                                             doc :: doc(),
                                                             line :: non_neg_integer(),
                                                             col :: non_neg_integer()}],
                                              services ::
                                                  [#tg_service{name :: binary(),
                                                               extends :: binary() | undefined,
                                                               functions ::
                                                                   [#tg_function{name :: binary(),
                                                                                 oneway :: boolean(),
                                                                                 return_type ::
                                                                                     thrift_type() |
                                                                                     void,
                                                                                 params ::
                                                                                     [#tg_field{id ::
                                                                                                    integer(),
                                                                                                required ::
                                                                                                    requiredness(),
                                                                                                type ::
                                                                                                    thrift_type(),
                                                                                                name ::
                                                                                                    binary(),
                                                                                                default ::
                                                                                                    const_value() |
                                                                                                    undefined,
                                                                                                doc ::
                                                                                                    doc()}],
                                                                                 throws ::
                                                                                     [#tg_field{id ::
                                                                                                    integer(),
                                                                                                required ::
                                                                                                    requiredness(),
                                                                                                type ::
                                                                                                    thrift_type(),
                                                                                                name ::
                                                                                                    binary(),
                                                                                                default ::
                                                                                                    const_value() |
                                                                                                    undefined,
                                                                                                doc ::
                                                                                                    doc()}],
                                                                                 doc :: doc()}],
                                                               doc :: doc(),
                                                               line :: non_neg_integer(),
                                                               col :: non_neg_integer()}]}},
                         type_modules :: #{module_key() => module()},
                         include_modules :: #{module_key() => module_key()},
                         current :: undefined | module_key(),
                         qualify :: boolean()}) ->
                      erl_syntax:forms().

Every wire-codec form of the module: per-struct encode/decode functions, container helpers, binary_codec/1.

type_name/2

-spec type_name(wire_type(), #{integer() => pos_integer()}) -> binary().

Shared with the compact/JSON codec emitters: renders a wire type as a helper-name fragment.

typed_prefix/2

-spec typed_prefix(binary(), binary()) -> binary().

Shared with the compact/JSON codec emitters: joins the namespace prefix with a snake-case name.