Packages

A Protocol Buffers library for Gleam, providing encoding and decoding of protobuf messages.

Current section

Files

Jump to
protozoa src protozoa@internal@import_resolver.erl
Raw

src/protozoa@internal@import_resolver.erl

-module(protozoa@internal@import_resolver).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/protozoa/internal/import_resolver.gleam").
-export([describe_error/1, new/0, with_search_paths/2, resolve_imports/2, get_type_registry/1, get_all_loaded_files/1, get_public_imports/2]).
-export_type([import_resolver/0, error/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-type import_resolver() :: {import_resolver,
list(binary()),
gleam@dict:dict(binary(), protozoa@parser:proto_file()),
gleam@dict:dict(binary(), list(binary())),
protozoa@internal@type_registry:type_registry(),
gleam@dict:dict(binary(), list(binary()))}.
-type error() :: {file_not_found, binary()} |
{circular_dependency, binary()} |
{read_error, binary(), binary()} |
{parse_error, binary(), binary()} |
{well_known_type_not_found, binary()}.
-file("src/protozoa/internal/import_resolver.gleam", 28).
?DOC(false).
-spec describe_error(error()) -> binary().
describe_error(Error) ->
case Error of
{file_not_found, Path} ->
<<"File not found: "/utf8, Path/binary>>;
{circular_dependency, Path@1} ->
<<"Circular dependency detected at: "/utf8, Path@1/binary>>;
{read_error, Path@2, Reason} ->
<<<<<<"Failed to read file "/utf8, Path@2/binary>>/binary,
": "/utf8>>/binary,
Reason/binary>>;
{parse_error, Path@3, Reason@1} ->
<<<<<<"Failed to parse file "/utf8, Path@3/binary>>/binary,
": "/utf8>>/binary,
Reason@1/binary>>;
{well_known_type_not_found, Path@4} ->
<<"Well-known type not found: "/utf8, Path@4/binary>>
end.
-file("src/protozoa/internal/import_resolver.gleam", 39).
?DOC(false).
-spec new() -> import_resolver().
new() ->
{import_resolver,
[<<"."/utf8>>],
maps:new(),
maps:new(),
protozoa@internal@type_registry:new(),
maps:new()}.
-file("src/protozoa/internal/import_resolver.gleam", 49).
?DOC(false).
-spec with_search_paths(import_resolver(), list(binary())) -> import_resolver().
with_search_paths(Resolver, Paths) ->
{import_resolver,
Paths,
erlang:element(3, Resolver),
erlang:element(4, Resolver),
erlang:element(5, Resolver),
erlang:element(6, Resolver)}.
-file("src/protozoa/internal/import_resolver.gleam", 56).
?DOC(false).
-spec find_file(binary(), list(binary())) -> {ok, binary()} | {error, error()}.
find_file(Path, Search_paths) ->
case Search_paths of
[] ->
{error, {file_not_found, Path}};
[Search_path | Rest] ->
Full_path = case Search_path of
<<"."/utf8>> ->
Path;
_ ->
<<<<Search_path/binary, "/"/utf8>>/binary, Path/binary>>
end,
case simplifile_erl:is_file(Full_path) of
{ok, true} ->
{ok, Full_path};
_ ->
find_file(Path, Rest)
end
end.
-file("src/protozoa/internal/import_resolver.gleam", 72).
?DOC(false).
-spec detect_circular_dependency(
binary(),
gleam@set:set(binary()),
gleam@dict:dict(binary(), list(binary()))
) -> {ok, nil} | {error, error()}.
detect_circular_dependency(Path, Visiting, Graph) ->
case gleam@set:contains(Visiting, Path) of
true ->
{error, {circular_dependency, Path}};
false ->
New_visiting = gleam@set:insert(Visiting, Path),
case gleam_stdlib:map_get(Graph, Path) of
{ok, Deps} ->
gleam@list:try_each(
Deps,
fun(Dep) ->
detect_circular_dependency(Dep, New_visiting, Graph)
end
);
{error, _} ->
{ok, nil}
end
end.
-file("src/protozoa/internal/import_resolver.gleam", 93).
?DOC(false).
-spec resolve_imports(import_resolver(), binary()) -> {ok,
{protozoa@parser:proto_file(), import_resolver()}} |
{error, error()}.
resolve_imports(Resolver, File_path) ->
case gleam_stdlib:map_get(erlang:element(3, Resolver), File_path) of
{ok, Proto_file} ->
{ok, {Proto_file, Resolver}};
{error, _} ->
Proto_file@1 = case protozoa@internal@well_known_types:is_well_known_import(
File_path
) of
true ->
case gleam_stdlib:map_get(
protozoa@internal@well_known_types:get_well_known_proto_files(
),
File_path
) of
{ok, Wkt} ->
{ok, Wkt};
{error, _} ->
{error, {well_known_type_not_found, File_path}}
end;
false ->
gleam@result:'try'(
find_file(File_path, erlang:element(2, Resolver)),
fun(Full_path) ->
gleam@result:'try'(
begin
_pipe = simplifile:read(Full_path),
gleam@result:map_error(
_pipe,
fun(Reason) ->
{read_error,
File_path,
simplifile:describe_error(
Reason
)}
end
)
end,
fun(Content) ->
_pipe@1 = protozoa@parser:parse(Content),
gleam@result:map_error(
_pipe@1,
fun(Parse_error) ->
{parse_error,
File_path,
protozoa@parser:describe_parse_error(
Parse_error
)}
end
)
end
)
end
)
end,
gleam@result:'try'(
Proto_file@1,
fun(Proto_file@2) ->
Import_paths = gleam@list:map(
erlang:element(4, Proto_file@2),
fun(Imp) -> erlang:element(2, Imp) end
),
Public_import_paths = begin
_pipe@2 = erlang:element(4, Proto_file@2),
_pipe@3 = gleam@list:filter(
_pipe@2,
fun(Imp@1) -> erlang:element(3, Imp@1) end
),
gleam@list:map(
_pipe@3,
fun(Imp@2) -> erlang:element(2, Imp@2) end
)
end,
New_graph = gleam@dict:insert(
erlang:element(4, Resolver),
File_path,
Import_paths
),
gleam@result:'try'(
detect_circular_dependency(
File_path,
gleam@set:new(),
New_graph
),
fun(_) ->
Resolver_with_imports = {import_resolver,
erlang:element(2, Resolver),
gleam@dict:insert(
erlang:element(3, Resolver),
File_path,
Proto_file@2
),
New_graph,
erlang:element(5, Resolver),
gleam@dict:insert(
erlang:element(6, Resolver),
File_path,
Public_import_paths
)},
gleam@result:'try'(
gleam@list:try_fold(
erlang:element(4, Proto_file@2),
Resolver_with_imports,
fun(Res, Imp@3) ->
gleam@result:'try'(
resolve_imports(
Res,
erlang:element(2, Imp@3)
),
fun(_use0) ->
{_, Updated_res} = _use0,
{ok, Updated_res}
end
)
end
),
fun(Resolver_after_imports) ->
gleam@result:'try'(
begin
_pipe@4 = protozoa@internal@type_registry:add_file(
erlang:element(
5,
Resolver_after_imports
),
File_path,
Proto_file@2
),
gleam@result:map_error(
_pipe@4,
fun(Error) ->
{read_error,
File_path,
protozoa@internal@type_registry:describe_error(
Error
)}
end
)
end,
fun(Updated_registry) ->
Final_resolver = {import_resolver,
erlang:element(
2,
Resolver_after_imports
),
erlang:element(
3,
Resolver_after_imports
),
erlang:element(
4,
Resolver_after_imports
),
Updated_registry,
erlang:element(
6,
Resolver_after_imports
)},
{ok, {Proto_file@2, Final_resolver}}
end
)
end
)
end
)
end
)
end.
-file("src/protozoa/internal/import_resolver.gleam", 197).
?DOC(false).
-spec get_type_registry(import_resolver()) -> protozoa@internal@type_registry:type_registry().
get_type_registry(Resolver) ->
erlang:element(5, Resolver).
-file("src/protozoa/internal/import_resolver.gleam", 201).
?DOC(false).
-spec get_all_loaded_files(import_resolver()) -> list({binary(),
protozoa@parser:proto_file()}).
get_all_loaded_files(Resolver) ->
maps:to_list(erlang:element(3, Resolver)).
-file("src/protozoa/internal/import_resolver.gleam", 215).
?DOC(false).
-spec get_transitive_public_imports(
binary(),
gleam@dict:dict(binary(), list(binary())),
gleam@set:set(binary())
) -> gleam@set:set(binary()).
get_transitive_public_imports(File_path, Public_imports, Visited) ->
case gleam@set:contains(Visited, File_path) of
true ->
Visited;
false ->
Visited_with_current = gleam@set:insert(Visited, File_path),
case gleam_stdlib:map_get(Public_imports, File_path) of
{ok, Imports} ->
gleam@list:fold(
Imports,
Visited_with_current,
fun(Acc, Import_path) ->
With_import = gleam@set:insert(Acc, Import_path),
get_transitive_public_imports(
Import_path,
Public_imports,
With_import
)
end
);
{error, _} ->
Visited_with_current
end
end.
-file("src/protozoa/internal/import_resolver.gleam", 207).
?DOC(false).
-spec get_public_imports(import_resolver(), binary()) -> list(binary()).
get_public_imports(Resolver, File_path) ->
_pipe = get_transitive_public_imports(
File_path,
erlang:element(6, Resolver),
gleam@set:new()
),
gleam@set:to_list(_pipe).