Current section

Files

Jump to
libero src libero@codegen_decoders.erl
Raw

src/libero@codegen_decoders.erl

-module(libero@codegen_decoders).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/libero/codegen_decoders.gleam").
-export([generate_decoders_gleam/1, emit_client_msg_statics/2, emit_class_statics/1, emit_typed_decoders/1, generate_decoders_ffi/5]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Typed decoder generators.\n"
"\n"
" Emits JS decoder source from discovered types and handler endpoints.\n"
" Returns strings; writing to disk is the consumer's responsibility.\n"
).
-file("src/libero/codegen_decoders.gleam", 21).
?DOC(" Generate the Gleam wrapper module source for the typed decoder FFI.\n").
-spec generate_decoders_gleam(binary()) -> binary().
generate_decoders_gleam(Ffi_module_path) ->
<<<<"//// Code generated by libero. DO NOT EDIT.
////
//// Gleam wrapper for the typed decoder FFI. Importing this module
//// triggers constructor and decoder registration on the JavaScript target.
@external(javascript, \"./"/utf8,
Ffi_module_path/binary>>/binary,
"\", \"ensure_decoders\")
@external(erlang, \"libero_ffi\", \"ensure_decoders\")
pub fn ensure_decoders() -> Bool
"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 286).
-spec emit_float_type_hint(libero@field_type:field_type()) -> binary().
emit_float_type_hint(Ft) ->
case Ft of
float_field ->
<<"\"float\""/utf8>>;
{list_of, Element} ->
<<<<"{ kind: \"list\", element: "/utf8,
(emit_float_type_hint(Element))/binary>>/binary,
" }"/utf8>>;
{option_of, Inner} ->
<<<<"{ kind: \"option\", inner: "/utf8,
(emit_float_type_hint(Inner))/binary>>/binary,
" }"/utf8>>;
{result_of, Ok, Err} ->
<<<<<<<<"{ kind: \"result\", ok: "/utf8,
(emit_float_type_hint(Ok))/binary>>/binary,
", err: "/utf8>>/binary,
(emit_float_type_hint(Err))/binary>>/binary,
" }"/utf8>>;
{dict_of, Key, Value} ->
<<<<<<<<"{ kind: \"dict\", key: "/utf8,
(emit_float_type_hint(Key))/binary>>/binary,
", value: "/utf8>>/binary,
(emit_float_type_hint(Value))/binary>>/binary,
" }"/utf8>>;
{tuple_of, Elements} ->
Hints = begin
_pipe = Elements,
_pipe@1 = gleam@list:map(_pipe, fun emit_float_type_hint/1),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end,
<<<<"{ kind: \"tuple\", elements: ["/utf8, Hints/binary>>/binary,
"] }"/utf8>>;
int_field ->
<<"null"/utf8>>;
string_field ->
<<"null"/utf8>>;
bool_field ->
<<"null"/utf8>>;
bit_array_field ->
<<"null"/utf8>>;
nil_field ->
<<"null"/utf8>>;
{type_var, _} ->
<<"null"/utf8>>;
{user_type, _, _, _} ->
<<"null"/utf8>>
end.
-file("src/libero/codegen_decoders.gleam", 243).
-spec emit_client_msg_statics(list(libero@scanner:handler_endpoint()), binary()) -> binary().
emit_client_msg_statics(Endpoints, Dispatch_module_ref) ->
Lines = gleam@list:filter_map(
Endpoints,
fun(E) ->
Hints = begin
_pipe = erlang:element(6, E),
gleam@list:map(
_pipe,
fun(P) -> emit_float_type_hint(erlang:element(2, P)) end
)
end,
Needs_hints = gleam@list:any(
Hints,
fun(H) -> H /= <<"null"/utf8>> end
),
case Needs_hints of
false ->
{error, nil};
true ->
Class_ref = <<<<Dispatch_module_ref/binary, "."/utf8>>/binary,
(libero@codegen:to_pascal_case(
<<"server_"/utf8, (erlang:element(3, E))/binary>>
))/binary>>,
{ok,
<<<<<<Class_ref/binary, ".__fieldTypes = ["/utf8>>/binary,
(gleam@string:join(Hints, <<", "/utf8>>))/binary>>/binary,
"];"/utf8>>}
end
end
),
case Lines of
[] ->
<<""/utf8>>;
_ ->
<<(gleam@string:join(Lines, <<"\n"/utf8>>))/binary, "\n"/utf8>>
end.
-file("src/libero/codegen_decoders.gleam", 272).
-spec variant_hash(libero@walker:discovered_variant()) -> binary().
variant_hash(V) ->
{_, Hash} = libero@wire_identity:wire_identity(
erlang:element(2, V),
erlang:element(3, V),
erlang:element(7, V)
),
Hash.
-file("src/libero/codegen_decoders.gleam", 218).
?DOC(
" Emit per-variant class-static assignments for every discovered user\n"
" type. `__wireAtom` carries the 10-char hash; `__fieldTypes` carries\n"
" the positional field-type hints the encoder needs (Float marked,\n"
" containers wrapped, primitives null). These statics replace the\n"
" runtime `_bareToQualifiedAtom` and `fieldTypeRegistry` lookup tables.\n"
"\n"
" Even 0-arity variants get a `__fieldTypes = []` for symmetry; the\n"
" encoder branches on key count so the empty array is never indexed.\n"
).
-spec emit_class_statics(list(libero@walker:discovered_type())) -> binary().
emit_class_statics(Discovered) ->
Lines = gleam@list:flat_map(
Discovered,
fun(T) ->
gleam@list:flat_map(
erlang:element(5, T),
fun(V) ->
Class_ref = <<<<<<"_m_"/utf8,
(libero@codegen:module_to_underscored(
erlang:element(2, V)
))/binary>>/binary,
"."/utf8>>/binary,
(erlang:element(3, V))/binary>>,
Hints = begin
_pipe = erlang:element(7, V),
_pipe@1 = gleam@list:map(
_pipe,
fun emit_float_type_hint/1
),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end,
[<<<<<<Class_ref/binary, ".__wireAtom = \""/utf8>>/binary,
(variant_hash(V))/binary>>/binary,
"\";"/utf8>>,
<<<<<<Class_ref/binary, ".__fieldTypes = ["/utf8>>/binary,
Hints/binary>>/binary,
"];"/utf8>>]
end
)
end
),
case Lines of
[] ->
<<""/utf8>>;
_ ->
<<(gleam@string:join(Lines, <<"\n"/utf8>>))/binary, "\n"/utf8>>
end.
-file("src/libero/codegen_decoders.gleam", 551).
-spec emit_response_helper() -> binary().
emit_response_helper() ->
<<<<<<<<<<<<<<<<<<<<<<<<<<<<"function _decode_response(raw, decode_ok, decode_err) {\n"/utf8,
" if (Array.isArray(raw)) {\n"/utf8>>/binary,
" if (raw[0] === \"ok\") {\n"/utf8>>/binary,
" const inner = raw[1];\n"/utf8>>/binary,
" if (Array.isArray(inner) && inner[0] === \"ok\") {\n"/utf8>>/binary,
" return new _Success(decode_ok(inner[1]));\n"/utf8>>/binary,
" } else if (Array.isArray(inner) && inner[0] === \"error\") {\n"/utf8>>/binary,
" return new _Failure(new _DomainError(decode_err(inner[1])));\n"/utf8>>/binary,
" }\n"/utf8>>/binary,
" } else if (raw[0] === \"error\") {\n"/utf8>>/binary,
" return new _Failure(new _TransportError(_decode_rpc_error(raw[1])));\n"/utf8>>/binary,
" }\n"/utf8>>/binary,
" }\n"/utf8>>/binary,
" return new _Failure(new _TransportError(new _MalformedRequest()));\n"/utf8>>/binary,
"}"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 539).
-spec emit_rpc_error_decoder() -> binary().
emit_rpc_error_decoder() ->
<<<<<<<<<<<<<<"function _decode_rpc_error(term) {\n"/utf8,
" if (term === \"malformed_request\") return new _MalformedRequest();\n"/utf8>>/binary,
" if (Array.isArray(term)) {\n"/utf8>>/binary,
" if (term[0] === \"unknown_function\") return new _UnknownFunction(decode_string(term[1]));\n"/utf8>>/binary,
" if (term[0] === \"internal_error\") return new _InternalError(decode_string(term[1]), decode_string(term[2]));\n"/utf8>>/binary,
" }\n"/utf8>>/binary,
" return new _MalformedRequest();\n"/utf8>>/binary,
"}"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 322).
-spec decoder_fn_name(binary(), binary()) -> binary().
decoder_fn_name(Module_path, Type_name) ->
<<<<<<"decode_"/utf8,
(libero@codegen:module_to_underscored(Module_path))/binary>>/binary,
"_"/utf8>>/binary,
(libero@walker:to_snake_case(Type_name))/binary>>.
-file("src/libero/codegen_decoders.gleam", 521).
-spec emit_lambda_decoders(list(libero@field_type:field_type()), integer()) -> binary().
emit_lambda_decoders(Inners, Start_depth) ->
_pipe = Inners,
_pipe@1 = gleam@list:index_map(
_pipe,
fun(Ft, I) ->
P_depth = Start_depth + I,
Param = <<"t"/utf8, (erlang:integer_to_binary(P_depth))/binary>>,
<<<<<<"("/utf8, Param/binary>>/binary, ") => "/utf8>>/binary,
(field_decoder_call_depth(Ft, Param, P_depth + 1))/binary>>
end
),
gleam@string:join(_pipe@1, <<", "/utf8>>).
-file("src/libero/codegen_decoders.gleam", 511).
-spec emit_higher_order_decoder(
binary(),
list(libero@field_type:field_type()),
binary(),
integer()
) -> binary().
emit_higher_order_decoder(Fn_name, Inners, Term_expr, Start_depth) ->
Decoders = emit_lambda_decoders(Inners, Start_depth),
<<<<<<<<<<Fn_name/binary, "("/utf8>>/binary, Decoders/binary>>/binary,
", "/utf8>>/binary,
Term_expr/binary>>/binary,
")"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 454).
-spec field_decoder_call_depth(
libero@field_type:field_type(),
binary(),
integer()
) -> binary().
field_decoder_call_depth(Ft, Term_expr, Depth) ->
Param = <<"t"/utf8, (erlang:integer_to_binary(Depth))/binary>>,
Next = Depth + 1,
case Ft of
int_field ->
<<<<"decode_int("/utf8, Term_expr/binary>>/binary, ")"/utf8>>;
float_field ->
<<<<"decode_float("/utf8, Term_expr/binary>>/binary, ")"/utf8>>;
string_field ->
<<<<"decode_string("/utf8, Term_expr/binary>>/binary, ")"/utf8>>;
bool_field ->
<<<<"decode_bool("/utf8, Term_expr/binary>>/binary, ")"/utf8>>;
bit_array_field ->
<<<<"decode_bit_array("/utf8, Term_expr/binary>>/binary, ")"/utf8>>;
nil_field ->
<<<<"decode_nil("/utf8, Term_expr/binary>>/binary, ")"/utf8>>;
{list_of, Inner} ->
<<<<<<<<<<<<"decode_list_of(("/utf8, Param/binary>>/binary,
") => "/utf8>>/binary,
(field_decoder_call_depth(Inner, Param, Next))/binary>>/binary,
", "/utf8>>/binary,
Term_expr/binary>>/binary,
")"/utf8>>;
{option_of, Inner@1} ->
<<<<<<<<<<<<"decode_option_of(("/utf8, Param/binary>>/binary,
") => "/utf8>>/binary,
(field_decoder_call_depth(Inner@1, Param, Next))/binary>>/binary,
", "/utf8>>/binary,
Term_expr/binary>>/binary,
")"/utf8>>;
{result_of, Ok, Err} ->
emit_higher_order_decoder(
<<"decode_result_of"/utf8>>,
[Ok, Err],
Term_expr,
Next
);
{dict_of, K, V} ->
emit_higher_order_decoder(
<<"decode_dict_of"/utf8>>,
[K, V],
Term_expr,
Next
);
{tuple_of, Elems} ->
Decoders = emit_lambda_decoders(Elems, Next),
<<<<<<<<"decode_tuple_of(["/utf8, Decoders/binary>>/binary,
"], "/utf8>>/binary,
Term_expr/binary>>/binary,
")"/utf8>>;
{type_var, Name} ->
<<<<"(() => { throw new DecodeError(\"TypeVar<"/utf8, Name/binary>>/binary,
"> not supported at runtime\"); })()"/utf8>>;
{user_type, Module_path, Type_name, _} ->
<<<<<<(decoder_fn_name(Module_path, Type_name))/binary, "("/utf8>>/binary,
Term_expr/binary>>/binary,
")"/utf8>>
end.
-file("src/libero/codegen_decoders.gleam", 449).
-spec field_decoder_call(libero@field_type:field_type(), binary()) -> binary().
field_decoder_call(Ft, Term_expr) ->
field_decoder_call_depth(Ft, Term_expr, 0).
-file("src/libero/codegen_decoders.gleam", 569).
-spec emit_response_decoders(list(libero@scanner:handler_endpoint())) -> binary().
emit_response_decoders(Endpoints) ->
case Endpoints of
[] ->
<<""/utf8>>;
_ ->
Decoders = gleam@list:map(
Endpoints,
fun(E) ->
Ok_decoder = field_decoder_call(
erlang:element(4, E),
<<"t"/utf8>>
),
Err_decoder = field_decoder_call(
erlang:element(5, E),
<<"t"/utf8>>
),
<<<<<<<<<<<<<<<<"export function decode_response_"/utf8,
(erlang:element(3, E))/binary>>/binary,
"(raw) {\n"/utf8>>/binary,
" return _decode_response(raw, (t) => "/utf8>>/binary,
Ok_decoder/binary>>/binary,
", (t) => "/utf8>>/binary,
Err_decoder/binary>>/binary,
");\n"/utf8>>/binary,
"}"/utf8>>
end
),
<<<<<<<<<<<<"\n// --- Per-endpoint response decoders ---\n\n"/utf8,
(emit_rpc_error_decoder())/binary>>/binary,
"\n\n"/utf8>>/binary,
(emit_response_helper())/binary>>/binary,
"\n\n"/utf8>>/binary,
(gleam@string:join(Decoders, <<"\n\n"/utf8>>))/binary>>/binary,
"\n"/utf8>>
end.
-file("src/libero/codegen_decoders.gleam", 534).
-spec emit_ensure_decoders() -> binary().
emit_ensure_decoders() ->
<<"export function ensure_decoders() { return true; }"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 90).
-spec emit_typed_decoder_registrations(list(libero@walker:discovered_type())) -> binary().
emit_typed_decoder_registrations(Discovered) ->
case Discovered of
[] ->
<<""/utf8>>;
_ ->
Calls = begin
_pipe = gleam@list:flat_map(
Discovered,
fun(T) ->
Fn_name = decoder_fn_name(
erlang:element(2, T),
erlang:element(3, T)
),
gleam@list:map(
erlang:element(5, T),
fun(V) ->
<<<<<<<<<<<<"registerAtomDecoder(\""/utf8,
(variant_hash(V))/binary>>/binary,
"\", \""/utf8>>/binary,
Fn_name/binary>>/binary,
"\", "/utf8>>/binary,
Fn_name/binary>>/binary,
");"/utf8>>
end
)
end
),
gleam@string:join(_pipe, <<"\n"/utf8>>)
end,
<<Calls/binary, "\n"/utf8>>
end.
-file("src/libero/codegen_decoders.gleam", 351).
-spec emit_variant_constructor_call(
libero@walker:discovered_variant(),
binary()
) -> binary().
emit_variant_constructor_call(Variant, Args) ->
<<<<<<<<<<<<"new _m_"/utf8,
(libero@codegen:module_to_underscored(
erlang:element(2, Variant)
))/binary>>/binary,
"."/utf8>>/binary,
(erlang:element(3, Variant))/binary>>/binary,
"("/utf8>>/binary,
Args/binary>>/binary,
")"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 282).
-spec variant_source_label(libero@walker:discovered_variant()) -> binary().
variant_source_label(V) ->
<<<<(erlang:element(3, V))/binary, " @ "/utf8>>/binary,
(erlang:element(2, V))/binary>>.
-file("src/libero/codegen_decoders.gleam", 401).
-spec emit_tagged_union_decoder(list(libero@walker:discovered_variant())) -> binary().
emit_tagged_union_decoder(Variants) ->
Arms = gleam@list:map(
Variants,
fun(V) ->
Expected_len = erlang:integer_to_binary(
erlang:length(erlang:element(7, V)) + 1
),
Args = case erlang:element(7, V) of
[] ->
<<""/utf8>>;
Fields ->
_pipe = Fields,
_pipe@1 = gleam@list:index_map(
_pipe,
fun(Ft, I) ->
field_decoder_call(
Ft,
<<<<"term["/utf8,
(erlang:integer_to_binary(I + 1))/binary>>/binary,
"]"/utf8>>
)
end
),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end,
Length_guard = case erlang:element(7, V) of
[] ->
<<<<<<<<<<<<"if (Array.isArray(term) && term.length !== "/utf8,
Expected_len/binary>>/binary,
") throw new DecodeError(\"expected "/utf8>>/binary,
(variant_hash(V))/binary>>/binary,
" arity "/utf8>>/binary,
Expected_len/binary>>/binary,
", got \" + term.length);\n"/utf8>>;
_ ->
<<<<<<<<<<<<"if (!Array.isArray(term) || term.length !== "/utf8,
Expected_len/binary>>/binary,
") throw new DecodeError(\"expected "/utf8>>/binary,
(variant_hash(V))/binary>>/binary,
" arity "/utf8>>/binary,
Expected_len/binary>>/binary,
", got \" + (Array.isArray(term) ? term.length : typeof term));\n"/utf8>>
end,
<<<<<<<<<<<<<<<<" case \""/utf8, (variant_hash(V))/binary>>/binary,
"\": // "/utf8>>/binary,
(variant_source_label(V))/binary>>/binary,
"\n "/utf8>>/binary,
Length_guard/binary>>/binary,
" return "/utf8>>/binary,
(emit_variant_constructor_call(V, Args))/binary>>/binary,
";"/utf8>>
end
),
<<<<<<<<" const tag = Array.isArray(term) ? term[0] : term;\n"/utf8,
" switch (tag) {\n"/utf8>>/binary,
(gleam@string:join(Arms, <<"\n"/utf8>>))/binary>>/binary,
"\n default:\n throw new DecodeError(\"unknown variant atom: \" + String(tag));\n"/utf8>>/binary,
" }"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 364).
-spec emit_enum_decoder(list(libero@walker:discovered_variant())) -> binary().
emit_enum_decoder(Variants) ->
Cases = gleam@list:map(
Variants,
fun(V) ->
<<<<<<<<<<" if (term === \""/utf8, (variant_hash(V))/binary>>/binary,
"\") return "/utf8>>/binary,
(emit_variant_constructor_call(V, <<""/utf8>>))/binary>>/binary,
"; // "/utf8>>/binary,
(variant_source_label(V))/binary>>
end
),
<<(gleam@string:join(Cases, <<"\n"/utf8>>))/binary,
"\n throw new DecodeError(\"unknown variant atom: \" + String(term));"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 329).
-spec all_variants_zero_arity(list(libero@walker:discovered_variant())) -> boolean().
all_variants_zero_arity(Variants) ->
gleam@list:all(
Variants,
fun(V) -> gleam@list:is_empty(erlang:element(7, V)) end
).
-file("src/libero/codegen_decoders.gleam", 378).
-spec emit_record_decoder(libero@walker:discovered_variant()) -> binary().
emit_record_decoder(Variant) ->
Field_lines = gleam@list:index_map(
erlang:element(7, Variant),
fun(Ft, I) ->
<<" "/utf8,
(field_decoder_call(
Ft,
<<<<"term["/utf8, (erlang:integer_to_binary(I + 1))/binary>>/binary,
"]"/utf8>>
))/binary>>
end
),
Args = <<<<"\n"/utf8,
(gleam@string:join(Field_lines, <<",\n"/utf8>>))/binary>>/binary,
"\n "/utf8>>,
Hash = variant_hash(Variant),
Label = variant_source_label(Variant),
Expected_len = erlang:integer_to_binary(
erlang:length(erlang:element(7, Variant)) + 1
),
<<<<<<<<<<<<<<<<<<<<<<" if (!Array.isArray(term) || term.length !== "/utf8,
Expected_len/binary>>/binary,
" || term[0] !== \""/utf8>>/binary,
Hash/binary>>/binary,
"\") throw new DecodeError(\"expected "/utf8>>/binary,
Hash/binary>>/binary,
" ("/utf8>>/binary,
Label/binary>>/binary,
"), got \" + (Array.isArray(term) ? String(term[0]) : typeof term));\n"/utf8>>/binary,
" return "/utf8>>/binary,
(emit_variant_constructor_call(Variant, Args))/binary>>/binary,
";"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 333).
-spec emit_type_decoder(libero@walker:discovered_type()) -> binary().
emit_type_decoder(T) ->
Fn_name = decoder_fn_name(erlang:element(2, T), erlang:element(3, T)),
Body = case erlang:element(5, T) of
[] ->
<<" throw new DecodeError(\"empty type\");"/utf8>>;
[Single] ->
case erlang:element(7, Single) of
[] ->
emit_enum_decoder(erlang:element(5, T));
_ ->
emit_record_decoder(Single)
end;
Variants ->
case all_variants_zero_arity(Variants) of
true ->
emit_enum_decoder(Variants);
false ->
emit_tagged_union_decoder(Variants)
end
end,
<<<<<<<<"export function "/utf8, Fn_name/binary>>/binary,
"(term) {\n"/utf8>>/binary,
Body/binary>>/binary,
"\n}"/utf8>>.
-file("src/libero/codegen_decoders.gleam", 78).
?DOC(
" Emit a JS string with one decoder function per discovered type,\n"
" registration calls that populate etf/wire_ffi.mjs's typed decoder registry,\n"
" and an `ensure_decoders` entry point.\n"
).
-spec emit_typed_decoders(list(libero@walker:discovered_type())) -> binary().
emit_typed_decoders(Discovered) ->
Type_decoders = gleam@list:map(
Discovered,
fun(T) -> emit_type_decoder(T) end
),
Registrations = emit_typed_decoder_registrations(Discovered),
Entry = emit_ensure_decoders(),
Parts = gleam@list:filter(
[gleam@string:join(Type_decoders, <<"\n\n"/utf8>>),
Registrations,
Entry],
fun(S) -> S /= <<""/utf8>> end
),
gleam@string:join(Parts, <<"\n\n"/utf8>>).
-file("src/libero/codegen_decoders.gleam", 115).
-spec emit_decoder_imports(
list(libero@walker:discovered_type()),
list(libero@scanner:handler_endpoint()),
binary(),
binary(),
gleam@option:option(binary())
) -> binary().
emit_decoder_imports(
Discovered,
Endpoints,
Relpath_prefix,
Package,
Dispatch_module
) ->
Module_paths = begin
_pipe = gleam@list:fold(
Discovered,
{[], gleam@set:new()},
fun(Acc, T) ->
{Paths_acc, Seen} = Acc,
case gleam@set:contains(Seen, erlang:element(2, T)) of
true ->
Acc;
false ->
{lists:append(Paths_acc, [erlang:element(2, T)]),
gleam@set:insert(Seen, erlang:element(2, T))}
end
end
),
(fun(Pair) -> erlang:element(1, Pair) end)(_pipe)
end,
Prelude_import = <<<<<<<<<<<<<<"import { decode_int, decode_float, decode_string, decode_bool, "/utf8,
"decode_bit_array, decode_nil, decode_list_of, decode_option_of, "/utf8>>/binary,
"decode_result_of, decode_dict_of, decode_tuple_of, DecodeError, "/utf8>>/binary,
"setResultCtors, setOptionCtors, setListCtors, "/utf8>>/binary,
"setDictFromList } from \""/utf8>>/binary,
Relpath_prefix/binary>>/binary,
"libero/libero/decoders_prelude.mjs"/utf8>>/binary,
"\";"/utf8>>,
Stdlib_imports = <<<<<<<<<<<<<<<<"import { Ok, Error as ResultError, Empty, NonEmpty } from \""/utf8,
Relpath_prefix/binary>>/binary,
"gleam_stdlib/gleam.mjs\";\n"/utf8>>/binary,
"import { Some, None } from \""/utf8>>/binary,
Relpath_prefix/binary>>/binary,
"gleam_stdlib/gleam/option.mjs\";\n"/utf8>>/binary,
"import { from_list as dictFromList } from \""/utf8>>/binary,
Relpath_prefix/binary>>/binary,
"gleam_stdlib/gleam/dict.mjs\";"/utf8>>,
Rpc_ffi_import = case gleam@list:is_empty(Discovered) of
true ->
<<""/utf8>>;
false ->
<<<<"\nimport { registerAtomDecoder } from \""/utf8,
Relpath_prefix/binary>>/binary,
"libero/libero/etf/wire_ffi.mjs\";"/utf8>>
end,
Module_imports = gleam@list:map(
Module_paths,
fun(Mp) ->
<<<<<<<<<<"import * as _m_"/utf8,
(libero@codegen:module_to_underscored(Mp))/binary>>/binary,
" from \""/utf8>>/binary,
Relpath_prefix/binary>>/binary,
(libero@codegen:module_to_mjs_path(Mp, Package))/binary>>/binary,
"\";"/utf8>>
end
),
Remote_data_import = case Endpoints of
[] ->
<<""/utf8>>;
_ ->
<<<<<<"\nimport { Success as _Success, Failure as _Failure, "/utf8,
"TransportError as _TransportError, DomainError as _DomainError } from \""/utf8>>/binary,
Relpath_prefix/binary>>/binary,
"libero/libero/remote_data.mjs\";"/utf8>>
end,
Rpc_error_import = case Endpoints of
[] ->
<<""/utf8>>;
_ ->
<<<<<<<<"\nimport { MalformedRequest as _MalformedRequest, "/utf8,
"UnknownFunction as _UnknownFunction, "/utf8>>/binary,
"InternalError as _InternalError } from \""/utf8>>/binary,
Relpath_prefix/binary>>/binary,
"libero/libero/error.mjs\";"/utf8>>
end,
Dispatch_import = case Dispatch_module of
{some, Dm} ->
<<<<<<<<<<"\nimport * as _m_"/utf8,
(libero@codegen:module_to_underscored(Dm))/binary>>/binary,
" from \""/utf8>>/binary,
Relpath_prefix/binary>>/binary,
(libero@codegen:module_to_mjs_path(Dm, Package))/binary>>/binary,
"\";"/utf8>>;
none ->
<<""/utf8>>
end,
gleam@string:join(
[Prelude_import,
<<<<<<<<Stdlib_imports/binary, Rpc_ffi_import/binary>>/binary,
Remote_data_import/binary>>/binary,
Rpc_error_import/binary>>/binary,
Dispatch_import/binary>> |
Module_imports],
<<"\n"/utf8>>
).
-file("src/libero/codegen_decoders.gleam", 36).
?DOC(" Generate the JS FFI decoder source from discovered types and endpoints.\n").
-spec generate_decoders_ffi(
list(libero@walker:discovered_type()),
list(libero@scanner:handler_endpoint()),
binary(),
binary(),
gleam@option:option(binary())
) -> binary().
generate_decoders_ffi(
Discovered,
Endpoints,
Relpath_prefix,
Package,
Dispatch_module
) ->
Imports = emit_decoder_imports(
Discovered,
Endpoints,
Relpath_prefix,
Package,
Dispatch_module
),
Body = emit_typed_decoders(Discovered),
Response_decoders = emit_response_decoders(Endpoints),
Class_statics = emit_class_statics(Discovered),
Client_msg_statics = case Dispatch_module of
{some, Dm} ->
emit_client_msg_statics(
Endpoints,
<<"_m_"/utf8,
(libero@codegen:module_to_underscored(Dm))/binary>>
);
none ->
<<""/utf8>>
end,
Ctor_setters = <<<<<<"setResultCtors(Ok, ResultError);\n"/utf8,
"setOptionCtors(Some, None);\n"/utf8>>/binary,
"setListCtors(Empty, NonEmpty);\n"/utf8>>/binary,
"setDictFromList(dictFromList);\n"/utf8>>,
<<<<<<<<<<<<<<<<<<"// Code generated by libero. DO NOT EDIT.
//
// Per-type decoder functions derived from the DiscoveredType graph.
"/utf8,
Imports/binary>>/binary,
"\n\n"/utf8>>/binary,
Ctor_setters/binary>>/binary,
Class_statics/binary>>/binary,
Client_msg_statics/binary>>/binary,
"\n"/utf8>>/binary,
Body/binary>>/binary,
"\n"/utf8>>/binary,
Response_decoders/binary>>.