Current section

Files

Jump to
ids src ids@nanoid.erl
Raw

src/ids@nanoid.erl

-module(ids@nanoid).
-compile([no_auto_import, nowarn_unused_vars]).
-export([generate/0]).
-spec check_size(integer()) -> {ok, boolean()} | {error, binary()}.
check_size(Size) ->
case Size > 0 of
true ->
_pipe = true,
{ok, _pipe};
false ->
Error = <<"Error: The specified ID size is too small. Increase the size of the ID."/utf8>>,
_pipe@1 = Error,
{error, _pipe@1}
end.
-spec check_alphabet(bitstring()) -> {ok, boolean()} | {error, binary()}.
check_alphabet(Alphabet) ->
case gleam@bit_string:byte_size(Alphabet) > 1 of
true ->
_pipe = true,
{ok, _pipe};
false ->
Error = <<"Error: The specified alphabet size is too small. Increase the size of the alphabet."/utf8>>,
_pipe@1 = Error,
{error, _pipe@1}
end.
-spec check_nanoid_args(integer(), bitstring()) -> {ok, boolean()} |
{error, binary()}.
check_nanoid_args(Size, Alphabet) ->
case check_size(Size) of
{ok, true} ->
case check_alphabet(Alphabet) of
{ok, true} ->
_pipe = true,
{ok, _pipe};
{error, Error} ->
_pipe@1 = Error,
{error, _pipe@1}
end;
{error, Error@1} ->
_pipe@2 = Error@1,
{error, _pipe@2}
end.
-spec random_bytes(integer()) -> list(integer()).
random_bytes(Size) ->
_pipe = crypto:strong_rand_bytes(Size),
binary:bin_to_list(_pipe).
-spec generate_nanoid(integer(), bitstring(), integer()) -> {ok, bitstring()} |
{error, binary()}.
generate_nanoid(Size, Alphabet, Mask) ->
case check_nanoid_args(Size, Alphabet) of
{ok, true} ->
_pipe = Size,
_pipe@1 = random_bytes(_pipe),
_pipe@2 = gleam@list:map(
_pipe@1,
fun(X) ->
case gleam@bit_string:slice(
Alphabet,
erlang:'band'(X, Mask),
1
) of
{ok, Nanoid} ->
Nanoid;
_ ->
<<""/utf8>>
end
end
),
_pipe@3 = gleam@bit_string:concat(_pipe@2),
{ok, _pipe@3};
{error, Error} ->
_pipe@4 = Error,
{error, _pipe@4}
end.
-spec do_generate(integer(), bitstring(), integer(), integer(), bitstring()) -> {ok,
bitstring()} |
{error, binary()}.
do_generate(Size, Alphabet, Mask, Step, Acc) ->
case gleam@bit_string:byte_size(Acc) >= Size of
true ->
_assert_subject = gleam@bit_string:slice(Acc, 0, Size),
{ok, Nanoid} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"ids/nanoid"/utf8>>,
function => <<"do_generate"/utf8>>,
line => 82})
end,
_pipe = Nanoid,
{ok, _pipe};
false ->
case generate_nanoid(Step, Alphabet, Mask) of
{ok, Partial_nanoid} ->
_pipe@1 = gleam@bit_string:concat([Acc, Partial_nanoid]),
do_generate(Size, Alphabet, Mask, Step, _pipe@1);
{error, Error} ->
_pipe@2 = Error,
{error, _pipe@2}
end
end.
-spec calculate_mask(integer()) -> integer().
calculate_mask(Alphabet_length) ->
V1 = case math:log(2.0) of
0.0 -> 0.0;
Gleam@denominator -> math:log(gleam@int:to_float(Alphabet_length - 1)) / Gleam@denominator
end,
V2 = gleam@float:round(gleam@float:floor(V1)),
erlang:'bsl'(2, V2) - 1.
-spec calculate_step(integer(), integer(), integer()) -> integer().
calculate_step(Mask, Size, Alphabet_length) ->
Step = gleam@float:ceiling(case gleam@int:to_float(Alphabet_length) of
0.0 -> 0.0;
Gleam@denominator -> ((1.6 * gleam@int:to_float(Mask)) * gleam@int:to_float(
Size
))
/ Gleam@denominator
end),
gleam@float:round(Step).
-spec generate() -> binary().
generate() ->
Alphabet = <<"_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"/utf8>>,
_assert_subject = gleam@bit_string:to_string(Alphabet),
{ok, Alphabet_string} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"ids/nanoid"/utf8>>,
function => <<"generate"/utf8>>,
line => 50})
end,
Alphabet_length = gleam@string:length(Alphabet_string),
Size = 21,
_assert_subject@1 = check_nanoid_args(Size, Alphabet),
{ok, true} = case _assert_subject@1 of
{ok, true} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"ids/nanoid"/utf8>>,
function => <<"generate"/utf8>>,
line => 56})
end,
Mask = calculate_mask(Alphabet_length),
Step = calculate_step(Mask, Size, Alphabet_length),
_assert_subject@2 = do_generate(Size, Alphabet, Mask, Step, <<""/utf8>>),
{ok, Bitstr_nanoid} = case _assert_subject@2 of
{ok, _} -> _assert_subject@2;
_assert_fail@2 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@2,
module => <<"ids/nanoid"/utf8>>,
function => <<"generate"/utf8>>,
line => 62})
end,
_assert_subject@3 = gleam@bit_string:to_string(Bitstr_nanoid),
{ok, Str_nanoid} = case _assert_subject@3 of
{ok, _} -> _assert_subject@3;
_assert_fail@3 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@3,
module => <<"ids/nanoid"/utf8>>,
function => <<"generate"/utf8>>,
line => 65})
end,
Str_nanoid.