-module(libero@json@codegen). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/libero/json/codegen.gleam"). -export([generate/1, generate_transport_codecs_with_push_and_ssr/3]). -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 JSON encoder and decoder codegen.\n" "\n" " Generates Gleam source code for per-type `json.Json` builders and\n" " typed decoders. Each discovered type gets a pair of functions:\n" " `json_encode_` — builds a `json.Json` value\n" " `json_decode_` — validates and decodes from `Dynamic`\n" "\n" " The generated wire format follows the JSON-transport-v1 contract shape:\n" " { \"type\": \".\",\n" " \"variant\": \"\",\n" " \"fields\": }\n" "\n" " Labelled variants encode fields as a JSON object under \"fields\";\n" " unlabelled variants encode them as a JSON array. Mixed labelled /\n" " unlabelled constructors are rejected at codegen time.\n" ). -file("src/libero/json/codegen.gleam", 1186). ?DOC(" Emit the builtin Result decoder function.\n"). -spec emit_result_decoder() -> binary(). emit_result_decoder() -> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"pub fn json_decode_gleam_result__result(value: Dynamic, decode_ok: fn(Dynamic) -> Result(a, List(JsonError)), decode_err: fn(Dynamic) -> Result(b, List(JsonError))) -> Result(Result(a, b), List(JsonError)) {\n"/utf8, " use _ <- result.try(\n"/utf8>>/binary, " case json_runtime.field_string(value, \"type\", \"type\") {\n"/utf8>>/binary, " Ok(\"gleam/result.Result\") -> Ok(Nil)\n"/utf8>>/binary, " Ok(s) -> Error([JsonError(\"type\", \"expected gleam/result.Result, got \" <> s)])\n"/utf8>>/binary, " Error(_) -> Error([JsonError(\"type\", \"missing or not a string\")])\n"/utf8>>/binary, " }\n"/utf8>>/binary, " )\n"/utf8>>/binary, " case json_runtime.field_string(value, \"variant\", \"variant\") {\n"/utf8>>/binary, " Ok(\"Ok\") -> {\n"/utf8>>/binary, " use fields <- result.try(json_runtime.field(value, \"fields\", \"fields\"))\n"/utf8>>/binary, " use size <- result.try(json_runtime.array_length(fields, \"fields\"))\n"/utf8>>/binary, " use _ <- result.try(case size { 1 -> Ok(Nil) n -> Error([JsonError(\"fields\", \"expected 1 elements, got \" <> int.to_string(n))]) })\n"/utf8>>/binary, " use inner_raw <- result.try(json_runtime.array_at(fields, 0, \"fields[0]\"))\n"/utf8>>/binary, " use val <- result.try(decode_ok(inner_raw))\n"/utf8>>/binary, " Ok(Ok(val))\n"/utf8>>/binary, " }\n"/utf8>>/binary, " Ok(\"Error\") -> {\n"/utf8>>/binary, " use fields <- result.try(json_runtime.field(value, \"fields\", \"fields\"))\n"/utf8>>/binary, " use size <- result.try(json_runtime.array_length(fields, \"fields\"))\n"/utf8>>/binary, " use _ <- result.try(case size { 1 -> Ok(Nil) n -> Error([JsonError(\"fields\", \"expected 1 elements, got \" <> int.to_string(n))]) })\n"/utf8>>/binary, " use inner_raw <- result.try(json_runtime.array_at(fields, 0, \"fields[0]\"))\n"/utf8>>/binary, " use val <- result.try(decode_err(inner_raw))\n"/utf8>>/binary, " Ok(Error(val))\n"/utf8>>/binary, " }\n"/utf8>>/binary, " Ok(other) -> Error([JsonError(\"variant\", \"unknown Result variant: \" <> other)])\n"/utf8>>/binary, " Error(_) -> Error([JsonError(\"variant\", \"missing or not a string\")])\n"/utf8>>/binary, " }\n"/utf8>>/binary, "}"/utf8>>. -file("src/libero/json/codegen.gleam", 1133). ?DOC(" Emit the builtin Option decoder function.\n"). -spec emit_option_decoder() -> binary(). emit_option_decoder() -> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"pub fn json_decode_gleam_option__option(value: Dynamic, decode_inner: fn(Dynamic) -> Result(a, List(JsonError))) -> Result(Option(a), List(JsonError)) {\n"/utf8, " use _ <- result.try(\n"/utf8>>/binary, " case json_runtime.field_string(value, \"type\", \"type\") {\n"/utf8>>/binary, " Ok(\"gleam/option.Option\") -> Ok(Nil)\n"/utf8>>/binary, " Ok(s) -> Error([JsonError(\"type\", \"expected gleam/option.Option, got \" <> s)])\n"/utf8>>/binary, " Error(_) -> Error([JsonError(\"type\", \"missing or not a string\")])\n"/utf8>>/binary, " }\n"/utf8>>/binary, " )\n"/utf8>>/binary, " case json_runtime.field_string(value, \"variant\", \"variant\") {\n"/utf8>>/binary, " Ok(\"None\") -> {\n"/utf8>>/binary, " use fields <- result.try(json_runtime.field(value, \"fields\", \"fields\"))\n"/utf8>>/binary, " use size <- result.try(json_runtime.object_size(fields, \"fields\"))\n"/utf8>>/binary, " case size {\n"/utf8>>/binary, " 0 -> Ok(None)\n"/utf8>>/binary, " n -> Error([JsonError(\"fields\", \"expected exactly 0 object fields, got \" <> int.to_string(n))])\n"/utf8>>/binary, " }\n"/utf8>>/binary, " }\n"/utf8>>/binary, " Ok(\"Some\") -> {\n"/utf8>>/binary, " use fields <- result.try(json_runtime.field(value, \"fields\", \"fields\"))\n"/utf8>>/binary, " use size <- result.try(json_runtime.array_length(fields, \"fields\"))\n"/utf8>>/binary, " use _ <- result.try(case size { 1 -> Ok(Nil) n -> Error([JsonError(\"fields\", \"expected 1 elements, got \" <> int.to_string(n))]) })\n"/utf8>>/binary, " use inner_raw <- result.try(json_runtime.array_at(fields, 0, \"fields[0]\"))\n"/utf8>>/binary, " use val <- result.try(decode_inner(inner_raw))\n"/utf8>>/binary, " Ok(Some(val))\n"/utf8>>/binary, " }\n"/utf8>>/binary, " Ok(other) -> Error([JsonError(\"variant\", \"unknown Option variant: \" <> other)])\n"/utf8>>/binary, " Error(_) -> Error([JsonError(\"variant\", \"missing or not a string\")])\n"/utf8>>/binary, " }\n"/utf8>>/binary, "}"/utf8>>. -file("src/libero/json/codegen.gleam", 1167). ?DOC(" Emit the builtin Result encoder function.\n"). -spec emit_result_encoder() -> binary(). emit_result_encoder() -> <<<<<<<<<<<<<<<<<<<<<<<<<<"pub fn json_encode_gleam_result__result(value, encode_ok: fn(a) -> json.Json, encode_err: fn(b) -> json.Json) -> json.Json {\n"/utf8, " case value {\n"/utf8>>/binary, " Ok(inner) -> json.object([\n"/utf8>>/binary, " #(\"type\", json.string(\"gleam/result.Result\")),\n"/utf8>>/binary, " #(\"variant\", json.string(\"Ok\")),\n"/utf8>>/binary, " #(\"fields\", json.array([encode_ok(inner)], of: fn(x) { x })),\n"/utf8>>/binary, " ])\n"/utf8>>/binary, " Error(inner) -> json.object([\n"/utf8>>/binary, " #(\"type\", json.string(\"gleam/result.Result\")),\n"/utf8>>/binary, " #(\"variant\", json.string(\"Error\")),\n"/utf8>>/binary, " #(\"fields\", json.array([encode_err(inner)], of: fn(x) { x })),\n"/utf8>>/binary, " ])\n"/utf8>>/binary, " }\n"/utf8>>/binary, "}"/utf8>>. -file("src/libero/json/codegen.gleam", 1114). ?DOC(" Emit the builtin Option encoder function.\n"). -spec emit_option_encoder() -> binary(). emit_option_encoder() -> <<<<<<<<<<<<<<<<<<<<<<<<<<"pub fn json_encode_gleam_option__option(value, encode_inner: fn(a) -> json.Json) -> json.Json {\n"/utf8, " case value {\n"/utf8>>/binary, " Some(inner) -> json.object([\n"/utf8>>/binary, " #(\"type\", json.string(\"gleam/option.Option\")),\n"/utf8>>/binary, " #(\"variant\", json.string(\"Some\")),\n"/utf8>>/binary, " #(\"fields\", json.array([encode_inner(inner)], of: fn(x) { x })),\n"/utf8>>/binary, " ])\n"/utf8>>/binary, " None -> json.object([\n"/utf8>>/binary, " #(\"type\", json.string(\"gleam/option.Option\")),\n"/utf8>>/binary, " #(\"variant\", json.string(\"None\")),\n"/utf8>>/binary, " #(\"fields\", json.object([])),\n"/utf8>>/binary, " ])\n"/utf8>>/binary, " }\n"/utf8>>/binary, "}"/utf8>>. -file("src/libero/json/codegen.gleam", 940). ?DOC(" Build positional constructor field names e.g. `f0, f1`\n"). -spec emit_variant_constructor_positional(libero@walker:discovered_variant()) -> binary(). emit_variant_constructor_positional(V) -> Names = gleam@list:index_map( erlang:element(7, V), fun(_, I) -> <<"f"/utf8, (erlang:integer_to_binary(I))/binary>> end ), gleam@string:join(Names, <<", "/utf8>>). -file("src/libero/json/codegen.gleam", 928). ?DOC(" Build labelled constructor field names e.g. `title:, body:`\n"). -spec emit_variant_constructor_labels(libero@walker:discovered_variant()) -> binary(). emit_variant_constructor_labels(V) -> Names = gleam@list:filter_map(erlang:element(6, V), fun(L) -> case L of {some, N} -> {ok, <>}; none -> {error, nil} end end), gleam@string:join(Names, <<", "/utf8>>). -file("src/libero/json/codegen.gleam", 1330). ?DOC(" Generate inline decode for Tuple types.\n"). -spec emit_tuple_decode( list(libero@field_type:field_type()), binary(), binary(), binary() ) -> binary(). emit_tuple_decode(Elements, Raw_var, Path, Pad) -> Element_count = erlang:length(Elements), N_str = erlang:integer_to_binary(Element_count), Fields_pad = <>, Field_decodes = gleam@list:index_map( Elements, fun(Ft, I) -> Idx_str = erlang:integer_to_binary(I), Var_name = <<"t"/utf8, Idx_str/binary>>, Result_var = <>, <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Result_var/binary>>/binary, " = case json_runtime.array_at("/utf8>>/binary, Raw_var/binary>>/binary, ", "/utf8>>/binary, Idx_str/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "["/utf8>>/binary, Idx_str/binary>>/binary, "]\") {\n"/utf8>>/binary, Fields_pad/binary>>/binary, " Ok(raw) -> "/utf8>>/binary, (emit_raw_value_decode( Ft, <<"raw"/utf8>>, <<<<<>/binary, Idx_str/binary>>/binary, "]"/utf8>>, <> ))/binary>>/binary, "\n"/utf8>>/binary, Fields_pad/binary>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, Fields_pad/binary>>/binary, "}\n"/utf8>>/binary, Fields_pad/binary>>/binary, "use "/utf8>>/binary, Var_name/binary>>/binary, " <- result.try("/utf8>>/binary, Result_var/binary>>/binary, ")\n"/utf8>> end ), Tuple_expr = <<<<"#("/utf8, (gleam@string:join( gleam@list:index_map( Elements, fun(_, I@1) -> <<"t"/utf8, (erlang:integer_to_binary(I@1))/binary>> end ), <<", "/utf8>> ))/binary>>/binary, ")"/utf8>>, <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(size) -> case size {\n"/utf8>>/binary, Pad/binary>>/binary, " "/utf8>>/binary, N_str/binary>>/binary, " -> {\n"/utf8>>/binary, (gleam@string:join( Field_decodes, <<""/utf8>> ))/binary>>/binary, Fields_pad/binary>>/binary, "Ok("/utf8>>/binary, Tuple_expr/binary>>/binary, ")\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, " n -> Error([JsonError(\""/utf8>>/binary, Path/binary>>/binary, "\", \"expected "/utf8>>/binary, N_str/binary>>/binary, " elements, got \" <> int.to_string(n))])\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, Pad/binary>>/binary, "}"/utf8>>. -file("src/libero/json/codegen.gleam", 1220). ?DOC(" Generate inline decode for Dict types.\n"). -spec emit_dict_decode( libero@field_type:field_type(), libero@field_type:field_type(), binary(), binary(), binary() ) -> binary(). emit_dict_decode(Key, Value, Raw_var, Path, Pad) -> case Key of string_field -> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(entries) -> {\n"/utf8>>/binary, Pad/binary>>/binary, " use decoded <- result.try(\n"/utf8>>/binary, Pad/binary>>/binary, " list.try_map(entries, fn(entry) {\n"/utf8>>/binary, Pad/binary>>/binary, " let k = entry.0\n"/utf8>>/binary, Pad/binary>>/binary, " let v_raw = entry.1\n"/utf8>>/binary, Pad/binary>>/binary, " use v <- result.try(\n"/utf8>>/binary, (emit_raw_value_decode( Value, <<"v_raw"/utf8>>, <>, <> ))/binary>>/binary, "\n"/utf8>>/binary, Pad/binary>>/binary, " )\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(#(k, v))\n"/utf8>>/binary, Pad/binary>>/binary, " })\n"/utf8>>/binary, Pad/binary>>/binary, " )\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(dict.from_list(decoded))\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, Pad/binary>>/binary, "}"/utf8>>; _ -> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(pairs_raw) -> {\n"/utf8>>/binary, Pad/binary>>/binary, " use pairs <- result.try(\n"/utf8>>/binary, Pad/binary>>/binary, " list.try_map(pairs_raw, fn(pair_raw) {\n"/utf8>>/binary, Pad/binary>>/binary, " let k_raw = pair_raw.0\n"/utf8>>/binary, Pad/binary>>/binary, " let v_raw = pair_raw.1\n"/utf8>>/binary, Pad/binary>>/binary, " use k <- result.try(\n"/utf8>>/binary, (emit_raw_value_decode( Key, <<"k_raw"/utf8>>, <>, <> ))/binary>>/binary, "\n"/utf8>>/binary, Pad/binary>>/binary, " )\n"/utf8>>/binary, Pad/binary>>/binary, " use v <- result.try(\n"/utf8>>/binary, (emit_raw_value_decode( Value, <<"v_raw"/utf8>>, <>, <> ))/binary>>/binary, "\n"/utf8>>/binary, Pad/binary>>/binary, " )\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(#(k, v))\n"/utf8>>/binary, Pad/binary>>/binary, " })\n"/utf8>>/binary, Pad/binary>>/binary, " )\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(dict.from_list(pairs))\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, Pad/binary>>/binary, "}"/utf8>> end. -file("src/libero/json/codegen.gleam", 947). ?DOC( " Emit a decode expression for a raw Dynamic value according to FieldType.\n" " Returns a single expression evaluating to `Result(value, List(JsonError))`.\n" ). -spec emit_raw_value_decode( libero@field_type:field_type(), binary(), binary(), binary() ) -> binary(). emit_raw_value_decode(Ft, Raw_var, Path, Pad) -> case Ft of string_field -> <<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\")"/utf8>>; int_field -> <<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\")"/utf8>>; float_field -> <<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\")"/utf8>>; bool_field -> <<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\")"/utf8>>; nil_field -> <<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\")"/utf8>>; bit_array_field -> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \"encoding\", \""/utf8>>/binary, Path/binary>>/binary, ".encoding\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(\"base64url\") -> case json_runtime.field_string("/utf8>>/binary, Raw_var/binary>>/binary, ", \"data\", \""/utf8>>/binary, Path/binary>>/binary, ".data\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(s) -> case bit_array.base64_url_decode(s) {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(bits) -> Ok(bits)\n"/utf8>>/binary, Pad/binary>>/binary, " Error(_) -> Error([JsonError(\""/utf8>>/binary, Path/binary>>/binary, ".data\", \"expected valid base64url BitArray data\")])\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, " Error(_) -> Error([JsonError(\""/utf8>>/binary, Path/binary>>/binary, ".data\", \"missing or not a string\")])\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(other) -> Error([JsonError(\""/utf8>>/binary, Path/binary>>/binary, ".encoding\", \"expected base64url BitArray encoding, got \" <> other)])\n"/utf8>>/binary, Pad/binary>>/binary, " Error(_) -> Error([JsonError(\""/utf8>>/binary, Path/binary>>/binary, ".encoding\", \"missing or not a string\")])\n"/utf8>>/binary, Pad/binary>>/binary, "}"/utf8>>; {user_type, Module_path, Type_name, _} -> Qual = libero@walker:qualified_atom_name(Module_path, Type_name), <<<<<<<<<>/binary, Qual/binary>>/binary, "("/utf8>>/binary, Raw_var/binary>>/binary, ")"/utf8>>; {list_of, Element} -> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Raw_var/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(items) -> list.try_map(items, fn(item_raw) {\n"/utf8>>/binary, (emit_raw_value_decode( Element, <<"item_raw"/utf8>>, <>, <> ))/binary>>/binary, "\n"/utf8>>/binary, Pad/binary>>/binary, " })\n"/utf8>>/binary, Pad/binary>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, Pad/binary>>/binary, "}"/utf8>>; {option_of, Inner} -> Qual@1 = libero@walker:qualified_atom_name( <<"gleam/option"/utf8>>, <<"Option"/utf8>> ), <<<<<<<<<<<<<<<<<>/binary, Qual@1/binary>>/binary, "("/utf8>>/binary, Raw_var/binary>>/binary, ", fn(inner_raw) {\n"/utf8>>/binary, (emit_raw_value_decode( Inner, <<"inner_raw"/utf8>>, <>, <> ))/binary>>/binary, "\n"/utf8>>/binary, Pad/binary>>/binary, "})"/utf8>>; {result_of, Ok, Err} -> Qual@2 = libero@walker:qualified_atom_name( <<"gleam/result"/utf8>>, <<"Result"/utf8>> ), <<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Qual@2/binary>>/binary, "("/utf8>>/binary, Raw_var/binary>>/binary, ", fn(inner_raw) {\n"/utf8>>/binary, (emit_raw_value_decode( Ok, <<"inner_raw"/utf8>>, <>, <> ))/binary>>/binary, "\n"/utf8>>/binary, Pad/binary>>/binary, "}, fn(inner_raw) {\n"/utf8>>/binary, (emit_raw_value_decode( Err, <<"inner_raw"/utf8>>, <>, <> ))/binary>>/binary, "\n"/utf8>>/binary, Pad/binary>>/binary, "})"/utf8>>; {dict_of, Key, Value} -> emit_dict_decode(Key, Value, Raw_var, Path, Pad); {tuple_of, Elements} -> emit_tuple_decode(Elements, Raw_var, Path, Pad); {type_var, Name} -> <<<<<<<<<>/binary, Path/binary>>/binary, "\", \"cannot decode type variable "/utf8>>/binary, Name/binary>>/binary, "\")])"/utf8>> end. -file("src/libero/json/codegen.gleam", 860). ?DOC(" Generate field decode bindings for unlabelled fields (extracted by index).\n"). -spec emit_unlabelled_field_decodes( libero@walker:discovered_variant(), binary() ) -> binary(). emit_unlabelled_field_decodes(V, Pad) -> Field_count = erlang:length(erlang:element(7, V)), N_str = erlang:integer_to_binary(Field_count), Length_check = <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Pad/binary>>/binary, " case json_runtime.array_length(fields, \"fields\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(size) -> case size {\n"/utf8>>/binary, Pad/binary>>/binary, " "/utf8>>/binary, N_str/binary>>/binary, " -> Ok(fields)\n"/utf8>>/binary, Pad/binary>>/binary, " n -> Error([JsonError(\"fields\", \"expected "/utf8>>/binary, N_str/binary>>/binary, " elements, got \" <> int.to_string(n))])\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, ")\n"/utf8>>, Entries = gleam@list:index_map( erlang:element(7, V), fun(Ft, I) -> Idx_str = erlang:integer_to_binary(I), Path = <<<<"fields["/utf8, Idx_str/binary>>/binary, "]"/utf8>>, Var_name = <<"f"/utf8, Idx_str/binary>>, Result_var = <>, <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Result_var/binary>>/binary, " = case json_runtime.array_at(arr, "/utf8>>/binary, Idx_str/binary>>/binary, ", \""/utf8>>/binary, Path/binary>>/binary, "\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(raw) -> "/utf8>>/binary, (emit_raw_value_decode( Ft, <<"raw"/utf8>>, Path, <> ))/binary>>/binary, "\n"/utf8>>/binary, Pad/binary>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, Pad/binary>>/binary, "}\n"/utf8>>/binary, Pad/binary>>/binary, "use "/utf8>>/binary, Var_name/binary>>/binary, " <- result.try("/utf8>>/binary, Result_var/binary>>/binary, ")\n"/utf8>> end ), <>))/binary>>. -file("src/libero/json/codegen.gleam", 815). ?DOC(" Generate field decode bindings for labelled fields (extracted by name).\n"). -spec emit_labelled_field_decodes(libero@walker:discovered_variant(), binary()) -> binary(). emit_labelled_field_decodes(V, Pad) -> Zipped = gleam@list:zip(erlang:element(7, V), erlang:element(6, V)), Entries = gleam@list:index_map( Zipped, fun(Pair, _) -> {Ft, Label} = Pair, case Label of {some, Name} -> Path = <<"fields."/utf8, Name/binary>>, Result_var = <>, <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Result_var/binary>>/binary, " = case json_runtime.field(fields, \""/utf8>>/binary, Name/binary>>/binary, "\", \""/utf8>>/binary, Path/binary>>/binary, "\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(raw) -> "/utf8>>/binary, (emit_raw_value_decode( Ft, <<"raw"/utf8>>, Path, <> ))/binary>>/binary, "\n"/utf8>>/binary, Pad/binary>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, Pad/binary>>/binary, "}\n"/utf8>>/binary, Pad/binary>>/binary, "use "/utf8>>/binary, Name/binary>>/binary, " <- result.try("/utf8>>/binary, Result_var/binary>>/binary, ")\n"/utf8>>; none -> <<""/utf8>> end end ), gleam@string:join(Entries, <<""/utf8>>). -file("src/libero/json/codegen.gleam", 780). -spec emit_fields_object_size_check(binary(), integer(), binary()) -> binary(). emit_fields_object_size_check(Path, Expected_size, Pad) -> Expected = erlang:integer_to_binary(Expected_size), <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, Pad/binary>>/binary, " case json_runtime.object_size(fields, \""/utf8>>/binary, Path/binary>>/binary, "\") {\n"/utf8>>/binary, Pad/binary>>/binary, " Ok(size) -> case size {\n"/utf8>>/binary, Pad/binary>>/binary, " "/utf8>>/binary, Expected/binary>>/binary, " -> Ok(Nil)\n"/utf8>>/binary, Pad/binary>>/binary, " n -> Error([JsonError(\""/utf8>>/binary, Path/binary>>/binary, "\", \"expected exactly "/utf8>>/binary, Expected/binary>>/binary, " object fields, got \" <> int.to_string(n))])\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, Pad/binary>>/binary, " }\n"/utf8>>/binary, Pad/binary>>/binary, ")\n"/utf8>>. -file("src/libero/json/codegen.gleam", 771). -spec emit_fields_extract(binary()) -> binary(). emit_fields_extract(Pad) -> <<<<<<<<<>/binary, Pad/binary>>/binary, " json_runtime.field(value, \"fields\", \"fields\")\n"/utf8>>/binary, Pad/binary>>/binary, ")\n"/utf8>>. -file("src/libero/json/codegen.gleam", 708). ?DOC( " Emit a single decode clause that matches a variant name string and\n" " decodes the variant's fields, constructing the Gleam value.\n" ). -spec emit_decode_clause(libero@walker:discovered_variant(), binary()) -> binary(). emit_decode_clause(V, Alias) -> Pad = <<" "/utf8>>, case erlang:element(7, V) of [] -> <<<<<<<<<<<<<<<<<<<<<<<<<>/binary, (erlang:element( 3, V ))/binary>>/binary, "\") -> {\n"/utf8>>/binary, (emit_fields_extract( <> ))/binary>>/binary, (emit_fields_object_size_check( <<"fields"/utf8>>, 0, <> ))/binary>>/binary, Pad/binary>>/binary, " Ok("/utf8>>/binary, Alias/binary>>/binary, "."/utf8>>/binary, (erlang:element(3, V))/binary>>/binary, ")\n"/utf8>>/binary, Pad/binary>>/binary, "}\n"/utf8>>; _ -> All_labelled = gleam@list:all( erlang:element(6, V), fun(L) -> L /= none end ), Fields_extract = emit_fields_extract(<>), Field_decodes = case All_labelled of true -> <<(emit_fields_object_size_check( <<"fields"/utf8>>, erlang:length(erlang:element(7, V)), <> ))/binary, (emit_labelled_field_decodes( V, <> ))/binary>>; false -> emit_unlabelled_field_decodes(V, <>) end, Field_names = case All_labelled of true -> emit_variant_constructor_labels(V); false -> emit_variant_constructor_positional(V) end, <<<<<<<<<<<<<<<<<<<<<<<<<<<<<>/binary, (erlang:element( 3, V ))/binary>>/binary, "\") -> {\n"/utf8>>/binary, Fields_extract/binary>>/binary, Field_decodes/binary>>/binary, Pad/binary>>/binary, " Ok("/utf8>>/binary, Alias/binary>>/binary, "."/utf8>>/binary, (erlang:element(3, V))/binary>>/binary, "("/utf8>>/binary, Field_names/binary>>/binary, "))\n"/utf8>>/binary, Pad/binary>>/binary, "}\n"/utf8>> end. -file("src/libero/json/codegen.gleam", 667). ?DOC( " Emit a per-type decoder function that validates the wire format and\n" " dispatches to per-variant decoding.\n" ). -spec emit_type_decoder( libero@walker:discovered_type(), gleam@dict:dict(binary(), binary()) ) -> binary(). emit_type_decoder(Dt, Aliases) -> Qual = libero@walker:qualified_atom_name( erlang:element(2, Dt), erlang:element(3, Dt) ), Alias = gleam@result:unwrap( gleam_stdlib:map_get(Aliases, erlang:element(2, Dt)), libero@field_type:last_segment(erlang:element(2, Dt)) ), Clauses = gleam@list:map( erlang:element(5, Dt), fun(V) -> emit_decode_clause(V, Alias) end ), Type_str = <<<<(erlang:element(2, Dt))/binary, "."/utf8>>/binary, (erlang:element(3, Dt))/binary>>, <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"pub fn json_decode_"/utf8, Qual/binary>>/binary, "(value: dynamic.Dynamic) {\n"/utf8>>/binary, " use _ <- result.try(\n"/utf8>>/binary, " case json_runtime.field_string(value, \"type\", \"type\") {\n"/utf8>>/binary, " Ok(s) if s == \""/utf8>>/binary, Type_str/binary>>/binary, "\" -> Ok(s)\n"/utf8>>/binary, " Ok(s) -> Error([JsonError(\"type\", \"expected "/utf8>>/binary, Type_str/binary>>/binary, ", got \" <> s)])\n"/utf8>>/binary, " Error(_) -> Error([JsonError(\"type\", \"missing or not a string\")])\n"/utf8>>/binary, " }\n"/utf8>>/binary, " )\n"/utf8>>/binary, " case json_runtime.field_string(value, \"variant\", \"variant\") {\n"/utf8>>/binary, (gleam@string:join(Clauses, <<"\n"/utf8>>))/binary>>/binary, " Error(_) -> Error([JsonError(\"variant\", \"missing or not a string\")])\n"/utf8>>/binary, " Ok(s) -> Error([JsonError(\"variant\", \"unknown: \" <> s)])\n"/utf8>>/binary, " }\n"/utf8>>/binary, "}"/utf8>>. -file("src/libero/json/codegen.gleam", 438). ?DOC( " Validate that a Float value is finite (not NaN or Infinity).\n" " NaN/Infinity can arise from FFI on the JavaScript runtime.\n" " Panics with a descriptive message if the value is not finite.\n" ). -spec finite_float_check(binary()) -> binary(). finite_float_check(Var) -> <<<<<<<<<<<<<<<<<<"case "/utf8, Var/binary>>/binary, " -. "/utf8>>/binary, Var/binary>>/binary, " == 0.0 {\n"/utf8>>/binary, " True -> "/utf8>>/binary, Var/binary>>/binary, "\n"/utf8>>/binary, " False -> panic as \"Float must be finite (not NaN or Infinity)\"\n"/utf8>>/binary, " }"/utf8>>. -file("src/libero/json/codegen.gleam", 422). ?DOC( " Validate that an Int value is within JavaScript safe integer range.\n" " Panics with a descriptive message if the value is outside the range.\n" ). -spec safe_int_check(binary()) -> binary(). safe_int_check(Var) -> <<<<<<<<<<<<<<<<<<"case "/utf8, Var/binary>>/binary, " >= -9007199254740991 && "/utf8>>/binary, Var/binary>>/binary, " <= 9007199254740991 {\n"/utf8>>/binary, " True -> "/utf8>>/binary, Var/binary>>/binary, "\n"/utf8>>/binary, " False -> panic as \"Int outside JavaScript safe integer range\"\n"/utf8>>/binary, " }"/utf8>>. -file("src/libero/json/codegen.gleam", 453). ?DOC( " Wrap a raw Gleam value variable with the appropriate `json.X()` constructor\n" " so it becomes a `json.Json` expression.\n" ). -spec json_encode_expr(libero@field_type:field_type(), binary()) -> binary(). json_encode_expr(Ft, Var) -> case Ft of string_field -> <<<<"json.string("/utf8, Var/binary>>/binary, ")"/utf8>>; int_field -> <<<<"json.int("/utf8, (safe_int_check(Var))/binary>>/binary, ")"/utf8>>; float_field -> <<<<"json.float("/utf8, (finite_float_check(Var))/binary>>/binary, ")"/utf8>>; bool_field -> <<<<"json.bool("/utf8, Var/binary>>/binary, ")"/utf8>>; nil_field -> <<"json.null()"/utf8>>; bit_array_field -> <<<<"json.object([#(\"encoding\", json.string(\"base64url\")), #(\"data\", json.string(bit_array.base64_url_encode("/utf8, Var/binary>>/binary, ", True)))])"/utf8>>; {user_type, Module_path, Type_name, _} -> Qual = libero@walker:qualified_atom_name(Module_path, Type_name), <<<<<<<<"json_encode_"/utf8, Qual/binary>>/binary, "("/utf8>>/binary, Var/binary>>/binary, ")"/utf8>>; {list_of, Element} -> <<<<<<<<"json.array("/utf8, Var/binary>>/binary, ", of: fn(x) { "/utf8>>/binary, (json_encode_expr(Element, <<"x"/utf8>>))/binary>>/binary, " })"/utf8>>; {option_of, Inner} -> Qual@1 = libero@walker:qualified_atom_name( <<"gleam/option"/utf8>>, <<"Option"/utf8>> ), <<<<<<<<<<<<"json_encode_"/utf8, Qual@1/binary>>/binary, "("/utf8>>/binary, Var/binary>>/binary, ", fn(x) { "/utf8>>/binary, (json_encode_expr(Inner, <<"x"/utf8>>))/binary>>/binary, " })"/utf8>>; {result_of, Ok, Err} -> Qual@2 = libero@walker:qualified_atom_name( <<"gleam/result"/utf8>>, <<"Result"/utf8>> ), <<<<<<<<<<<<<<<<"json_encode_"/utf8, Qual@2/binary>>/binary, "("/utf8>>/binary, Var/binary>>/binary, ", fn(x) { "/utf8>>/binary, (json_encode_expr(Ok, <<"x"/utf8>>))/binary>>/binary, " }, fn(x) { "/utf8>>/binary, (json_encode_expr(Err, <<"x"/utf8>>))/binary>>/binary, " })"/utf8>>; {dict_of, Key, Value} -> case Key of string_field -> <<<<<<<<"json.object(dict.to_list("/utf8, Var/binary>>/binary, ") |> list.map(fn(kv) { let #(k, v) = kv #(k, "/utf8>>/binary, (json_encode_expr(Value, <<"v"/utf8>>))/binary>>/binary, ") }))"/utf8>>; _ -> <<<<<<<<<<<<"json.array(dict.to_list("/utf8, Var/binary>>/binary, "), of: fn(kv) { let #(k, v) = kv json.array(["/utf8>>/binary, (json_encode_expr(Key, <<"k"/utf8>>))/binary>>/binary, ", "/utf8>>/binary, (json_encode_expr(Value, <<"v"/utf8>>))/binary>>/binary, "], of: fn(x) { x }) })"/utf8>> end; {tuple_of, Elements} -> Encoded = gleam@list:index_map( Elements, fun(E, I) -> json_encode_expr( E, <<<>/binary, (erlang:integer_to_binary(I))/binary>> ) end ), <<<<"json.array(["/utf8, (gleam@string:join(Encoded, <<", "/utf8>>))/binary>>/binary, "], of: fn(x) { x })"/utf8>>; {type_var, Name} -> <<<<"panic as \"cannot encode type variable "/utf8, Name/binary>>/binary, "\""/utf8>> end. -file("src/libero/json/codegen.gleam", 640). -spec emit_fields_object(libero@walker:discovered_variant(), list(binary())) -> binary(). emit_fields_object(V, Field_vars) -> Entries = gleam@list:index_map( gleam@list:zip( erlang:element(7, V), gleam@list:zip(erlang:element(6, V), Field_vars) ), fun(Pair, I) -> {Ft, Label_and_var} = Pair, {Label, Fvar} = Label_and_var, case Label of {some, Name} -> <<<<<<<<"#(\""/utf8, Name/binary>>/binary, "\", "/utf8>>/binary, (json_encode_expr(Ft, Fvar))/binary>>/binary, ")"/utf8>>; none -> <<<<<<<<"#(\"_"/utf8, (erlang:integer_to_binary(I))/binary>>/binary, "\", "/utf8>>/binary, (json_encode_expr(Ft, Fvar))/binary>>/binary, ")"/utf8>> end end ), <<<<"json.object(["/utf8, (gleam@string:join(Entries, <<", "/utf8>>))/binary>>/binary, "])"/utf8>>. -file("src/libero/json/codegen.gleam", 627). -spec emit_unlabelled_fields_array( libero@walker:discovered_variant(), list(binary()) ) -> binary(). emit_unlabelled_fields_array(V, Field_vars) -> Encoded = begin _pipe = gleam@list:zip(erlang:element(7, V), Field_vars), gleam@list:map( _pipe, fun(Pair) -> {Ft, Fvar} = Pair, json_encode_expr(Ft, Fvar) end ) end, <<<<"json.array(["/utf8, (gleam@string:join(Encoded, <<", "/utf8>>))/binary>>/binary, "], of: fn(x) { x })"/utf8>>. -file("src/libero/json/codegen.gleam", 614). ?DOC( " Build the \"fields\" value for a variant.\n" " - Zero-field variants: `json.object([])`\n" " - Unlabelled fields: `json.array([f0, f1, ...], of: fn(x) { x })`\n" " - Labelled fields: `json.object([#(\"label\", f0), ...])`\n" ). -spec emit_fields_value(libero@walker:discovered_variant(), list(binary())) -> binary(). emit_fields_value(V, Field_vars) -> case erlang:element(6, V) of [] -> <<"json.object([])"/utf8>>; _ -> All_unlabelled = gleam@list:all( erlang:element(6, V), fun(L) -> L =:= none end ), case All_unlabelled of true -> emit_unlabelled_fields_array(V, Field_vars); false -> emit_fields_object(V, Field_vars) end end. -file("src/libero/json/codegen.gleam", 568). ?DOC(" Emit a single encode pattern-match arm for one variant.\n"). -spec emit_encode_clause(libero@walker:discovered_variant(), binary(), binary()) -> binary(). emit_encode_clause(Variant, Alias, Type_name) -> Field_vars = gleam@list:index_map( erlang:element(7, Variant), fun(Field, I) -> case Field of nil_field -> <<"_f"/utf8, (erlang:integer_to_binary(I))/binary>>; _ -> <<"f"/utf8, (erlang:integer_to_binary(I))/binary>> end end ), Fields_expr = emit_fields_value(Variant, Field_vars), Type_str = <<<<(erlang:element(2, Variant))/binary, "."/utf8>>/binary, Type_name/binary>>, Pattern = case Field_vars of [] -> <<<>/binary, (erlang:element(3, Variant))/binary>>; _ -> <<<<<<<<<>/binary, (erlang:element(3, Variant))/binary>>/binary, "("/utf8>>/binary, (gleam@string:join(Field_vars, <<", "/utf8>>))/binary>>/binary, ")"/utf8>> end, <<<<<<<<<<<<<<<<<<<<<<<<<<" "/utf8, Pattern/binary>>/binary, " ->\n"/utf8>>/binary, " json.object([\n"/utf8>>/binary, " #(\"type\", json.string(\""/utf8>>/binary, Type_str/binary>>/binary, "\")),\n"/utf8>>/binary, " #(\"variant\", json.string(\""/utf8>>/binary, (erlang:element(3, Variant))/binary>>/binary, "\")),\n"/utf8>>/binary, " #(\"fields\", "/utf8>>/binary, Fields_expr/binary>>/binary, "),\n"/utf8>>/binary, " ])"/utf8>>. -file("src/libero/json/codegen.gleam", 540). ?DOC( " Emit a per-type encoder function that pattern-matches on the type's\n" " variants and builds a `json.Json` value with the standard wire shape:\n" " { \"type\": \".\",\n" " \"variant\": \"\",\n" " \"fields\": }\n" ). -spec emit_type_encoder( libero@walker:discovered_type(), gleam@dict:dict(binary(), binary()) ) -> binary(). emit_type_encoder(Dt, Aliases) -> Qual = libero@walker:qualified_atom_name( erlang:element(2, Dt), erlang:element(3, Dt) ), Alias = gleam@result:unwrap( gleam_stdlib:map_get(Aliases, erlang:element(2, Dt)), libero@field_type:last_segment(erlang:element(2, Dt)) ), Clauses = gleam@list:map( erlang:element(5, Dt), fun(V) -> emit_encode_clause(V, Alias, erlang:element(3, Dt)) end ), <<<<<<<<<<"pub fn json_encode_"/utf8, Qual/binary>>/binary, "(value) -> json.Json {\n"/utf8>>/binary, " case value {\n"/utf8>>/binary, (gleam@string:join(Clauses, <<"\n"/utf8>>))/binary>>/binary, "\n }\n}"/utf8>>. -file("src/libero/json/codegen.gleam", 1451). -spec uses_list(libero@field_type:field_type()) -> boolean(). uses_list(Ft) -> case Ft of {list_of, _} -> true; _ -> false end. -file("src/libero/json/codegen.gleam", 1444). -spec uses_dict(libero@field_type:field_type()) -> boolean(). uses_dict(Ft) -> case Ft of {dict_of, _, _} -> true; _ -> false end. -file("src/libero/json/codegen.gleam", 1427). -spec flatten_field_type(libero@field_type:field_type()) -> list(libero@field_type:field_type()). flatten_field_type(Ft) -> case Ft of {list_of, Inner} -> [Ft | flatten_field_type(Inner)]; {option_of, Inner@1} -> [Ft | flatten_field_type(Inner@1)]; {result_of, Ok, Err} -> [Ft | lists:append(flatten_field_type(Ok), flatten_field_type(Err))]; {dict_of, Key, Value} -> [Ft | lists:append(flatten_field_type(Key), flatten_field_type(Value))]; {tuple_of, Elements} -> [Ft | gleam@list:flat_map(Elements, fun flatten_field_type/1)]; _ -> [Ft] end. -file("src/libero/json/codegen.gleam", 1419). -spec collect_all_fields(list(libero@walker:discovered_type())) -> list(libero@field_type:field_type()). collect_all_fields(Discovered) -> gleam@list:flat_map( Discovered, fun(Dt) -> gleam@list:flat_map( erlang:element(5, Dt), fun(V) -> gleam@list:flat_map( erlang:element(7, V), fun(Ft) -> flatten_field_type(Ft) end ) end ) end ). -file("src/libero/json/codegen.gleam", 352). -spec check_supported_field_type(libero@field_type:field_type(), binary()) -> list(libero@json@error:json_error()). check_supported_field_type(Ft, Path) -> case Ft of int_field -> []; float_field -> []; string_field -> []; bool_field -> []; bit_array_field -> []; nil_field -> []; {type_var, Name} -> [{json_error, Path, <<<<"type variable "/utf8, Name/binary>>/binary, " cannot cross the JSON wire"/utf8>>}]; {user_type, _, _, Args} -> _pipe = Args, _pipe@1 = gleam@list:index_map( _pipe, fun(Arg, Index) -> {Arg, Index} end ), gleam@list:flat_map( _pipe@1, fun(Pair) -> {Arg@1, Index@1} = Pair, check_supported_field_type( Arg@1, <<<<<>/binary, (erlang:integer_to_binary(Index@1))/binary>>/binary, "]"/utf8>> ) end ); {list_of, Element} -> check_supported_field_type( Element, <> ); {option_of, Inner} -> check_supported_field_type(Inner, <>); {result_of, Ok, Err} -> lists:append( check_supported_field_type(Ok, <>), check_supported_field_type(Err, <>) ); {dict_of, Key, Value} -> Key_errors = case Key of int_field -> []; string_field -> []; bool_field -> []; _ -> [{json_error, Path, <<<<"Dict key type "/utf8, (libero@field_type:to_canonical_token(Key))/binary>>/binary, " is not supported by JSON transport; use Int, String, or Bool keys"/utf8>>}] end, lists:append( Key_errors, check_supported_field_type( Value, <> ) ); {tuple_of, Elements} -> _pipe@2 = Elements, _pipe@3 = gleam@list:index_map( _pipe@2, fun(Element@1, Index@2) -> {Element@1, Index@2} end ), gleam@list:flat_map( _pipe@3, fun(Pair@1) -> {Element@2, Index@3} = Pair@1, check_supported_field_type( Element@2, <<<<<>/binary, (erlang:integer_to_binary(Index@3))/binary>>/binary, "]"/utf8>> ) end ) end. -file("src/libero/json/codegen.gleam", 321). -spec check_supported_field_types(list(libero@walker:discovered_type())) -> {ok, nil} | {error, list(libero@json@error:json_error())}. check_supported_field_types(Discovered) -> Errors = gleam@list:flat_map( Discovered, fun(Dt) -> gleam@list:flat_map( erlang:element(5, Dt), fun(V) -> _pipe = erlang:element(7, V), _pipe@1 = gleam@list:index_map( _pipe, fun(Field, Index) -> {Field, Index} end ), gleam@list:flat_map( _pipe@1, fun(Pair) -> {Field@1, Index@1} = Pair, check_supported_field_type( Field@1, <<<<<<<<<<<<<<(erlang:element(2, Dt))/binary, "."/utf8>>/binary, (erlang:element(3, Dt))/binary>>/binary, "."/utf8>>/binary, (erlang:element(3, V))/binary>>/binary, ".field["/utf8>>/binary, (erlang:integer_to_binary(Index@1))/binary>>/binary, "]"/utf8>> ) end ) end ) end ), case Errors of [] -> {ok, nil}; _ -> {error, Errors} end. -file("src/libero/json/codegen.gleam", 315). -spec has_mixed_fields(list(gleam@option:option(binary()))) -> boolean(). has_mixed_fields(Labels) -> Has_labelled = gleam@list:any(Labels, fun(L) -> L /= none end), Has_unlabelled = gleam@list:any(Labels, fun(L@1) -> L@1 =:= none end), Has_labelled andalso Has_unlabelled. -file("src/libero/json/codegen.gleam", 288). -spec check_no_mixed_fields(list(libero@walker:discovered_type())) -> {ok, nil} | {error, list(libero@json@error:json_error())}. check_no_mixed_fields(Discovered) -> Errors = gleam@list:flat_map( Discovered, fun(Dt) -> gleam@list:flat_map( erlang:element(5, Dt), fun(V) -> case has_mixed_fields(erlang:element(6, V)) of true -> [{json_error, <<<<<<<<(erlang:element(2, Dt))/binary, "."/utf8>>/binary, (erlang:element(3, Dt))/binary>>/binary, "."/utf8>>/binary, (erlang:element(3, V))/binary>>, <<"mixed labelled/unlabelled fields are not supported in JSON v1"/utf8>>}]; false -> [] end end ) end ), case Errors of [] -> {ok, nil}; _ -> {error, Errors} end. -file("src/libero/json/codegen.gleam", 49). -spec generate_with_extra( list(libero@walker:discovered_type()), list(libero@field_type:field_type()), binary(), boolean(), boolean() ) -> {ok, binary()} | {error, list(libero@json@error:json_error())}. generate_with_extra( Discovered, Extra_fields, Extra_tail, Needs_json_wire, Needs_frame ) -> gleam@result:'try'( check_no_mixed_fields(Discovered), fun(_) -> gleam@result:'try'( check_supported_field_types(Discovered), fun(_) -> Aliases = begin _pipe = Discovered, _pipe@1 = gleam@list:map( _pipe, fun(Dt) -> erlang:element(2, Dt) end ), libero@codegen:build_module_alias_map(_pipe@1) end, User_imports = begin _pipe@2 = Aliases, _pipe@3 = maps:to_list(_pipe@2), _pipe@4 = gleam@list:filter( _pipe@3, fun(Pair) -> {Mod, _} = Pair, (not gleam_stdlib:string_starts_with( Mod, <<"gleam/"/utf8>> ) andalso not gleam_stdlib:string_starts_with( Mod, <<"libero/"/utf8>> )) andalso (Mod /= <<"gleam"/utf8>>) end ), _pipe@5 = gleam@list:map( _pipe@4, fun(Pair@1) -> {Mod@1, Alias} = Pair@1, Seg = libero@field_type:last_segment(Mod@1), case Alias =:= Seg of true -> <<"import "/utf8, Mod@1/binary>>; false -> <<<<<<"import "/utf8, Mod@1/binary>>/binary, " as "/utf8>>/binary, Alias/binary>> end end ), _pipe@6 = gleam@string:join(_pipe@5, <<"\n"/utf8>>), (fun(S) -> case S of <<""/utf8>> -> <<""/utf8>>; _ -> <> end end)(_pipe@6) end, All_fields = lists:append( collect_all_fields(Discovered), Extra_fields ), Needs_bit_array = gleam@list:any( All_fields, fun(Ft) -> Ft =:= bit_array_field end ), Has_dict_field = gleam@list:any(All_fields, fun uses_dict/1), Needs_dict = Has_dict_field, Has_list_field = gleam@list:any(All_fields, fun uses_list/1), Needs_list = Has_dict_field orelse Has_list_field, Bit_array_import = case Needs_bit_array of true -> <<"import gleam/bit_array\n"/utf8>>; false -> <<""/utf8>> end, Dict_import = case Needs_dict of true -> <<"import gleam/dict\n"/utf8>>; false -> <<""/utf8>> end, Int_import = <<"import gleam/int\n"/utf8>>, List_import = case Needs_list of true -> <<"import gleam/list\n"/utf8>>; false -> <<""/utf8>> end, List_at_helper = <<""/utf8>>, Json_wire_import = case Needs_json_wire of true -> <<"import libero/json/wire as json_wire\n"/utf8>>; false -> <<""/utf8>> end, Frame_import = case Needs_frame of true -> <<"import libero/frame\n"/utf8>>; false -> <<""/utf8>> end, Header = <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"// Generated by libero. DO NOT EDIT.\n"/utf8, "////\n"/utf8>>/binary, "//// Typed JSON encoders and decoders for all discovered types.\n"/utf8>>/binary, "\n"/utf8>>/binary, "import gleam/dynamic.{type Dynamic}\n"/utf8>>/binary, "import gleam/json\n"/utf8>>/binary, Bit_array_import/binary>>/binary, Frame_import/binary>>/binary, Json_wire_import/binary>>/binary, "import libero/json/runtime as json_runtime\n"/utf8>>/binary, "import libero/json/error.{type JsonError, JsonError}\n"/utf8>>/binary, "import gleam/result\n"/utf8>>/binary, "import gleam/option.{type Option, None, Some}\n"/utf8>>/binary, Int_import/binary>>/binary, List_import/binary>>/binary, Dict_import/binary>>/binary, User_imports/binary>>/binary, "\n"/utf8>>/binary, List_at_helper/binary>>/binary, "\n"/utf8>>, Encoders = gleam@list:map( Discovered, fun(Dt@1) -> emit_type_encoder(Dt@1, Aliases) end ), Decoders = gleam@list:map( Discovered, fun(Dt@2) -> emit_type_decoder(Dt@2, Aliases) end ), Builtin_encoders = <<<<(emit_option_encoder())/binary, "\n\n"/utf8>>/binary, (emit_result_encoder())/binary>>, Builtin_decoders = <<<<(emit_option_decoder())/binary, "\n\n"/utf8>>/binary, (emit_result_decoder())/binary>>, {ok, <<<<<<<<<<<<<<<<<
> ))/binary>>/binary, "\n\n"/utf8>>/binary, (gleam@string:join( Decoders, <<"\n\n"/utf8>> ))/binary>>/binary, "\n\n"/utf8>>/binary, Builtin_encoders/binary>>/binary, "\n\n"/utf8>>/binary, Builtin_decoders/binary>>/binary, Extra_tail/binary>>/binary, "\n"/utf8>>} end ) end ). -file("src/libero/json/codegen.gleam", 37). ?DOC( " Generate Gleam source for JSON typed encoders and decoders.\n" " Returns `Ok(source)` on success, or `Error(List(JsonError))` if any\n" " constructor has mixed labelled/unlabelled fields (rejected for JSON v1).\n" ). -spec generate(list(libero@walker:discovered_type())) -> {ok, binary()} | {error, list(libero@json@error:json_error())}. generate(Discovered) -> generate_with_extra(Discovered, [], <<""/utf8>>, false, false). -file("src/libero/json/codegen.gleam", 190). -spec has_client_context_push(list(libero@json@contract:push_contract())) -> boolean(). has_client_context_push(Push_types) -> gleam@list:any( Push_types, fun(Push) -> erlang:element(2, Push) =:= <<"__ClientContext__"/utf8>> end ). -file("src/libero/json/codegen.gleam", 259). -spec emit_ssr_helpers(list(libero@json@contract:ssr_model_contract())) -> binary(). emit_ssr_helpers(Ssr_models) -> _pipe = Ssr_models, _pipe@1 = gleam@list:flat_map( _pipe, fun(Model) -> Qual = libero@walker:qualified_atom_name( erlang:element(3, Model), erlang:element(4, Model) ), [<<<<<<<<<<<<"pub fn json_encode_ssr_"/utf8, Qual/binary>>/binary, "(value value) -> String {\n"/utf8>>/binary, " json_wire.encode_flags(json_encode_"/utf8>>/binary, Qual/binary>>/binary, "(value))\n"/utf8>>/binary, "}"/utf8>>, <<<<<<<<<<<<"pub fn json_decode_ssr_"/utf8, Qual/binary>>/binary, "(flags flags: String) {\n"/utf8>>/binary, " json_wire.decode_flags_typed(flags:, decoder: json_decode_"/utf8>>/binary, Qual/binary>>/binary, ")\n"/utf8>>/binary, "}"/utf8>>] end ), _pipe@2 = gleam@list:unique(_pipe@1), gleam@string:join(_pipe@2, <<"\n\n"/utf8>>). -file("src/libero/json/codegen.gleam", 214). -spec emit_client_context_helpers(list(libero@json@contract:push_contract())) -> binary(). emit_client_context_helpers(Push_types) -> _pipe = Push_types, _pipe@1 = gleam@list:filter( _pipe, fun(Push) -> erlang:element(2, Push) =:= <<"__ClientContext__"/utf8>> end ), _pipe@2 = gleam@list:flat_map( _pipe@1, fun(Push@1) -> Qual = libero@walker:qualified_atom_name( erlang:element(3, Push@1), erlang:element(4, Push@1) ), [<<<<<<<<<<<<<<<<"pub fn json_encode_client_context_"/utf8, Qual/binary>>/binary, "(value value) -> String {\n"/utf8>>/binary, " json_wire.encode_push(module: \""/utf8>>/binary, "__ClientContext__"/utf8>>/binary, "\", value: json_encode_"/utf8>>/binary, Qual/binary>>/binary, "(value))\n"/utf8>>/binary, "}"/utf8>>, <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"pub fn json_decode_client_context_"/utf8, Qual/binary>>/binary, "(data data: String) {\n"/utf8>>/binary, " case json_wire.decode_server_frame(data) {\n"/utf8>>/binary, " Ok(frame.Push(module:, value: raw)) -> case module {\n"/utf8>>/binary, " \""/utf8>>/binary, "__ClientContext__"/utf8>>/binary, "\" -> json_decode_"/utf8>>/binary, Qual/binary>>/binary, "(raw)\n"/utf8>>/binary, " other -> Error([JsonError(\"module\", \"expected "/utf8>>/binary, "__ClientContext__"/utf8>>/binary, ", got \" <> other)])\n"/utf8>>/binary, " }\n"/utf8>>/binary, " Ok(_) -> Error([JsonError(\"kind\", \"expected client-context push frame\")])\n"/utf8>>/binary, " Error(errors) -> Error(errors)\n"/utf8>>/binary, " }\n"/utf8>>/binary, "}"/utf8>>] end ), _pipe@3 = gleam@list:unique(_pipe@2), gleam@string:join(_pipe@3, <<"\n\n"/utf8>>). -file("src/libero/json/codegen.gleam", 194). -spec emit_push_helpers(list(libero@json@contract:push_contract())) -> binary(). emit_push_helpers(Push_types) -> _pipe = Push_types, _pipe@1 = gleam@list:map( _pipe, fun(Push) -> Qual = libero@walker:qualified_atom_name( erlang:element(3, Push), erlang:element(4, Push) ), <<<<<<<<<<<<"pub fn json_encode_push_"/utf8, Qual/binary>>/binary, "(module module: String, value value) -> String {\n"/utf8>>/binary, " json_wire.encode_push(module:, value: json_encode_"/utf8>>/binary, Qual/binary>>/binary, "(value))\n"/utf8>>/binary, "}"/utf8>> end ), _pipe@2 = gleam@list:unique(_pipe@1), gleam@string:join(_pipe@2, <<"\n\n"/utf8>>). -file("src/libero/json/codegen.gleam", 162). ?DOC(" Generate JSON codecs and transport wrappers for transport, push, and SSR.\n"). -spec generate_transport_codecs_with_push_and_ssr( list(libero@walker:discovered_type()), list(libero@json@contract:push_contract()), list(libero@json@contract:ssr_model_contract()) ) -> {ok, binary()} | {error, list(libero@json@error:json_error())}. generate_transport_codecs_with_push_and_ssr(Discovered, Push_types, Ssr_models) -> Transport_helpers = begin _pipe = [emit_push_helpers(Push_types), emit_client_context_helpers(Push_types), emit_ssr_helpers(Ssr_models)], _pipe@1 = gleam@list:filter(_pipe, fun(Src) -> Src /= <<""/utf8>> end), _pipe@2 = gleam@string:join(_pipe@1, <<"\n\n"/utf8>>), (fun(Src@1) -> case Src@1 of <<""/utf8>> -> <<""/utf8>>; _ -> <<"\n\n"/utf8, Src@1/binary>> end end)(_pipe@2) end, generate_with_extra( Discovered, [], Transport_helpers, not gleam@list:is_empty(Push_types) orelse not gleam@list:is_empty( Ssr_models ), has_client_context_push(Push_types) ).