Packages

Gleam implementation of Pika ID

Retired package: Deprecated

Current section

Files

Jump to
pika_id src pika_id.erl
Raw

src/pika_id.erl

-module(pika_id).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([pika_gen/2, pika_init/1, pika_custom_init/2, pika_deconstruct/2]).
-export_type([prefix/0, pika_option/0, pika_id_metadata/0, pika/0]).
-type prefix() :: {prefix, binary(), binary(), boolean()}.
-type pika_option() :: {with_epoch, integer()} | {with_node_id, integer()}.
-type pika_id_metadata() :: {pika_id_metadata,
binary(),
binary(),
binary(),
boolean(),
binary(),
binary(),
integer(),
integer(),
integer(),
integer(),
integer()}.
-type pika() :: {pika,
fun((binary()) -> {ok, binary()} | {error, binary()}),
fun((binary()) -> {ok, pika_id_metadata()} | {error, binary()})}.
-spec validate_settings(list(prefix()), list(pika_option())) -> {ok,
{pika_id@snowflake:snowflake_gen(), list(prefix())}} |
{error, binary()}.
validate_settings(Prefixes, Options) ->
gleam@result:'try'(case Prefixes of
[] ->
{error, <<"You must specify at least one prefix."/utf8>>};
Prefixes@1 ->
{ok, Prefixes@1}
end, fun(Prefixes@2) ->
gleam@result:'try'(
begin
_assert_subject = gleam@regex:from_string(
<<"^[0-9a-z]+$"/utf8>>
),
{ok, Reg} = 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 => <<"pika_id"/utf8>>,
function => <<"validate_settings"/utf8>>,
line => 74})
end,
Match = begin
_pipe = Prefixes@2,
gleam@list:find(
_pipe,
fun(Prefix) ->
not gleam@regex:check(
Reg,
erlang:element(2, Prefix)
)
end
)
end,
case Match of
{ok, Prefix@1} ->
{error,
<<<<"One of the prefixes is invalid (prefix '"/utf8,
(erlang:element(2, Prefix@1))/binary>>/binary,
"' must be Alphanumeric)"/utf8>>};
{error, _} ->
{ok, Prefixes@2}
end
end,
fun(Prefixes@3) ->
Snowflake_ctx = pika_id@snowflake:create_snowflake(),
Snowflake_ctx@2 = gleam@list:fold(
Options,
Snowflake_ctx,
fun(Snowflake_ctx@1, Option) -> case Option of
{with_epoch, Num} ->
_pipe@1 = Snowflake_ctx@1,
pika_id@snowflake:with_epoch(_pipe@1, Num);
{with_node_id, Num@1} ->
_pipe@2 = Snowflake_ctx@1,
pika_id@snowflake:with_node_id(
_pipe@2,
Num@1
)
end end
),
case begin
_pipe@3 = Snowflake_ctx@2,
pika_id@snowflake:start_snowflake(_pipe@3)
end of
{error, Err} ->
{error,
begin
_pipe@4 = Err,
gleam@string:inspect(_pipe@4)
end};
{ok, Snowflake_gen} ->
{ok, {Snowflake_gen, Prefixes@3}}
end
end
)
end).
-spec gen_tail(integer(), boolean()) -> binary().
gen_tail(Snowflake_id, Secure) ->
Snowflake_str = gleam@int:to_string(Snowflake_id),
case Secure of
false ->
_pipe = Snowflake_str,
_pipe@1 = gleam_stdlib:identity(_pipe),
gleam@bit_array:base64_encode(_pipe@1, false);
true ->
_pipe@4 = (<<<<<<"s_"/utf8,
(begin
_pipe@2 = crypto:strong_rand_bytes(16),
_pipe@3 = binary:encode_hex(_pipe@2),
gleam@string:lowercase(_pipe@3)
end)/binary>>/binary,
"_"/utf8>>/binary,
Snowflake_str/binary>>),
_pipe@5 = gleam_stdlib:identity(_pipe@4),
gleam@bit_array:base64_encode(_pipe@5, false)
end.
-spec gen(pika_id@snowflake:snowflake_gen(), list(prefix()), binary()) -> {ok,
binary()} |
{error, binary()}.
gen(Generator, Prefixes, Head) ->
case gleam@list:find(
Prefixes,
fun(Prefix) -> erlang:element(2, Prefix) =:= Head end
) of
{error, _} ->
{error, <<"Prefix is undefined"/utf8>>};
{ok, Prefix@1} ->
Snowflake_id = pika_id@snowflake:generate(Generator),
{ok,
<<<<Head/binary, "_"/utf8>>/binary,
(gen_tail(Snowflake_id, erlang:element(4, Prefix@1)))/binary>>}
end.
-spec pika_gen(pika(), binary()) -> {ok, binary()} | {error, binary()}.
pika_gen(Pika, Prefix) ->
(erlang:element(2, Pika))(Prefix).
-spec deconstruct(pika_id@snowflake:snowflake_gen(), list(prefix()), binary()) -> {ok,
pika_id_metadata()} |
{error, binary()}.
deconstruct(Generator, Prefixes, Id) ->
gleam@result:'try'(case gleam_stdlib:contains_string(Id, <<"_"/utf8>>) of
false ->
{error, <<"Invalid Pika ID"/utf8>>};
true ->
case gleam@string:split(Id, <<"_"/utf8>>) of
[] ->
{error, <<"Invalid Pika ID"/utf8>>};
[Head | Tail] ->
{ok, {Head, Tail}}
end
end, fun(_use0) ->
{Head@1, Tail@1} = _use0,
gleam@result:'try'(
case gleam@list:find(
Prefixes,
fun(Prefix) -> erlang:element(2, Prefix) =:= Head@1 end
) of
{error, _} ->
{error, <<"Prefix is undefined"/utf8>>};
{ok, Prefix@1} ->
{ok, Prefix@1}
end,
fun(Prefix@2) -> gleam@result:'try'(case Tail@1 of
[<<""/utf8>>] ->
{error, <<"Invalid Pika ID"/utf8>>};
[] ->
{error, <<"Invalid Pika ID"/utf8>>};
Rest ->
gleam@result:'try'(
case begin
_pipe = gleam@string:join(
Rest,
<<"_"/utf8>>
),
gleam@bit_array:base64_decode(_pipe)
end of
{error, _} ->
{error, <<"Invalid Pika ID"/utf8>>};
{ok, Decoded_tail} ->
{ok, Decoded_tail}
end,
fun(Tail_bit_array) ->
case begin
_pipe@1 = Tail_bit_array,
gleam@bit_array:to_string(_pipe@1)
end of
{error, _} ->
{error,
<<"Invalid Pika ID"/utf8>>};
{ok, Decoded_tail@1} ->
{ok, Decoded_tail@1}
end
end
)
end, fun(Decoded_tail@2) ->
gleam@result:'try'(
case erlang:element(4, Prefix@2) of
false ->
case gleam@int:parse(Decoded_tail@2) of
{error, _} ->
{error,
<<"Invalid Pika ID"/utf8>>};
{ok, Num} ->
{ok, Num}
end;
true ->
gleam@result:'try'(
case begin
_pipe@2 = gleam@string:split(
Decoded_tail@2,
<<"_"/utf8>>
),
gleam@list:last(_pipe@2)
end of
{error, _} ->
{error,
<<"Invalid Pika ID"/utf8>>};
{ok, Str_num} ->
{ok, Str_num}
end,
fun(Str_snowflake_id) ->
case gleam@int:parse(
Str_snowflake_id
) of
{error, _} ->
{error,
<<"Invalid Pika ID"/utf8>>};
{ok, Num@1} ->
{ok, Num@1}
end
end
)
end,
fun(Snowflake_id) ->
Snowflake_meta = pika_id@snowflake:deconstruct_snowflake_id(
Generator,
Snowflake_id
),
{ok,
{pika_id_metadata,
Id,
erlang:element(2, Prefix@2),
erlang:element(3, Prefix@2),
erlang:element(4, Prefix@2),
gleam@string:join(
Tail@1,
<<"_"/utf8>>
),
Decoded_tail@2,
erlang:element(2, Snowflake_meta),
erlang:element(3, Snowflake_meta),
erlang:element(4, Snowflake_meta),
erlang:element(5, Snowflake_meta),
erlang:element(6, Snowflake_meta)}}
end
)
end) end
)
end).
-spec pika_setup(pika_id@snowflake:snowflake_gen(), list(prefix())) -> pika().
pika_setup(Snowflake_gen, Prefixes) ->
{pika,
fun(_capture) -> gen(Snowflake_gen, Prefixes, _capture) end,
fun(_capture@1) -> deconstruct(Snowflake_gen, Prefixes, _capture@1) end}.
-spec pika_init(list(prefix())) -> {ok, pika()} | {error, binary()}.
pika_init(Prefixes) ->
case validate_settings(Prefixes, []) of
{error, Err} ->
{error,
<<"Unable to initialize pika: "/utf8,
(begin
_pipe = Err,
gleam@string:inspect(_pipe)
end)/binary>>};
{ok, {Snowflake_gen, Prefixes@1}} ->
{ok, pika_setup(Snowflake_gen, Prefixes@1)}
end.
-spec pika_custom_init(list(prefix()), list(pika_option())) -> {ok, pika()} |
{error, binary()}.
pika_custom_init(Prefixes, Options) ->
case validate_settings(Prefixes, Options) of
{error, Err} ->
{error,
<<"Unable to initialize pika: "/utf8,
(begin
_pipe = Err,
gleam@string:inspect(_pipe)
end)/binary>>};
{ok, {Snowflake_gen, Prefixes@1}} ->
{ok, pika_setup(Snowflake_gen, Prefixes@1)}
end.
-spec pika_deconstruct(pika(), binary()) -> {ok, pika_id_metadata()} |
{error, binary()}.
pika_deconstruct(Pika, Id) ->
(erlang:element(3, Pika))(Id).