Current section

Files

Jump to
oaspec src oaspec@internal@codegen@encoders.erl
Raw

src/oaspec@internal@codegen@encoders.erl

-module(oaspec@internal@codegen@encoders).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/internal/codegen/encoders.gleam").
-export([generate/1]).
-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(false).
-file("src/oaspec/internal/codegen/encoders.gleam", 853).
?DOC(false).
-spec generate_primitive_encoder(
gleam@string_tree:string_tree(),
binary(),
binary(),
binary(),
binary()
) -> gleam@string_tree:string_tree().
generate_primitive_encoder(Sb, Fn_name, Json_fn_name, Gleam_type, Json_expr) ->
_pipe = Sb,
_pipe@1 = oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<<<"pub fn "/utf8, Json_fn_name/binary>>/binary, "(value: "/utf8>>/binary,
Gleam_type/binary>>/binary,
") -> json.Json {"/utf8>>
),
_pipe@2 = oaspec@internal@util@string_extra:indent(_pipe@1, 1, Json_expr),
_pipe@3 = oaspec@internal@util@string_extra:line(_pipe@2, <<"}"/utf8>>),
_pipe@4 = oaspec@internal@util@string_extra:blank_line(_pipe@3),
_pipe@5 = oaspec@internal@util@string_extra:line(
_pipe@4,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary, "(value: "/utf8>>/binary,
Gleam_type/binary>>/binary,
") -> String {"/utf8>>
),
_pipe@6 = oaspec@internal@util@string_extra:indent(
_pipe@5,
1,
<<Json_fn_name/binary, "(value) |> json.to_string()"/utf8>>
),
_pipe@7 = oaspec@internal@util@string_extra:line(_pipe@6, <<"}"/utf8>>),
oaspec@internal@util@string_extra:blank_line(_pipe@7).
-file("src/oaspec/internal/codegen/encoders.gleam", 905).
?DOC(false).
-spec schema_ref_to_json_encoder_fn(
oaspec@internal@openapi@schema:schema_ref(),
binary(),
binary()
) -> binary().
schema_ref_to_json_encoder_fn(Ref, Parent_name, Prop_name) ->
case Ref of
{inline, {string_schema, _, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
<<<<"encode_"/utf8,
(oaspec@internal@util@naming:to_snake_case(
<<(oaspec@internal@util@naming:schema_to_type_name(
Parent_name
))/binary,
(oaspec@internal@util@naming:schema_to_type_name(
Prop_name
))/binary>>
))/binary>>/binary,
"_json"/utf8>>;
{inline, {array_schema, _, Items, _, _, _}} ->
Inner = schema_ref_to_json_encoder_fn(Items, Parent_name, Prop_name),
<<<<"fn(items) { json.array(items, "/utf8, Inner/binary>>/binary,
") }"/utf8>>;
_ ->
oaspec@internal@codegen@schema_dispatch:json_encoder_fn(Ref)
end.
-file("src/oaspec/internal/codegen/encoders.gleam", 877).
?DOC(false).
-spec schema_ref_to_json_encoder(
binary(),
oaspec@internal@openapi@schema:schema_ref(),
binary(),
binary()
) -> binary().
schema_ref_to_json_encoder(Value_expr, Ref, Parent_name, Prop_name) ->
case Ref of
{inline, {string_schema, _, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
Fn_name = <<<<"encode_"/utf8,
(oaspec@internal@util@naming:to_snake_case(
<<(oaspec@internal@util@naming:schema_to_type_name(
Parent_name
))/binary,
(oaspec@internal@util@naming:schema_to_type_name(
Prop_name
))/binary>>
))/binary>>/binary,
"_json"/utf8>>,
<<<<<<Fn_name/binary, "("/utf8>>/binary, Value_expr/binary>>/binary,
")"/utf8>>;
{inline, {array_schema, _, Items, _, _, _}} ->
Inner_fn = schema_ref_to_json_encoder_fn(
Items,
Parent_name,
Prop_name
),
<<<<<<<<"json.array("/utf8, Value_expr/binary>>/binary, ", "/utf8>>/binary,
Inner_fn/binary>>/binary,
")"/utf8>>;
_ ->
oaspec@internal@codegen@schema_dispatch:json_encoder_expr(
Ref,
Value_expr
)
end.
-file("src/oaspec/internal/codegen/encoders.gleam", 285).
?DOC(false).
-spec generate_encoder(
gleam@string_tree:string_tree(),
binary(),
oaspec@internal@openapi@schema:schema_ref(),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_encoder(Sb, Name, Schema_ref, Ctx) ->
Type_name = oaspec@internal@util@naming:schema_to_type_name(Name),
Fn_name = <<"encode_"/utf8,
(oaspec@internal@util@naming:to_snake_case(Name))/binary>>,
Json_fn_name = <<Fn_name/binary, "_json"/utf8>>,
case Schema_ref of
{inline,
{object_schema,
_,
Properties,
Required,
Additional_properties,
_,
_}} ->
Sb@1 = begin
_pipe = Sb,
oaspec@internal@util@string_extra:line(
_pipe,
<<<<<<<<"pub fn "/utf8, Json_fn_name/binary>>/binary,
"(value: types."/utf8>>/binary,
Type_name/binary>>/binary,
") -> json.Json {"/utf8>>
)
end,
Has_ap = case Additional_properties of
{typed, _} ->
true;
untyped ->
true;
forbidden ->
false;
unspecified ->
false
end,
All_props = oaspec@internal@codegen@ir_build:sorted_entries(
Properties
),
All_deduped_names = oaspec@internal@openapi@dedup:dedup_property_names(
gleam@list:map(All_props, fun(E) -> erlang:element(1, E) end)
),
Props_with_names = begin
_pipe@1 = gleam@list:index_map(
All_props,
fun(Entry, Idx) ->
{Prop_name, Prop_ref} = Entry,
Field_name = oaspec@internal@codegen@codec_helpers:list_at_or(
All_deduped_names,
Idx,
oaspec@internal@util@naming:to_snake_case(Prop_name)
),
{Prop_name, Prop_ref, Field_name}
end
),
gleam@list:filter(
_pipe@1,
fun(Entry@1) ->
{_, Prop_ref@1, _} = Entry@1,
not oaspec@internal@codegen@schema_utils:schema_ref_is_read_only(
Prop_ref@1,
Ctx
)
end
)
end,
Has_omittable = gleam@list:any(
Props_with_names,
fun(Entry@2) ->
{Prop_name@1, Prop_ref@2, _} = Entry@2,
not gleam@list:contains(Required, Prop_name@1) andalso not oaspec@internal@codegen@schema_utils:schema_ref_is_nullable(
Prop_ref@2,
Ctx
)
end
),
Sb@2 = case {Has_ap, Has_omittable} of
{true, false} ->
_pipe@2 = Sb@1,
oaspec@internal@util@string_extra:indent(
_pipe@2,
1,
<<"let base_props = ["/utf8>>
);
{true, true} ->
_pipe@3 = Sb@1,
oaspec@internal@util@string_extra:indent(
_pipe@3,
1,
<<"let base_props = list.flatten(["/utf8>>
);
{false, false} ->
_pipe@4 = Sb@1,
oaspec@internal@util@string_extra:indent(
_pipe@4,
1,
<<"json.object(["/utf8>>
);
{false, true} ->
_pipe@5 = Sb@1,
oaspec@internal@util@string_extra:indent(
_pipe@5,
1,
<<"json.object(list.flatten(["/utf8>>
)
end,
Sb@4 = gleam@list:index_fold(
Props_with_names,
Sb@2,
fun(Sb@3, Entry@3, Idx@1) ->
{Prop_name@2, Prop_ref@3, Field_name@1} = Entry@3,
Is_required = gleam@list:contains(Required, Prop_name@2),
Trailing = case Idx@1 =:= (erlang:length(Props_with_names) - 1) of
true ->
<<""/utf8>>;
false ->
<<","/utf8>>
end,
Encoder_expr = case oaspec@internal@codegen@schema_utils:constant_property_value(
Prop_ref@3,
Prop_name@2,
Required
) of
{some, Constant_value} ->
<<<<"json.string(\""/utf8,
(oaspec@internal@codegen@codec_helpers:escape_for_string_literal(
Constant_value
))/binary>>/binary,
"\")"/utf8>>;
none ->
schema_ref_to_json_encoder(
<<"value."/utf8, Field_name@1/binary>>,
Prop_ref@3,
Name,
Prop_name@2
)
end,
Is_nullable = oaspec@internal@codegen@schema_utils:schema_ref_is_nullable(
Prop_ref@3,
Ctx
),
Is_omittable = not Is_required andalso not Is_nullable,
case {Has_omittable, Is_required, Is_nullable, Is_omittable} of
{false, true, false, _} ->
_pipe@6 = Sb@3,
oaspec@internal@util@string_extra:indent(
_pipe@6,
2,
<<<<<<<<<<"#(\""/utf8, Prop_name@2/binary>>/binary,
"\", "/utf8>>/binary,
Encoder_expr/binary>>/binary,
")"/utf8>>/binary,
Trailing/binary>>
);
{false, _, _, _} ->
_pipe@7 = Sb@3,
oaspec@internal@util@string_extra:indent(
_pipe@7,
2,
<<<<<<<<<<<<<<"#(\""/utf8, Prop_name@2/binary>>/binary,
"\", json.nullable(value."/utf8>>/binary,
Field_name@1/binary>>/binary,
", "/utf8>>/binary,
(schema_ref_to_json_encoder_fn(
Prop_ref@3,
Name,
Prop_name@2
))/binary>>/binary,
"))"/utf8>>/binary,
Trailing/binary>>
);
{true, _, _, true} ->
Some_encoder_expr = schema_ref_to_json_encoder(
<<"x"/utf8>>,
Prop_ref@3,
Name,
Prop_name@2
),
_pipe@8 = Sb@3,
_pipe@9 = oaspec@internal@util@string_extra:indent(
_pipe@8,
2,
<<<<"case value."/utf8, Field_name@1/binary>>/binary,
" {"/utf8>>
),
_pipe@10 = oaspec@internal@util@string_extra:indent(
_pipe@9,
3,
<<"option.None -> []"/utf8>>
),
_pipe@11 = oaspec@internal@util@string_extra:indent(
_pipe@10,
3,
<<<<<<<<"option.Some(x) -> [#(\""/utf8,
Prop_name@2/binary>>/binary,
"\", "/utf8>>/binary,
Some_encoder_expr/binary>>/binary,
")]"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@11,
2,
<<"}"/utf8, Trailing/binary>>
);
{true, true, false, _} ->
_pipe@12 = Sb@3,
oaspec@internal@util@string_extra:indent(
_pipe@12,
2,
<<<<<<<<<<"[#(\""/utf8, Prop_name@2/binary>>/binary,
"\", "/utf8>>/binary,
Encoder_expr/binary>>/binary,
")]"/utf8>>/binary,
Trailing/binary>>
);
{true, _, _, _} ->
_pipe@13 = Sb@3,
oaspec@internal@util@string_extra:indent(
_pipe@13,
2,
<<<<<<<<<<<<<<"[#(\""/utf8, Prop_name@2/binary>>/binary,
"\", json.nullable(value."/utf8>>/binary,
Field_name@1/binary>>/binary,
", "/utf8>>/binary,
(schema_ref_to_json_encoder_fn(
Prop_ref@3,
Name,
Prop_name@2
))/binary>>/binary,
"))]"/utf8>>/binary,
Trailing/binary>>
)
end
end
),
Close_props_list = case Has_omittable of
true ->
<<"])"/utf8>>;
false ->
<<"]"/utf8>>
end,
Sb@5 = case Additional_properties of
{typed, Ap_ref} ->
Inner_encoder_fn = schema_ref_to_json_encoder_fn(
Ap_ref,
Name,
<<"additional_properties"/utf8>>
),
_pipe@14 = Sb@4,
_pipe@15 = oaspec@internal@util@string_extra:indent(
_pipe@14,
1,
Close_props_list
),
_pipe@16 = oaspec@internal@util@string_extra:indent(
_pipe@15,
1,
<<"let extra_props ="/utf8>>
),
_pipe@17 = oaspec@internal@util@string_extra:indent(
_pipe@16,
2,
<<"dict.to_list(value.additional_properties)"/utf8>>
),
_pipe@18 = oaspec@internal@util@string_extra:indent(
_pipe@17,
2,
<<"|> list.map(fn(entry) {"/utf8>>
),
_pipe@19 = oaspec@internal@util@string_extra:indent(
_pipe@18,
3,
<<"let #(k, v) = entry"/utf8>>
),
_pipe@20 = oaspec@internal@util@string_extra:indent(
_pipe@19,
3,
<<<<"#(k, "/utf8, Inner_encoder_fn/binary>>/binary,
"(v))"/utf8>>
),
_pipe@21 = oaspec@internal@util@string_extra:indent(
_pipe@20,
2,
<<"})"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@21,
1,
<<"json.object(list.append(base_props, extra_props))"/utf8>>
);
untyped ->
_pipe@22 = Sb@4,
_pipe@23 = oaspec@internal@util@string_extra:indent(
_pipe@22,
1,
Close_props_list
),
_pipe@24 = oaspec@internal@util@string_extra:indent(
_pipe@23,
1,
<<"let extra_props ="/utf8>>
),
_pipe@25 = oaspec@internal@util@string_extra:indent(
_pipe@24,
2,
<<"dict.to_list(value.additional_properties)"/utf8>>
),
_pipe@26 = oaspec@internal@util@string_extra:indent(
_pipe@25,
2,
<<"|> list.map(fn(entry) {"/utf8>>
),
_pipe@27 = oaspec@internal@util@string_extra:indent(
_pipe@26,
3,
<<"let #(k, v) = entry"/utf8>>
),
_pipe@28 = oaspec@internal@util@string_extra:indent(
_pipe@27,
3,
<<"#(k, encode_dynamic(v))"/utf8>>
),
_pipe@29 = oaspec@internal@util@string_extra:indent(
_pipe@28,
2,
<<"})"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@29,
1,
<<"json.object(list.append(base_props, extra_props))"/utf8>>
);
forbidden ->
_pipe@30 = Sb@4,
oaspec@internal@util@string_extra:indent(
_pipe@30,
1,
case Has_omittable of
true ->
<<"]))"/utf8>>;
false ->
<<"])"/utf8>>
end
);
unspecified ->
_pipe@30 = Sb@4,
oaspec@internal@util@string_extra:indent(
_pipe@30,
1,
case Has_omittable of
true ->
<<"]))"/utf8>>;
false ->
<<"])"/utf8>>
end
)
end,
Sb@6 = begin
_pipe@31 = Sb@5,
_pipe@32 = oaspec@internal@util@string_extra:line(
_pipe@31,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@32)
end,
_pipe@33 = Sb@6,
_pipe@34 = oaspec@internal@util@string_extra:line(
_pipe@33,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: types."/utf8>>/binary,
Type_name/binary>>/binary,
") -> String {"/utf8>>
),
_pipe@35 = oaspec@internal@util@string_extra:indent(
_pipe@34,
1,
<<Json_fn_name/binary, "(value) |> json.to_string()"/utf8>>
),
_pipe@36 = oaspec@internal@util@string_extra:line(
_pipe@35,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@36);
{inline, {string_schema, _, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
Enc_deduped_variants = oaspec@internal@openapi@dedup:dedup_enum_variants(
Enum_values
),
Sb@7 = begin
_pipe@37 = Sb,
_pipe@38 = oaspec@internal@util@string_extra:line(
_pipe@37,
<<<<<<<<"pub fn "/utf8, Json_fn_name/binary>>/binary,
"(value: types."/utf8>>/binary,
Type_name/binary>>/binary,
") -> json.Json {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@38,
1,
<<"let str = case value {"/utf8>>
)
end,
Sb@9 = gleam@list:index_fold(
Enum_values,
Sb@7,
fun(Sb@8, Value, Idx@2) ->
Variant_suffix = oaspec@internal@codegen@codec_helpers:list_at_or(
Enc_deduped_variants,
Idx@2,
oaspec@internal@util@naming:to_pascal_case(Value)
),
Variant = <<(oaspec@internal@util@naming:schema_to_type_name(
Type_name
))/binary,
Variant_suffix/binary>>,
_pipe@39 = Sb@8,
oaspec@internal@util@string_extra:indent(
_pipe@39,
2,
<<<<<<<<"types."/utf8, Variant/binary>>/binary,
" -> \""/utf8>>/binary,
Value/binary>>/binary,
"\""/utf8>>
)
end
),
Sb@10 = begin
_pipe@40 = Sb@9,
_pipe@41 = oaspec@internal@util@string_extra:indent(
_pipe@40,
1,
<<"}"/utf8>>
),
_pipe@42 = oaspec@internal@util@string_extra:indent(
_pipe@41,
1,
<<"json.string(str)"/utf8>>
),
_pipe@43 = oaspec@internal@util@string_extra:line(
_pipe@42,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@43)
end,
Sb@11 = begin
_pipe@44 = Sb@10,
_pipe@45 = oaspec@internal@util@string_extra:line(
_pipe@44,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: types."/utf8>>/binary,
Type_name/binary>>/binary,
") -> String {"/utf8>>
),
_pipe@46 = oaspec@internal@util@string_extra:indent(
_pipe@45,
1,
<<Json_fn_name/binary, "(value) |> json.to_string()"/utf8>>
),
_pipe@47 = oaspec@internal@util@string_extra:line(
_pipe@46,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@47)
end,
To_string_fn_name = <<Fn_name/binary, "_to_string"/utf8>>,
Sb@12 = begin
_pipe@48 = Sb@11,
_pipe@49 = oaspec@internal@util@string_extra:line(
_pipe@48,
<<<<<<<<"pub fn "/utf8, To_string_fn_name/binary>>/binary,
"(value: types."/utf8>>/binary,
Type_name/binary>>/binary,
") -> String {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@49,
1,
<<"case value {"/utf8>>
)
end,
Sb@14 = gleam@list:index_fold(
Enum_values,
Sb@12,
fun(Sb@13, Value@1, Idx@3) ->
Variant_suffix@1 = oaspec@internal@codegen@codec_helpers:list_at_or(
Enc_deduped_variants,
Idx@3,
oaspec@internal@util@naming:to_pascal_case(Value@1)
),
Variant@1 = <<(oaspec@internal@util@naming:schema_to_type_name(
Type_name
))/binary,
Variant_suffix@1/binary>>,
_pipe@50 = Sb@13,
oaspec@internal@util@string_extra:indent(
_pipe@50,
2,
<<<<<<<<"types."/utf8, Variant@1/binary>>/binary,
" -> \""/utf8>>/binary,
Value@1/binary>>/binary,
"\""/utf8>>
)
end
),
_pipe@51 = Sb@14,
_pipe@52 = oaspec@internal@util@string_extra:indent(
_pipe@51,
1,
<<"}"/utf8>>
),
_pipe@53 = oaspec@internal@util@string_extra:line(
_pipe@52,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@53);
{inline, {all_of_schema, Metadata, Schemas}} ->
Merged = oaspec@internal@codegen@allof_merge:merge_allof_schemas(
Schemas,
Ctx
),
Merged_schema = {inline,
{object_schema,
Metadata,
erlang:element(2, Merged),
erlang:element(3, Merged),
erlang:element(4, Merged),
none,
none}},
generate_encoder(Sb, Name, Merged_schema, Ctx);
{inline, {one_of_schema, _, Schemas@1, _}} ->
All_refs = gleam@list:all(Schemas@1, fun(S) -> case S of
{reference, _, _} ->
true;
_ ->
false
end end),
case All_refs of
false ->
erlang:error(#{gleam_error => panic,
message => (<<<<<<"oaspec: oneOf schema '"/utf8,
Name/binary>>/binary,
"' contains inline variant(s) which are not supported for encoder generation. "/utf8>>/binary,
"Move all oneOf variants to components/schemas and use $ref instead."/utf8>>),
file => <<?FILEPATH/utf8>>,
module => <<"oaspec/internal/codegen/encoders"/utf8>>,
function => <<"generate_encoder"/utf8>>,
line => 637});
true ->
Sb@15 = begin
_pipe@54 = Sb,
_pipe@55 = oaspec@internal@util@string_extra:line(
_pipe@54,
<<<<<<<<"pub fn "/utf8, Json_fn_name/binary>>/binary,
"(value: types."/utf8>>/binary,
Type_name/binary>>/binary,
") -> json.Json {"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@55,
1,
<<"case value {"/utf8>>
)
end,
Sb@17 = gleam@list:fold(
Schemas@1,
Sb@15,
fun(Sb@16, S_ref) -> case S_ref of
{reference, _, Name@1} ->
Variant_type = oaspec@internal@util@naming:schema_to_type_name(
Name@1
),
Variant_name = <<Type_name/binary,
Variant_type/binary>>,
Inner_encoder = <<<<"encode_"/utf8,
(oaspec@internal@util@naming:to_snake_case(
Name@1
))/binary>>/binary,
"_json"/utf8>>,
_pipe@56 = Sb@16,
oaspec@internal@util@string_extra:indent(
_pipe@56,
2,
<<<<<<<<"types."/utf8,
Variant_name/binary>>/binary,
"(inner) -> "/utf8>>/binary,
Inner_encoder/binary>>/binary,
"(inner)"/utf8>>
);
_ ->
Sb@16
end end
),
Sb@18 = begin
_pipe@57 = Sb@17,
_pipe@58 = oaspec@internal@util@string_extra:indent(
_pipe@57,
1,
<<"}"/utf8>>
),
_pipe@59 = oaspec@internal@util@string_extra:line(
_pipe@58,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@59)
end,
_pipe@60 = Sb@18,
_pipe@61 = oaspec@internal@util@string_extra:line(
_pipe@60,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: types."/utf8>>/binary,
Type_name/binary>>/binary,
") -> String {"/utf8>>
),
_pipe@62 = oaspec@internal@util@string_extra:indent(
_pipe@61,
1,
<<Json_fn_name/binary,
"(value) |> json.to_string()"/utf8>>
),
_pipe@63 = oaspec@internal@util@string_extra:line(
_pipe@62,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@63)
end;
{inline, {any_of_schema, _, Schemas@2, _}} ->
All_refs@1 = gleam@list:all(Schemas@2, fun(S@1) -> case S@1 of
{reference, _, _} ->
true;
_ ->
false
end end),
case All_refs@1 of
false ->
erlang:error(#{gleam_error => panic,
message => (<<<<<<"oaspec: anyOf schema '"/utf8,
Name/binary>>/binary,
"' contains inline variant(s) which are not supported for encoder generation. "/utf8>>/binary,
"Move all anyOf variants to components/schemas and use $ref instead."/utf8>>),
file => <<?FILEPATH/utf8>>,
module => <<"oaspec/internal/codegen/encoders"/utf8>>,
function => <<"generate_encoder"/utf8>>,
line => 706});
true ->
Variant_fields = gleam@list:map(
Schemas@2,
fun(S_ref@1) -> case S_ref@1 of
{reference, _, Name@2} ->
{oaspec@internal@util@naming:to_snake_case(
Name@2
),
<<<<"encode_"/utf8,
(oaspec@internal@util@naming:to_snake_case(
Name@2
))/binary>>/binary,
"_json"/utf8>>};
{inline, _} ->
{<<"unknown"/utf8>>, <<"json.null"/utf8>>}
end end
),
Sb@19 = begin
_pipe@64 = Sb,
oaspec@internal@util@string_extra:line(
_pipe@64,
<<<<<<<<"pub fn "/utf8, Json_fn_name/binary>>/binary,
"(value: types."/utf8>>/binary,
Type_name/binary>>/binary,
") -> json.Json {"/utf8>>
)
end,
Sb@21 = gleam@list:fold(
Variant_fields,
Sb@19,
fun(Sb@20, Field) ->
{Field_name@2, Encoder_fn} = Field,
_pipe@65 = Sb@20,
_pipe@66 = oaspec@internal@util@string_extra:indent(
_pipe@65,
1,
<<<<"case value."/utf8, Field_name@2/binary>>/binary,
" {"/utf8>>
),
_pipe@67 = oaspec@internal@util@string_extra:indent(
_pipe@66,
2,
<<<<"option.Some(v) -> "/utf8,
Encoder_fn/binary>>/binary,
"(v)"/utf8>>
),
oaspec@internal@util@string_extra:indent(
_pipe@67,
2,
<<"option.None ->"/utf8>>
)
end
),
Sb@22 = begin
_pipe@68 = Sb@21,
oaspec@internal@util@string_extra:indent(
_pipe@68,
(erlang:length(Variant_fields) + 1),
<<"json.null()"/utf8>>
)
end,
Sb@24 = gleam@list:fold(
Variant_fields,
Sb@22,
fun(Sb@23, _) -> _pipe@69 = Sb@23,
oaspec@internal@util@string_extra:indent(
_pipe@69,
1,
<<"}"/utf8>>
) end
),
Sb@25 = begin
_pipe@70 = Sb@24,
_pipe@71 = oaspec@internal@util@string_extra:line(
_pipe@70,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@71)
end,
_pipe@72 = Sb@25,
_pipe@73 = oaspec@internal@util@string_extra:line(
_pipe@72,
<<<<<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
"(value: types."/utf8>>/binary,
Type_name/binary>>/binary,
") -> String {"/utf8>>
),
_pipe@74 = oaspec@internal@util@string_extra:indent(
_pipe@73,
1,
<<Json_fn_name/binary,
"(value) |> json.to_string()"/utf8>>
),
_pipe@75 = oaspec@internal@util@string_extra:line(
_pipe@74,
<<"}"/utf8>>
),
oaspec@internal@util@string_extra:blank_line(_pipe@75)
end;
{inline, {string_schema, Metadata@1, _, [], _, _, _}} ->
{Gleam_type, Json_expr} = case erlang:element(3, Metadata@1) of
true ->
{<<"Option(String)"/utf8>>,
<<"json.nullable(value, json.string)"/utf8>>};
false ->
{<<"String"/utf8>>, <<"json.string(value)"/utf8>>}
end,
generate_primitive_encoder(
Sb,
Fn_name,
Json_fn_name,
Gleam_type,
Json_expr
);
{inline, {integer_schema, Metadata@2, _, _, _, _, _, _}} ->
{Gleam_type@1, Json_expr@1} = case erlang:element(3, Metadata@2) of
true ->
{<<"Option(Int)"/utf8>>,
<<"json.nullable(value, json.int)"/utf8>>};
false ->
{<<"Int"/utf8>>, <<"json.int(value)"/utf8>>}
end,
generate_primitive_encoder(
Sb,
Fn_name,
Json_fn_name,
Gleam_type@1,
Json_expr@1
);
{inline, {number_schema, Metadata@3, _, _, _, _, _, _}} ->
{Gleam_type@2, Json_expr@2} = case erlang:element(3, Metadata@3) of
true ->
{<<"Option(Float)"/utf8>>,
<<"json.nullable(value, json.float)"/utf8>>};
false ->
{<<"Float"/utf8>>, <<"json.float(value)"/utf8>>}
end,
generate_primitive_encoder(
Sb,
Fn_name,
Json_fn_name,
Gleam_type@2,
Json_expr@2
);
{inline, {boolean_schema, Metadata@4}} ->
{Gleam_type@3, Json_expr@3} = case erlang:element(3, Metadata@4) of
true ->
{<<"Option(Bool)"/utf8>>,
<<"json.nullable(value, json.bool)"/utf8>>};
false ->
{<<"Bool"/utf8>>, <<"json.bool(value)"/utf8>>}
end,
generate_primitive_encoder(
Sb,
Fn_name,
Json_fn_name,
Gleam_type@3,
Json_expr@3
);
{inline, {array_schema, Metadata@5, Items, _, _, _}} ->
Inner_type = oaspec@internal@codegen@codec_helpers:qualified_schema_ref_type(
Items,
Ctx
),
List_type = <<<<"List("/utf8, Inner_type/binary>>/binary, ")"/utf8>>,
Inner_encoder@1 = schema_ref_to_json_encoder_fn(
Items,
Name,
<<""/utf8>>
),
Array_expr = <<<<"json.array(value, "/utf8, Inner_encoder@1/binary>>/binary,
")"/utf8>>,
{Gleam_type@4, Json_expr@4} = case erlang:element(3, Metadata@5) of
true ->
{<<<<"Option("/utf8, List_type/binary>>/binary, ")"/utf8>>,
<<<<"json.nullable(value, fn(value) { "/utf8,
Array_expr/binary>>/binary,
" })"/utf8>>};
false ->
{List_type, Array_expr}
end,
generate_primitive_encoder(
Sb,
Fn_name,
Json_fn_name,
Gleam_type@4,
Json_expr@4
);
_ ->
Sb
end.
-file("src/oaspec/internal/codegen/encoders.gleam", 199).
?DOC(false).
-spec generate_inline_enum_encoders(
gleam@string_tree:string_tree(),
binary(),
oaspec@internal@openapi@schema:schema_ref(),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_inline_enum_encoders(Sb, Parent_name, Schema_ref, Ctx) ->
{Props, Required@1} = case Schema_ref of
{inline, {object_schema, _, Properties, Required, _, _, _}} ->
{oaspec@internal@codegen@ir_build:sorted_entries(Properties),
Required};
{inline, {all_of_schema, _, Schemas}} ->
Merged = oaspec@internal@codegen@allof_merge:merge_allof_schemas(
Schemas,
Ctx
),
{oaspec@internal@codegen@ir_build:sorted_entries(
erlang:element(2, Merged)
),
erlang:element(3, Merged)};
_ ->
{[], []}
end,
gleam@list:fold(
Props,
Sb,
fun(Sb@1, Entry) ->
{Prop_name, Prop_ref} = Entry,
case oaspec@internal@codegen@schema_utils:constant_property_value(
Prop_ref,
Prop_name,
Required@1
) of
{some, _} ->
Sb@1;
none ->
case Prop_ref of
{inline, {string_schema, _, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
Enum_name = <<(oaspec@internal@util@naming:schema_to_type_name(
Parent_name
))/binary,
(oaspec@internal@util@naming:schema_to_type_name(
Prop_name
))/binary>>,
generate_encoder(Sb@1, Enum_name, Prop_ref, Ctx);
_ ->
Sb@1
end
end
end
).
-file("src/oaspec/internal/codegen/encoders.gleam", 252).
?DOC(false).
-spec generate_anonymous_request_body_encoder(
gleam@string_tree:string_tree(),
binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
oaspec@internal@codegen@context:context()
) -> gleam@string_tree:string_tree().
generate_anonymous_request_body_encoder(Sb, Op_id, Operation, Ctx) ->
case erlang:element(7, Operation) of
{some, {value, Rb}} ->
Content_entries = oaspec@internal@codegen@ir_build:sorted_entries(
erlang:element(3, Rb)
),
case Content_entries of
[{_, Media_type} | _] ->
case erlang:element(2, Media_type) of
{some, {inline, Schema_obj}} ->
Filtered_schema = oaspec@internal@codegen@schema_utils:filter_read_only_properties(
Schema_obj,
Ctx
),
Name = <<(oaspec@internal@util@naming:to_snake_case(
Op_id
))/binary,
"_request_body"/utf8>>,
generate_encoder(
Sb,
Name,
{inline, Filtered_schema},
Ctx
);
_ ->
Sb
end;
_ ->
Sb
end;
{some, {ref, _}} ->
Sb;
none ->
Sb
end.
-file("src/oaspec/internal/codegen/encoders.gleam", 239).
?DOC(false).
-spec generate_anonymous_encoders(
gleam@string_tree:string_tree(),
oaspec@internal@codegen@context:context(),
list({binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
binary(),
oaspec@internal@openapi@spec:http_method()})
) -> gleam@string_tree:string_tree().
generate_anonymous_encoders(Sb, Ctx, Operations) ->
gleam@list:fold(
Operations,
Sb,
fun(Sb@1, Op) ->
{Op_id, Operation, _, _} = Op,
generate_anonymous_request_body_encoder(Sb@1, Op_id, Operation, Ctx)
end
).
-file("src/oaspec/internal/codegen/encoders.gleam", 932).
?DOC(false).
-spec ensure_import(list(binary()), binary()) -> list(binary()).
ensure_import(Imports, Name) ->
gleam@bool:guard(
gleam@list:contains(Imports, Name),
Imports,
fun() -> lists:append(Imports, [Name]) end
).
-file("src/oaspec/internal/codegen/encoders.gleam", 50).
?DOC(false).
-spec generate_encoders(
oaspec@internal@codegen@context:context(),
list({binary(),
oaspec@internal@openapi@spec:operation(oaspec@internal@openapi@spec:resolved()),
binary(),
oaspec@internal@openapi@spec:http_method()})
) -> binary().
generate_encoders(Ctx, Operations) ->
Schemas = case erlang:element(5, oaspec@internal@codegen@context:spec(Ctx)) of
{some, Components} ->
_pipe = gleam@list:sort(
maps:to_list(erlang:element(2, Components)),
fun(A, B) ->
gleam@string:compare(
erlang:element(1, A),
erlang:element(1, B)
)
end
),
gleam@list:filter(
_pipe,
fun(Entry) ->
not oaspec@internal@codegen@ir_build:is_internal_schema(
erlang:element(2, Entry)
)
end
);
none ->
[]
end,
Needs_types = gleam@list:any(
Schemas,
fun(Entry@1) ->
{_, Schema_ref} = Entry@1,
case Schema_ref of
{inline, {object_schema, _, _, _, _, _, _}} ->
true;
{inline, {all_of_schema, _, _}} ->
true;
{inline, {one_of_schema, _, _, _}} ->
true;
{inline, {any_of_schema, _, _, _}} ->
true;
{inline, {string_schema, _, _, Enum_values, _, _, _}} when Enum_values =/= [] ->
true;
_ ->
false
end
end
),
Needs_dict = gleam@list:any(
Schemas,
fun(Entry@2) ->
{_, Schema_ref@1} = Entry@2,
case Schema_ref@1 of
{inline, {object_schema, _, _, _, {typed, _}, _, _}} ->
true;
{inline, {object_schema, _, _, _, untyped, _, _}} ->
true;
_ ->
false
end
end
),
Needs_dynamic = gleam@list:any(
Schemas,
fun(Entry@3) ->
{_, Schema_ref@2} = Entry@3,
case Schema_ref@2 of
{inline, {object_schema, _, _, _, untyped, _, _}} ->
true;
_ ->
false
end
end
),
Needs_option_and_list = gleam@list:any(
Schemas,
fun(Entry@4) ->
{_, Schema_ref@3} = Entry@4,
case Schema_ref@3 of
{inline, {object_schema, _, Properties, Required, _, _, _}} ->
_pipe@1 = Properties,
_pipe@2 = oaspec@internal@codegen@ir_build:sorted_entries(
_pipe@1
),
gleam@list:any(
_pipe@2,
fun(P) ->
{Prop_name, Prop_ref} = P,
not gleam@list:contains(Required, Prop_name) andalso not oaspec@internal@codegen@schema_utils:schema_ref_is_nullable(
Prop_ref,
Ctx
)
end
);
_ ->
false
end
end
),
Base_imports = case {Needs_dict, Needs_dynamic} of
{true, true} ->
[<<"gleam/dict"/utf8>>,
<<"gleam/dynamic"/utf8>>,
<<"gleam/dynamic/decode"/utf8>>,
<<"gleam/json"/utf8>>,
<<"gleam/list"/utf8>>];
{true, false} ->
[<<"gleam/dict"/utf8>>,
<<"gleam/json"/utf8>>,
<<"gleam/list"/utf8>>];
{_, _} ->
[<<"gleam/json"/utf8>>]
end,
Needs_bare_option_type = gleam@list:any(
Schemas,
fun(Entry@5) ->
{_, Schema_ref@4} = Entry@5,
oaspec@internal@codegen@codec_helpers:schema_ref_has_bare_option_type(
Schema_ref@4
)
end
),
Option_import_line = case Needs_bare_option_type of
true ->
<<"gleam/option.{type Option}"/utf8>>;
false ->
<<"gleam/option"/utf8>>
end,
Base_imports@1 = case Needs_option_and_list of
true ->
_pipe@3 = Base_imports,
_pipe@4 = ensure_import(_pipe@3, <<"gleam/list"/utf8>>),
ensure_import(_pipe@4, Option_import_line);
false ->
Base_imports
end,
Imports = case Needs_types of
true ->
lists:append(
Base_imports@1,
[<<(oaspec@config:package(
oaspec@internal@codegen@context:config(Ctx)
))/binary,
"/types"/utf8>>]
);
false ->
Base_imports@1
end,
Sb = begin
_pipe@5 = oaspec@internal@util@string_extra:file_header(
<<"0.50.0"/utf8>>
),
oaspec@internal@util@string_extra:imports(_pipe@5, Imports)
end,
Sb@2 = gleam@list:fold(
Schemas,
Sb,
fun(Sb@1, Entry@6) ->
{Name, Schema_ref@5} = Entry@6,
generate_inline_enum_encoders(Sb@1, Name, Schema_ref@5, Ctx)
end
),
Sb@4 = gleam@list:fold(
Schemas,
Sb@2,
fun(Sb@3, Entry@7) ->
{Name@1, Schema_ref@6} = Entry@7,
generate_encoder(Sb@3, Name@1, Schema_ref@6, Ctx)
end
),
Sb@5 = generate_anonymous_encoders(Sb@4, Ctx, Operations),
Sb@6 = case Needs_dynamic of
true ->
_pipe@6 = Sb@5,
_pipe@7 = oaspec@internal@util@string_extra:doc_comment(
_pipe@6,
<<"Encode a Dynamic value to JSON by inspecting its runtime type."/utf8>>
),
oaspec@internal@util@string_extra:raw(
_pipe@7,
<<"fn encode_dynamic(value: dynamic.Dynamic) -> json.Json {
case dynamic.classify(value) {
\"String\" ->
case decode.run(value, decode.string) {
Ok(s) -> json.string(s)
Error(_) -> json.null()
}
\"Int\" ->
case decode.run(value, decode.int) {
Ok(i) -> json.int(i)
Error(_) -> json.null()
}
\"Float\" ->
case decode.run(value, decode.float) {
Ok(f) -> json.float(f)
Error(_) -> json.null()
}
\"Bool\" ->
case decode.run(value, decode.bool) {
Ok(b) -> json.bool(b)
Error(_) -> json.null()
}
\"Nil\" -> json.null()
_ -> json.null()
}
}
"/utf8>>
);
false ->
Sb@5
end,
oaspec@internal@util@string_extra:to_string(Sb@6).
-file("src/oaspec/internal/codegen/encoders.gleam", 36).
?DOC(false).
-spec generate(oaspec@internal@codegen@context:context()) -> list(oaspec@internal@codegen@context:generated_file()).
generate(Ctx) ->
Operations = oaspec@internal@codegen@context:operations(Ctx),
Content = generate_encoders(Ctx, Operations),
[{generated_file,
<<"encode.gleam"/utf8>>,
Content,
shared_target,
overwrite}].