Current section

Files

Jump to
glanoid src glanoid.erl
Raw

src/glanoid.erl

-module(glanoid).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([make_generator/1]).
-spec fix4(fun((fun((FNB, FNC, FND, FNE) -> FNK), FNB, FNC, FND, FNE) -> FNK)) -> fun((FNB, FNC, FND, FNE) -> FNK).
fix4(F) ->
fun(A, B, C, D) -> F(fix4(F), A, B, C, D) end.
-spec do_bit_size(integer(), integer()) -> integer().
do_bit_size(N, Acc) ->
case N of
0 ->
Acc;
_ ->
do_bit_size(erlang:'bsr'(N, 1), Acc + 1)
end.
-spec bit_size(integer()) -> integer().
bit_size(N) ->
do_bit_size(N, 0).
-spec make_generator(binary()) -> {ok, fun((integer()) -> binary())} |
{error, nil}.
make_generator(Alphabet) ->
gleam@bool:guard(
gleam@string:length(Alphabet) =:= 0,
{error, nil},
fun() ->
Bit_mask = begin
_pipe = Alphabet,
_pipe@1 = gleam@string:length(_pipe),
_pipe@2 = gleam@int:subtract(_pipe@1, 1),
_pipe@3 = bit_size(_pipe@2),
_pipe@4 = erlang:'bsl'(2, _pipe@3),
gleam@int:subtract(_pipe@4, 1)
end,
To_alphabet@1 = fix4(
fun(To_alphabet, Bits, Size, Alphabet@1, Acc) ->
case {gleam@string:length(Acc) =:= Size, Bits} of
{true, _} ->
Acc;
{false, <<X:8, Rest/bitstring>>} ->
Index = erlang:'band'(X, Bit_mask),
Letter = gleam@string:slice(Alphabet@1, Index, 1),
case Letter of
<<""/utf8>> ->
To_alphabet(Rest, Size, Alphabet@1, Acc);
_ ->
To_alphabet(
Rest,
Size,
Alphabet@1,
<<Acc/binary, Letter/binary>>
)
end;
{false, <<>>} ->
To_alphabet(
crypto:strong_rand_bytes(Size * 2),
Size,
Alphabet@1,
Acc
);
{_, _} ->
erlang:error(#{gleam_error => panic,
message => <<"panic expression evaluated"/utf8>>,
module => <<"glanoid"/utf8>>,
function => <<"make_generator"/utf8>>,
line => 48})
end
end
),
{ok, fun(Size@1) -> _pipe@5 = crypto:strong_rand_bytes(Size@1 * 2),
To_alphabet@1(_pipe@5, Size@1, Alphabet, <<""/utf8>>) end}
end
).