Current section
Files
Jump to
Current section
Files
src/protozoa@internal@codegen@types.erl
-module(protozoa@internal@codegen@types).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/protozoa/internal/codegen/types.gleam").
-export([flatten_type_name/1, capitalize_first/1, generate_enum_type/1, generate_enum_types/1, escape_keyword/1, generate_message_types_with_registry_tracked/4, generate_types_with_registry/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(false).
-file("src/protozoa/internal/codegen/types.gleam", 214).
?DOC(false).
-spec has_deprecated_option(list(protozoa@parser:field_option())) -> boolean().
has_deprecated_option(Options) ->
gleam@list:any(Options, fun(Option) -> case Option of
{deprecated, true} ->
true;
_ ->
false
end end).
-file("src/protozoa/internal/codegen/types.gleam", 338).
?DOC(false).
-spec is_nested_type_in_message(binary(), protozoa@parser:message()) -> boolean().
is_nested_type_in_message(Type_name, Parent_message) ->
_pipe = erlang:element(5, Parent_message),
gleam@list:any(
_pipe,
fun(Nested) -> erlang:element(2, Nested) =:= Type_name end
).
-file("src/protozoa/internal/codegen/types.gleam", 343).
?DOC(false).
-spec is_nested_enum_in_message(binary(), protozoa@parser:message()) -> boolean().
is_nested_enum_in_message(Enum_name, Parent_message) ->
_pipe = erlang:element(6, Parent_message),
gleam@list:any(
_pipe,
fun(Nested_enum) -> erlang:element(2, Nested_enum) =:= Enum_name end
).
-file("src/protozoa/internal/codegen/types.gleam", 316).
?DOC(false).
-spec qualify_nested_field_type(
protozoa@parser:proto_type(),
binary(),
protozoa@parser:message()
) -> protozoa@parser:proto_type().
qualify_nested_field_type(Proto_type, Parent_name, Parent_message) ->
case Proto_type of
{message_type, Name} ->
case is_nested_type_in_message(Name, Parent_message) of
true ->
{message_type, <<Parent_name/binary, Name/binary>>};
false ->
Proto_type
end;
{enum_type, Name@1} ->
case is_nested_enum_in_message(Name@1, Parent_message) of
true ->
{enum_type, <<Parent_name/binary, Name@1/binary>>};
false ->
Proto_type
end;
_ ->
Proto_type
end.
-file("src/protozoa/internal/codegen/types.gleam", 223).
?DOC(false).
-spec flatten_nested_message(
protozoa@parser:message(),
protozoa@parser:message()
) -> protozoa@parser:message().
flatten_nested_message(Nested_msg, Parent) ->
Fixed_fields = begin
_pipe = erlang:element(3, Nested_msg),
gleam@list:map(
_pipe,
fun(Field) ->
Updated_field_type = qualify_nested_field_type(
erlang:element(3, Field),
erlang:element(2, Parent),
Parent
),
{field,
erlang:element(2, Field),
Updated_field_type,
erlang:element(4, Field),
erlang:element(5, Field),
erlang:element(6, Field)}
end
)
end,
{message,
<<(erlang:element(2, Parent))/binary,
(erlang:element(2, Nested_msg))/binary>>,
Fixed_fields,
erlang:element(4, Nested_msg),
erlang:element(5, Nested_msg),
erlang:element(6, Nested_msg)}.
-file("src/protozoa/internal/codegen/types.gleam", 394).
?DOC(false).
-spec is_well_known_source(binary()) -> boolean().
is_well_known_source(Source_file) ->
gleam_stdlib:string_starts_with(Source_file, <<"google/protobuf/"/utf8>>).
-file("src/protozoa/internal/codegen/types.gleam", 418).
?DOC(false).
-spec flatten_type_name(binary()) -> binary().
flatten_type_name(Name) ->
case Name of
<<"google.protobuf.Timestamp"/utf8>> ->
<<"Timestamp"/utf8>>;
<<"google.protobuf.Duration"/utf8>> ->
<<"Duration"/utf8>>;
<<"google.protobuf.FieldMask"/utf8>> ->
<<"FieldMask"/utf8>>;
<<"google.protobuf.Empty"/utf8>> ->
<<"Empty"/utf8>>;
<<"google.protobuf.Any"/utf8>> ->
<<"Any"/utf8>>;
<<"google.protobuf.Struct"/utf8>> ->
<<"Struct"/utf8>>;
<<"google.protobuf.Value"/utf8>> ->
<<"Value"/utf8>>;
<<"google.protobuf.ListValue"/utf8>> ->
<<"ListValue"/utf8>>;
<<"google.protobuf.NullValue"/utf8>> ->
<<"NullValue"/utf8>>;
<<"google.protobuf.DoubleValue"/utf8>> ->
<<"DoubleValue"/utf8>>;
<<"google.protobuf.FloatValue"/utf8>> ->
<<"FloatValue"/utf8>>;
<<"google.protobuf.Int64Value"/utf8>> ->
<<"Int64Value"/utf8>>;
<<"google.protobuf.UInt64Value"/utf8>> ->
<<"UInt64Value"/utf8>>;
<<"google.protobuf.Int32Value"/utf8>> ->
<<"Int32Value"/utf8>>;
<<"google.protobuf.UInt32Value"/utf8>> ->
<<"UInt32Value"/utf8>>;
<<"google.protobuf.BoolValue"/utf8>> ->
<<"BoolValue"/utf8>>;
<<"google.protobuf.StringValue"/utf8>> ->
<<"StringValue"/utf8>>;
<<"google.protobuf.BytesValue"/utf8>> ->
<<"BytesValue"/utf8>>;
_ ->
_pipe = Name,
gleam@string:replace(_pipe, <<"."/utf8>>, <<""/utf8>>)
end.
-file("src/protozoa/internal/codegen/types.gleam", 398).
?DOC(false).
-spec qualify_cross_file_type(binary(), binary()) -> binary().
qualify_cross_file_type(Type_name, Source_file) ->
Module_name = case gleam@string:split(Source_file, <<"/"/utf8>>) of
[] ->
<<"unknown"/utf8>>;
Parts ->
case gleam@list:last(Parts) of
{ok, Filename} ->
case gleam@string:split(Filename, <<"."/utf8>>) of
[Name | _] ->
Name;
[] ->
<<"unknown"/utf8>>
end;
{error, _} ->
<<"unknown"/utf8>>
end
end,
<<<<Module_name/binary, "."/utf8>>/binary,
(flatten_type_name(Type_name))/binary>>.
-file("src/protozoa/internal/codegen/types.gleam", 348).
?DOC(false).
-spec resolve_external_type_simple(
binary(),
protozoa@internal@type_registry:type_registry(),
binary()
) -> binary().
resolve_external_type_simple(Name, Registry, File_path) ->
Current_package = case protozoa@internal@type_registry:get_file_package(
Registry,
File_path
) of
{some, Pkg} ->
Pkg;
none ->
<<""/utf8>>
end,
case protozoa@internal@type_registry:resolve_type_reference(
Registry,
Name,
Current_package
) of
{ok, Resolved_fqn} ->
case protozoa@internal@type_registry:get_type_source(
Registry,
Resolved_fqn
) of
{some, Source_file} ->
case is_well_known_source(Source_file) of
true ->
flatten_type_name(Resolved_fqn);
false ->
case Source_file =:= File_path of
true ->
flatten_type_name(Name);
false ->
qualify_cross_file_type(Name, Source_file)
end
end;
none ->
flatten_type_name(Name)
end;
{error, _} ->
case Name =:= <<"OtherMessage"/utf8>> of
true ->
<<"other."/utf8, (flatten_type_name(Name))/binary>>;
false ->
flatten_type_name(Name)
end
end.
-file("src/protozoa/internal/codegen/types.gleam", 278).
?DOC(false).
-spec resolve_field_type_simple(
protozoa@parser:proto_type(),
protozoa@internal@type_registry:type_registry(),
binary()
) -> binary().
resolve_field_type_simple(Proto_type, Registry, File_path) ->
case Proto_type of
string ->
<<"String"/utf8>>;
int32 ->
<<"Int"/utf8>>;
int64 ->
<<"Int"/utf8>>;
u_int32 ->
<<"Int"/utf8>>;
u_int64 ->
<<"Int"/utf8>>;
s_int32 ->
<<"Int"/utf8>>;
s_int64 ->
<<"Int"/utf8>>;
fixed32 ->
<<"Int"/utf8>>;
fixed64 ->
<<"Int"/utf8>>;
s_fixed32 ->
<<"Int"/utf8>>;
s_fixed64 ->
<<"Int"/utf8>>;
bool ->
<<"Bool"/utf8>>;
bytes ->
<<"BitArray"/utf8>>;
double ->
<<"Float"/utf8>>;
float ->
<<"Float"/utf8>>;
{message_type, Name} ->
resolve_external_type_simple(Name, Registry, File_path);
{enum_type, Name@1} ->
resolve_external_type_simple(Name@1, Registry, File_path);
{repeated, Inner} ->
<<<<"List("/utf8,
(resolve_field_type_simple(Inner, Registry, File_path))/binary>>/binary,
")"/utf8>>;
{optional, Inner@1} ->
<<<<"Option("/utf8,
(resolve_field_type_simple(Inner@1, Registry, File_path))/binary>>/binary,
")"/utf8>>;
{map, Key, Value} ->
<<<<<<<<"List(#("/utf8,
(resolve_field_type_simple(Key, Registry, File_path))/binary>>/binary,
", "/utf8>>/binary,
(resolve_field_type_simple(Value, Registry, File_path))/binary>>/binary,
"))"/utf8>>
end.
-file("src/protozoa/internal/codegen/types.gleam", 263).
?DOC(false).
-spec resolve_field_type(
protozoa@parser:field(),
protozoa@internal@type_registry:type_registry(),
binary(),
protozoa@parser:message()
) -> binary().
resolve_field_type(Field, Registry, File_path, _) ->
case erlang:element(3, Field) of
{repeated, Inner} ->
<<<<"List("/utf8,
(resolve_field_type_simple(Inner, Registry, File_path))/binary>>/binary,
")"/utf8>>;
{optional, Inner@1} ->
<<<<"Option("/utf8,
(resolve_field_type_simple(Inner@1, Registry, File_path))/binary>>/binary,
")"/utf8>>;
_ ->
resolve_field_type_simple(
erlang:element(3, Field),
Registry,
File_path
)
end.
-file("src/protozoa/internal/codegen/types.gleam", 447).
?DOC(false).
-spec capitalize_first(binary()) -> binary().
capitalize_first(Str) ->
_pipe = Str,
_pipe@1 = gleam@string:split(_pipe, <<"_"/utf8>>),
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Part) -> case gleam_stdlib:string_pop_grapheme(Part) of
{ok, {First, Rest}} ->
<<(string:uppercase(First))/binary, Rest/binary>>;
{error, _} ->
Part
end end
),
gleam@string:join(_pipe@2, <<""/utf8>>).
-file("src/protozoa/internal/codegen/types.gleam", 129).
?DOC(false).
-spec generate_enum_type(protozoa@parser:enum()) -> binary().
generate_enum_type(Enum) ->
Variants = begin
_pipe = erlang:element(3, Enum),
_pipe@1 = gleam@list:map(
_pipe,
fun(Variant) ->
<<" "/utf8,
(capitalize_first(erlang:element(2, Variant)))/binary>>
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
<<<<<<<<"pub type "/utf8, (erlang:element(2, Enum))/binary>>/binary,
" {\n"/utf8>>/binary,
Variants/binary>>/binary,
"\n}"/utf8>>.
-file("src/protozoa/internal/codegen/types.gleam", 122).
?DOC(false).
-spec generate_enum_types(list(protozoa@parser:enum())) -> binary().
generate_enum_types(Enums) ->
_pipe = Enums,
_pipe@1 = gleam@list:map(_pipe, fun generate_enum_type/1),
gleam@string:join(_pipe@1, <<"\n\n"/utf8>>).
-file("src/protozoa/internal/codegen/types.gleam", 183).
?DOC(false).
-spec generate_oneof_type(
binary(),
protozoa@parser:oneof(),
protozoa@internal@type_registry:type_registry(),
binary()
) -> binary().
generate_oneof_type(Message_name, Oneof, Registry, File_path) ->
Type_name = <<(capitalize_first(Message_name))/binary,
(capitalize_first(erlang:element(2, Oneof)))/binary>>,
Variants = begin
_pipe = erlang:element(3, Oneof),
_pipe@1 = gleam@list:map(
_pipe,
fun(Field) ->
Base_variant_name = capitalize_first(erlang:element(2, Field)),
Gleam_type = resolve_field_type_simple(
erlang:element(3, Field),
Registry,
File_path
),
Variant_name = case {Base_variant_name, Gleam_type} of
{<<"Empty"/utf8>>, <<"Empty"/utf8>>} ->
<<"EmptyData"/utf8>>;
{<<"StringValue"/utf8>>, <<"String"/utf8>>} ->
<<"StringValueVariant"/utf8>>;
{<<"BoolValue"/utf8>>, <<"Bool"/utf8>>} ->
<<"BoolValueVariant"/utf8>>;
{<<"ListValue"/utf8>>, <<"ListValue"/utf8>>} ->
<<"ListValueVariant"/utf8>>;
{Name, _} ->
Name
end,
<<<<<<<<" "/utf8, Variant_name/binary>>/binary, "("/utf8>>/binary,
Gleam_type/binary>>/binary,
")"/utf8>>
end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
<<<<<<<<"pub type "/utf8, Type_name/binary>>/binary, " {\n"/utf8>>/binary,
Variants/binary>>/binary,
"\n}"/utf8>>.
-file("src/protozoa/internal/codegen/types.gleam", 241).
?DOC(false).
-spec generate_nested_enum_types(
protozoa@parser:message(),
gleam@set:set(binary())
) -> {list(binary()), gleam@set:set(binary())}.
generate_nested_enum_types(Message, Seen_enums) ->
_pipe = erlang:element(6, Message),
gleam@list:fold(
_pipe,
{[], Seen_enums},
fun(Acc, Nested_enum) ->
{Existing_enum_types, Current_enums} = Acc,
Flattened_name = <<(erlang:element(2, Message))/binary,
(erlang:element(2, Nested_enum))/binary>>,
case gleam@set:contains(Current_enums, Flattened_name) of
true ->
Acc;
false ->
Flattened_enum = {enum,
Flattened_name,
erlang:element(3, Nested_enum)},
Enum_code = generate_enum_type(Flattened_enum),
Updated_enums = gleam@set:insert(
Current_enums,
Flattened_name
),
{lists:append(Existing_enum_types, [Enum_code]),
Updated_enums}
end
end
).
-file("src/protozoa/internal/codegen/types.gleam", 45).
?DOC(false).
-spec escape_keyword(binary()) -> binary().
escape_keyword(Name) ->
case gleam@list:contains(
[<<"case"/utf8>>,
<<"const"/utf8>>,
<<"fn"/utf8>>,
<<"if"/utf8>>,
<<"import"/utf8>>,
<<"let"/utf8>>,
<<"opaque"/utf8>>,
<<"pub"/utf8>>,
<<"todo"/utf8>>,
<<"type"/utf8>>,
<<"use"/utf8>>,
<<"assert"/utf8>>,
<<"try"/utf8>>,
<<"panic"/utf8>>,
<<"auto"/utf8>>,
<<"delegate"/utf8>>,
<<"derive"/utf8>>,
<<"echo"/utf8>>,
<<"else"/utf8>>,
<<"external"/utf8>>,
<<"macro"/utf8>>,
<<"module"/utf8>>,
<<"test"/utf8>>,
<<"as"/utf8>>,
<<"when"/utf8>>],
Name
) of
true ->
<<Name/binary, "_"/utf8>>;
false ->
Name
end.
-file("src/protozoa/internal/codegen/types.gleam", 139).
?DOC(false).
-spec generate_message_type(
protozoa@parser:message(),
protozoa@internal@type_registry:type_registry(),
binary()
) -> binary().
generate_message_type(Message, Registry, File_path) ->
Fields = begin
_pipe = erlang:element(3, Message),
gleam@list:map(
_pipe,
fun(Field) ->
Gleam_type = resolve_field_type(
Field,
Registry,
File_path,
Message
),
Escaped_name = escape_keyword(erlang:element(2, Field)),
Deprecation_comment = case has_deprecated_option(
erlang:element(6, Field)
) of
true ->
<<" // @deprecated"/utf8>>;
false ->
<<""/utf8>>
end,
<<<<<<<<" "/utf8, Escaped_name/binary>>/binary, ": "/utf8>>/binary,
Gleam_type/binary>>/binary,
Deprecation_comment/binary>>
end
)
end,
Oneofs = begin
_pipe@1 = erlang:element(4, Message),
gleam@list:map(
_pipe@1,
fun(Oneof) ->
Oneof_type_name = <<(capitalize_first(
erlang:element(2, Message)
))/binary,
(capitalize_first(erlang:element(2, Oneof)))/binary>>,
Escaped_name@1 = escape_keyword(erlang:element(2, Oneof)),
<<<<<<<<" "/utf8, Escaped_name@1/binary>>/binary,
": option.Option("/utf8>>/binary,
Oneof_type_name/binary>>/binary,
")"/utf8>>
end
)
end,
All_fields = lists:append(Fields, Oneofs),
case All_fields of
[] ->
<<<<<<<<"pub type "/utf8, (erlang:element(2, Message))/binary>>/binary,
" {\n "/utf8>>/binary,
(erlang:element(2, Message))/binary>>/binary,
"\n}"/utf8>>;
_ ->
Fields_str = gleam@string:join(All_fields, <<",\n"/utf8>>),
<<<<<<<<<<<<"pub type "/utf8, (erlang:element(2, Message))/binary>>/binary,
" {\n "/utf8>>/binary,
(erlang:element(2, Message))/binary>>/binary,
"(\n"/utf8>>/binary,
Fields_str/binary>>/binary,
",\n )\n}"/utf8>>
end.
-file("src/protozoa/internal/codegen/types.gleam", 78).
?DOC(false).
-spec generate_message_types_with_registry_tracked(
protozoa@parser:message(),
protozoa@internal@type_registry:type_registry(),
binary(),
gleam@set:set(binary())
) -> {list(binary()), gleam@set:set(binary())}.
generate_message_types_with_registry_tracked(
Message,
Registry,
File_path,
Seen_enums
) ->
{Nested_types, Enums_after_nested} = begin
_pipe = erlang:element(5, Message),
gleam@list:fold(
_pipe,
{[], Seen_enums},
fun(Acc, Nested_msg) ->
{Existing_nested, Current_enums} = Acc,
Flattened_msg = flatten_nested_message(Nested_msg, Message),
{New_nested_types, Updated_enums} = generate_message_types_with_registry_tracked(
Flattened_msg,
Registry,
File_path,
Current_enums
),
{lists:append(Existing_nested, New_nested_types), Updated_enums}
end
)
end,
{Nested_enum_types, Enums_after_enum_gen} = generate_nested_enum_types(
Message,
Enums_after_nested
),
Oneof_types = begin
_pipe@1 = erlang:element(4, Message),
gleam@list:map(
_pipe@1,
fun(Oneof) ->
generate_oneof_type(
erlang:element(2, Message),
Oneof,
Registry,
File_path
)
end
)
end,
Main_type = generate_message_type(Message, Registry, File_path),
All_types = lists:append(
[Nested_types, Nested_enum_types, Oneof_types, [Main_type]]
),
{All_types, Enums_after_enum_gen}.
-file("src/protozoa/internal/codegen/types.gleam", 53).
?DOC(false).
-spec generate_types_with_registry(
list(protozoa@parser:message()),
protozoa@internal@type_registry:type_registry(),
binary()
) -> binary().
generate_types_with_registry(Messages, Registry, File_path) ->
Generated_enum_names = gleam@set:new(),
{All_types, _} = begin
_pipe = Messages,
gleam@list:fold(
_pipe,
{[], Generated_enum_names},
fun(Acc, Msg) ->
{Existing_types, Seen_enums} = Acc,
{New_types, Updated_enums} = generate_message_types_with_registry_tracked(
Msg,
Registry,
File_path,
Seen_enums
),
{lists:append(Existing_types, New_types), Updated_enums}
end
)
end,
_pipe@1 = All_types,
gleam@string:join(_pipe@1, <<"\n\n"/utf8>>).