Packages
gleam_erlang
0.23.0
1.3.0
1.2.0
1.1.0
1.0.0
1.0.0-rc1
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.1
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.1
0.18.0
0.18.0-rc1
retired
0.17.1
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Types and functions for programs running on Erlang!
Current section
Files
Jump to
Current section
Files
src/gleam_erlang_ffi.erl
-module(gleam_erlang_ffi).
-export([
atom_from_dynamic/1, rescue/1, atom_from_string/1, get_line/1,
ensure_all_started/1, sleep/1, os_family/0, sleep_forever/0, read_file/1,
append_file/2, write_file/2, delete_file/1, get_all_env/0, get_env/1,
set_env/2, unset_env/1, delete_directory/1, recursive_delete/1,
list_directory/1, demonitor/1, make_directory/1, new_selector/0, link/1,
insert_selector_handler/3, select/1, select/2, trap_exits/1, map_selector/2,
merge_selector/2, flush_messages/0, file_info/1, link_info/1,
priv_directory/1, connect_node/1, register_process/2, unregister_process/1,
process_named/1, identity/1
]).
-define(is_posix_error(Error),
Error =:= eacces orelse Error =:= eagain orelse Error =:= ebadf orelse
Error =:= ebadmsg orelse Error =:= ebusy orelse Error =:= edeadlk orelse
Error =:= edeadlock orelse Error =:= edquot orelse Error =:= eexist orelse
Error =:= efault orelse Error =:= efbig orelse Error =:= eftype orelse
Error =:= eintr orelse Error =:= einval orelse Error =:= eio orelse
Error =:= eisdir orelse Error =:= eloop orelse Error =:= emfile orelse
Error =:= emlink orelse Error =:= emultihop orelse Error =:= enametoolong orelse
Error =:= enfile orelse Error =:= enobufs orelse Error =:= enodev orelse
Error =:= enolck orelse Error =:= enolink orelse Error =:= enoent orelse
Error =:= enomem orelse Error =:= enospc orelse Error =:= enosr orelse
Error =:= enostr orelse Error =:= enosys orelse Error =:= enotblk orelse
Error =:= enotdir orelse Error =:= enotsup orelse Error =:= enxio orelse
Error =:= eopnotsupp orelse Error =:= eoverflow orelse Error =:= eperm orelse
Error =:= epipe orelse Error =:= erange orelse Error =:= erofs orelse
Error =:= espipe orelse Error =:= esrch orelse Error =:= estale orelse
Error =:= etxtbsy orelse Error =:= exdev
).
-spec atom_from_string(binary()) -> {ok, atom()} | {error, atom_not_loaded}.
atom_from_string(S) ->
try {ok, binary_to_existing_atom(S)}
catch error:badarg -> {error, atom_not_loaded}
end.
atom_from_dynamic(Data) when is_atom(Data) ->
{ok, Data};
atom_from_dynamic(Data) ->
{error, [{decode_error, <<"Atom">>, gleam@dynamic:classify(Data), []}]}.
-spec get_line(io:prompt()) -> {ok, unicode:unicode_binary()} | {error, eof | no_data}.
get_line(Prompt) ->
case io:get_line(Prompt) of
eof -> {error, eof};
{error, _} -> {error, no_data};
Data when is_binary(Data) -> {ok, Data};
Data when is_list(Data) -> {ok, unicode:characters_to_binary(Data)}
end.
rescue(F) ->
try {ok, F()}
catch
throw:X -> {error, {thrown, X}};
error:X -> {error, {errored, X}};
exit:X -> {error, {exited, X}}
end.
ensure_all_started(Application) ->
case application:ensure_all_started(Application) of
{ok, _} = Ok -> Ok;
{error, {ProblemApp, {"no such file or directory", _}}} ->
{error, {unknown_application, ProblemApp}}
end.
sleep(Microseconds) ->
timer:sleep(Microseconds),
nil.
sleep_forever() ->
timer:sleep(infinity),
nil.
file_info_result(Result) ->
case Result of
{ok, {file_info, Size, Type, Access, Atime, Mtime, Ctime, Mode, Links, MajorDevice, MinorDevice, Inode, Uid, Gid}} when Access =:= none ->
{ok, {file_info, Size, Type, no_access, Atime, Mtime, Ctime, Mode, Links, MajorDevice, MinorDevice, Inode, Uid, Gid}};
{ok, _} ->
Result;
{error, Reason} when ?is_posix_error(Reason) ->
Result
end.
file_info(Filename) ->
file_info_result(file:read_file_info(Filename, [{time, posix}])).
link_info(Filename) ->
file_info_result(file:read_link_info(Filename, [{time, posix}])).
posix_result(Result) ->
case Result of
ok -> {ok, nil};
{ok, Value} -> {ok, Value};
{error, Reason} when ?is_posix_error(Reason) -> {error, Reason}
end.
read_file(Filename) ->
posix_result(file:read_file(Filename)).
write_file(Contents, Filename) ->
posix_result(file:write_file(Filename, Contents)).
append_file(Contents, Filename) ->
posix_result(file:write_file(Filename, Contents, [append])).
delete_file(Filename) ->
posix_result(file:delete(Filename)).
make_directory(Dir) ->
posix_result(file:make_dir(Dir)).
list_directory(Dir) ->
case file:list_dir(Dir) of
{ok, Filenames} ->
{ok, [list_to_binary(Filename) || Filename <- Filenames]};
{error, Reason} when ?is_posix_error(Reason) ->
{error, Reason}
end.
delete_directory(Dir) ->
posix_result(file:del_dir(Dir)).
recursive_delete(Dir) ->
posix_result(file:del_dir_r(Dir)).
get_all_env() ->
BinVars = lists:map(fun(VarString) ->
[VarName, VarVal] = string:split(VarString, "="),
{list_to_binary(VarName), list_to_binary(VarVal)}
end, os:getenv()),
maps:from_list(BinVars).
get_env(Name) ->
case os:getenv(binary_to_list(Name)) of
false -> {error, nil};
Value -> {ok, list_to_binary(Value)}
end.
set_env(Name, Value) ->
os:putenv(binary_to_list(Name), binary_to_list(Value)),
nil.
unset_env(Name) ->
os:unsetenv(binary_to_list(Name)),
nil.
os_family() ->
case os:type() of
{win32, nt} ->
windows_nt;
{unix, linux} ->
linux;
{unix, darwin} ->
darwin;
{unix, freebsd} ->
free_bsd;
{_, Other} ->
{other, atom_to_binary(Other, utf8)}
end.
new_selector() ->
{selector, #{}}.
map_selector({selector, Handlers}, Fn) ->
MappedHandlers = maps:map(fun(_Tag, Handler) ->
fun(Message) -> Fn(Handler(Message)) end
end, Handlers),
{selector, MappedHandlers}.
merge_selector({selector, HandlersA}, {selector, HandlersB}) ->
{selector, maps:merge(HandlersA, HandlersB)}.
insert_selector_handler({selector, Handlers}, Tag, Fn) ->
{selector, Handlers#{Tag => Fn}}.
select(Selector) ->
{ok, Message} = select(Selector, infinity),
Message.
select({selector, Handlers}, Timeout) ->
AnythingHandler = maps:get(anything, Handlers, undefined),
receive
% Monitored process down messages.
% This is special cased so we can selectively receive based on the
% reference as well as the record tag.
{'DOWN', Ref, process, Pid, Reason} when is_map_key(Ref, Handlers) ->
Fn = maps:get(Ref, Handlers),
{ok, Fn({process_down, Pid, Reason})};
Msg when is_map_key({element(1, Msg), tuple_size(Msg)}, Handlers) ->
Fn = maps:get({element(1, Msg), tuple_size(Msg)}, Handlers),
{ok, Fn(Msg)};
Msg when AnythingHandler =/= undefined ->
{ok, AnythingHandler(Msg)}
after Timeout ->
{error, nil}
end.
demonitor({_, Reference}) ->
erlang:demonitor(Reference, [flush]).
link(Pid) ->
try
erlang:link(Pid)
catch
error:_ -> false
end.
trap_exits(ShouldTrap) ->
erlang:process_flag(trap_exit, ShouldTrap),
nil.
flush_messages() ->
receive _Message -> flush_messages()
after 0 -> nil
end.
priv_directory(Name) ->
try erlang:binary_to_existing_atom(Name) of
Atom ->
case code:priv_dir(Atom) of
{error, _} -> {error, nil};
Path -> {ok, unicode:characters_to_binary(Path)}
end
catch
error:badarg -> {error, nil}
end.
connect_node(Node) ->
case net_kernel:connect_node(Node) of
true -> {ok, Node};
false -> {error, failed_to_connect};
ignored -> {error, local_node_is_not_alive}
end.
register_process(Pid, Name) ->
try
true = erlang:register(Name, Pid),
{ok, nil}
catch
error:badarg -> {error, nil}
end.
unregister_process(Name) ->
try
true = erlang:unregister(Name),
{ok, nil}
catch
error:badarg -> {error, nil}
end.
process_named(Name) ->
case erlang:whereis(Name) of
Pid when is_pid(Pid) -> {ok, Pid};
_ -> {error, nil}
end.
identity(X) ->
X.