-module(atproto_codegen@emit@union). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/atproto_codegen/emit/union.gleam"). -export([emit_union/6]). -export_type([union_parts/0, variant/0]). -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( " Union synthesis with `$type`-dispatching codecs. Open unions get an\n" " `Other(Dynamic)` escape hatch; closed unions fail decode instead.\n" "\n" " The three parts (type, encoder, decoder) are returned separately rather\n" " than as one joined string: the `types` plugin renders the first two, the\n" " `decode-json` plugin the third, and the host interleaves them with the\n" " def's own type/encoder/decoder so the emitted file matches the order the\n" " monolithic emitter used to produce.\n" ). -type union_parts() :: {union_parts, binary(), binary(), binary()}. -type variant() :: {variant, binary(), binary(), list(binary()), binary(), binary()}. -file("src/atproto_codegen/emit/union.gleam", 33). -spec union_variant( atproto_codegen@config:config(), binary(), binary(), binary() ) -> variant(). union_variant(Cfg, Nsid, Name, Ref) -> R = atproto_codegen@naming:parse_ref(Nsid, Ref), Ref_name = atproto_codegen@naming:ref_type_name(erlang:element(5, Cfg), R), Qual = atproto_codegen@naming:qualifier( erlang:element(5, Cfg), Nsid, erlang:element(2, R) ), Type_keys = case erlang:element(3, R) of <<"main"/utf8>> -> [erlang:element(2, R), <<(erlang:element(2, R))/binary, "#main"/utf8>>]; Def_name -> [<<<<(erlang:element(2, R))/binary, "#"/utf8>>/binary, Def_name/binary>>] end, {variant, <>, <>, Type_keys, <<<>/binary, "_fields"/utf8>>, <<<>/binary, "_decoder()"/utf8>>}. -file("src/atproto_codegen/emit/union.gleam", 56). -spec emit_union( atproto_codegen@emit@zero:zero_plan(), atproto_codegen@config:config(), binary(), binary(), list(binary()), boolean() ) -> union_parts(). emit_union(Plan, Cfg, Nsid, Name, Refs, Closed) -> Variants = gleam@list:map( Refs, fun(_capture) -> union_variant(Cfg, Nsid, Name, _capture) end ), Snake = justin:snake_case(Name), Type_lines = gleam@list:map( Variants, fun(V) -> <<<<<<<<" "/utf8, (erlang:element(2, V))/binary>>/binary, "("/utf8>>/binary, (erlang:element(3, V))/binary>>/binary, ")"/utf8>> end ), Type_lines@1 = case Closed of true -> Type_lines; false -> lists:append( Type_lines, [<<<<" "/utf8, Name/binary>>/binary, "Other(dynamic.Dynamic)"/utf8>>] ) end, Type_def = <<<<<<<<"pub type "/utf8, Name/binary>>/binary, " {\n"/utf8>>/binary, (gleam@string:join(Type_lines@1, <<"\n"/utf8>>))/binary>>/binary, "\n}"/utf8>>, Encode_arms = gleam@list:map( Variants, fun(V@1) -> Primary@1 = case erlang:element(4, V@1) of [Primary | _] -> Primary; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen/emit/union"/utf8>>, function => <<"emit_union"/utf8>>, line => 78, value => _assert_fail, start => 2359, 'end' => 2397, pattern_start => 2370, pattern_end => 2383}) end, <<<<<<<<<<<<" "/utf8, (erlang:element(2, V@1))/binary>>/binary, "(inner) ->\n json.object([\n #(\"$type\", json.string(\""/utf8>>/binary, (atproto_codegen@emit@exprs:escape(Primary@1))/binary>>/binary, "\")),\n .."/utf8>>/binary, (erlang:element(5, V@1))/binary>>/binary, "(inner)\n ])"/utf8>> end ), Encode_arms@1 = case Closed of true -> Encode_arms; false -> lists:append( Encode_arms, [<<<<" "/utf8, Name/binary>>/binary, "Other(inner) -> internal.dynamic_to_json(inner)"/utf8>>] ) end, Encoder = <<<<<<<<<<<<"pub fn encode_"/utf8, Snake/binary>>/binary, "(value: "/utf8>>/binary, Name/binary>>/binary, ") -> json.Json {\n case value {\n"/utf8>>/binary, (gleam@string:join(Encode_arms@1, <<"\n"/utf8>>))/binary>>/binary, "\n }\n}"/utf8>>, Decode_arms = gleam@list:map( Variants, fun(V@2) -> Patterns = begin _pipe = erlang:element(4, V@2), _pipe@1 = gleam@list:map( _pipe, fun(K) -> <<<<"\""/utf8, (atproto_codegen@emit@exprs:escape(K))/binary>>/binary, "\""/utf8>> end ), gleam@string:join(_pipe@1, <<" | "/utf8>>) end, <<<<<<<<<<<<" "/utf8, Patterns/binary>>/binary, " -> decode.map("/utf8>>/binary, (erlang:element(6, V@2))/binary>>/binary, ", "/utf8>>/binary, (erlang:element(2, V@2))/binary>>/binary, ")"/utf8>> end ), Fallback_arm = case Closed of true -> <<<<<<<<" _ -> decode.failure("/utf8, (atproto_codegen@emit@exprs:zero_expr( Plan, Cfg, Nsid, Name, {t_union, Refs, true} ))/binary>>/binary, ", \""/utf8>>/binary, (atproto_codegen@emit@exprs:escape(Name))/binary>>/binary, "\")"/utf8>>; false -> <<<<" _ -> decode.map(decode.dynamic, "/utf8, Name/binary>>/binary, "Other)"/utf8>> end, Decode_arms@1 = lists:append(Decode_arms, [Fallback_arm]), Decoder = <<<<<<<<<<<<"pub fn "/utf8, Snake/binary>>/binary, "_decoder() -> decode.Decoder("/utf8>>/binary, Name/binary>>/binary, ") {\n use tag <- decode.optional_field(\"$type\", \"\", decode.string)\n case tag {\n"/utf8>>/binary, (gleam@string:join(Decode_arms@1, <<"\n"/utf8>>))/binary>>/binary, "\n }\n}"/utf8>>, {union_parts, Type_def, Encoder, Decoder}.