Current section
Files
Jump to
Current section
Files
src/gxid.erl
-module(gxid).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([string/1, time/1, machine_id/1, pid/1, random_number/1, to_xid/1, parse/1, start/0, generate/1]).
-export_type([message/0, state/0, xid/0, char_list/0]).
-opaque message() :: {generate, gleam@erlang@process:subject(xid())}.
-opaque state() :: {state, integer(), integer(), integer()}.
-opaque xid() :: {xid, integer(), integer(), integer(), integer(), binary()}.
-type char_list() :: any().
-spec string(xid()) -> binary().
string(Xid) ->
erlang:element(6, Xid).
-spec time(xid()) -> integer().
time(Xid) ->
erlang:element(2, Xid).
-spec machine_id(xid()) -> integer().
machine_id(Xid) ->
erlang:element(3, Xid).
-spec pid(xid()) -> integer().
pid(Xid) ->
erlang:element(4, Xid).
-spec random_number(xid()) -> integer().
random_number(Xid) ->
erlang:element(5, Xid).
-spec format_time(integer()) -> bitstring().
format_time(Time) ->
<<Time:32/big>>.
-spec format_machine_id(integer()) -> bitstring().
format_machine_id(Mid) ->
<<Mid:24/big>>.
-spec format_pid(integer()) -> bitstring().
format_pid(Pid) ->
<<Pid:16/big>>.
-spec format_random_number(integer()) -> bitstring().
format_random_number(Random_number) ->
<<(erlang:'bsl'(Random_number, 8)):24/big>>.
-spec encode_hex(integer()) -> binary().
encode_hex(I) ->
case I of
0 ->
<<"0"/utf8>>;
1 ->
<<"1"/utf8>>;
2 ->
<<"2"/utf8>>;
3 ->
<<"3"/utf8>>;
4 ->
<<"4"/utf8>>;
5 ->
<<"5"/utf8>>;
6 ->
<<"6"/utf8>>;
7 ->
<<"7"/utf8>>;
8 ->
<<"8"/utf8>>;
9 ->
<<"9"/utf8>>;
10 ->
<<"a"/utf8>>;
11 ->
<<"b"/utf8>>;
12 ->
<<"c"/utf8>>;
13 ->
<<"d"/utf8>>;
14 ->
<<"e"/utf8>>;
15 ->
<<"f"/utf8>>;
16 ->
<<"g"/utf8>>;
17 ->
<<"h"/utf8>>;
18 ->
<<"i"/utf8>>;
19 ->
<<"j"/utf8>>;
20 ->
<<"k"/utf8>>;
21 ->
<<"l"/utf8>>;
22 ->
<<"m"/utf8>>;
23 ->
<<"n"/utf8>>;
24 ->
<<"o"/utf8>>;
25 ->
<<"p"/utf8>>;
26 ->
<<"q"/utf8>>;
27 ->
<<"r"/utf8>>;
28 ->
<<"s"/utf8>>;
29 ->
<<"t"/utf8>>;
30 ->
<<"u"/utf8>>;
31 ->
<<"v"/utf8>>;
_ ->
<<""/utf8>>
end.
-spec encode(bitstring()) -> binary().
encode(Bit_xid) ->
_assert_subject = <<Bit_xid/bitstring>>,
<<B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11>> = case _assert_subject of
<<_, _, _, _, _, _, _, _, _, _, _, _>> -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"gxid"/utf8>>,
function => <<"encode"/utf8>>,
line => 135})
end,
Res = [encode_hex(erlang:'bsr'(B0, 3)),
encode_hex(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(B1, 6), 16#1F),
erlang:'band'(erlang:'bsl'(B0, 2), 16#1F)
)
),
encode_hex(erlang:'band'(erlang:'bsr'(B1, 1), 16#1F)),
encode_hex(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(B2, 4), 16#1F),
erlang:'band'(erlang:'bsl'(B1, 4), 16#1F)
)
),
encode_hex(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(B3, 7), 16#1F),
erlang:'band'(erlang:'bsl'(B2, 1), 16#1F)
)
),
encode_hex(erlang:'band'(erlang:'bsr'(B3, 2), 16#1F)),
encode_hex(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(B4, 5), 16#1F),
erlang:'band'(erlang:'bsl'(B3, 3), 16#1F)
)
),
encode_hex(erlang:'band'(B4, 16#1F)),
encode_hex(erlang:'bsr'(B5, 3)),
encode_hex(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(B6, 6), 16#1F),
erlang:'band'(erlang:'bsl'(B5, 2), 16#1F)
)
),
encode_hex(erlang:'band'(erlang:'bsr'(B6, 1), 16#1F)),
encode_hex(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(B7, 4), 16#1F),
erlang:'band'(erlang:'bsl'(B6, 4), 16#1F)
)
),
encode_hex(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(B8, 7), 16#1F),
erlang:'band'(erlang:'bsl'(B7, 1), 16#1F)
)
),
encode_hex(erlang:'band'(erlang:'bsr'(B8, 2), 16#1F)),
encode_hex(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(B9, 5), 16#1F),
erlang:'band'(erlang:'bsl'(B8, 3), 16#1F)
)
),
encode_hex(erlang:'band'(B9, 16#1F)),
encode_hex(erlang:'bsr'(B10, 3)),
encode_hex(
erlang:'bor'(
erlang:'band'(erlang:'bsr'(B11, 6), 16#1F),
erlang:'band'(erlang:'bsl'(B10, 2), 16#1F)
)
),
encode_hex(erlang:'band'(erlang:'bsr'(B11, 1), 16#1F)),
encode_hex(erlang:'band'(erlang:'bsl'(B11, 4), 16#1F))],
gleam@string:join(Res, <<""/utf8>>).
-spec to_xid(bitstring()) -> xid().
to_xid(Bit_xid) ->
_assert_subject = <<Bit_xid/bitstring>>,
<<Time:32/big-unsigned,
Mid:24/big-unsigned,
Pid:16/big-unsigned,
Rn1/big-unsigned,
Rn2/big-unsigned,
Rn3/big-unsigned>> = case _assert_subject of
<<_:32/big-unsigned,
_:24/big-unsigned,
_:16/big-unsigned,
_/big-unsigned,
_/big-unsigned,
_/big-unsigned>> -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"gxid"/utf8>>,
function => <<"to_xid"/utf8>>,
line => 246})
end,
{xid,
Time,
Mid,
Pid,
erlang:'bor'(
erlang:'bor'(erlang:'bsl'(Rn1, 16), erlang:'bsl'(Rn2, 8)),
Rn3
),
encode(Bit_xid)}.
-spec handle(message(), state()) -> gleam@otp@actor:next(message(), state()).
handle(Msg, State) ->
case Msg of
{generate, Reply} ->
gleam@otp@actor:send(
Reply,
begin
_pipe = [format_time(os:system_time(millisecond)),
format_machine_id(erlang:element(2, State)),
format_pid(erlang:element(3, State)),
format_random_number(erlang:element(4, State))],
_pipe@1 = gleam_stdlib:bit_array_concat(_pipe),
to_xid(_pipe@1)
end
),
{continue,
erlang:setelement(4, State, erlang:element(4, State) + 1),
none}
end.
-spec decode_hex(binary()) -> integer().
decode_hex(S) ->
case S of
<<"0"/utf8>> ->
0;
<<"1"/utf8>> ->
1;
<<"2"/utf8>> ->
2;
<<"3"/utf8>> ->
3;
<<"4"/utf8>> ->
4;
<<"5"/utf8>> ->
5;
<<"6"/utf8>> ->
6;
<<"7"/utf8>> ->
7;
<<"8"/utf8>> ->
8;
<<"9"/utf8>> ->
9;
<<"a"/utf8>> ->
10;
<<"b"/utf8>> ->
11;
<<"c"/utf8>> ->
12;
<<"d"/utf8>> ->
13;
<<"e"/utf8>> ->
14;
<<"f"/utf8>> ->
15;
<<"g"/utf8>> ->
16;
<<"h"/utf8>> ->
17;
<<"i"/utf8>> ->
18;
<<"j"/utf8>> ->
19;
<<"k"/utf8>> ->
20;
<<"l"/utf8>> ->
21;
<<"m"/utf8>> ->
22;
<<"n"/utf8>> ->
23;
<<"o"/utf8>> ->
24;
<<"p"/utf8>> ->
25;
<<"q"/utf8>> ->
26;
<<"r"/utf8>> ->
27;
<<"s"/utf8>> ->
28;
<<"t"/utf8>> ->
29;
<<"u"/utf8>> ->
30;
<<"v"/utf8>> ->
31;
_ ->
0
end.
-spec decode(binary()) -> bitstring().
decode(Xid) ->
_assert_subject = begin
_pipe = gleam@string:to_graphemes(Xid),
gleam@list:map(_pipe, fun(X) -> decode_hex(X) end)
end,
[S0,
S1,
S2,
S3,
S4,
S5,
S6,
S7,
S8,
S9,
S10,
S11,
S12,
S13,
S14,
S15,
S16,
S17,
S18,
S19] = case _assert_subject of
[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"gxid"/utf8>>,
function => <<"decode"/utf8>>,
line => 272})
end,
<<(erlang:'bor'(erlang:'bsl'(S0, 3), erlang:'bsr'(S1, 2))),
(erlang:'bor'(
erlang:'bor'(erlang:'bsl'(S1, 6), erlang:'bsl'(S2, 1)),
erlang:'bsr'(S3, 4)
)),
(erlang:'bor'(erlang:'bsl'(S3, 4), erlang:'bsr'(S4, 1))),
(erlang:'bor'(
erlang:'bor'(erlang:'bsl'(S4, 7), erlang:'bsl'(S5, 2)),
erlang:'bsr'(S6, 3)
)),
(erlang:'bor'(erlang:'bsl'(S6, 5), S7)),
(erlang:'bor'(erlang:'bsl'(S8, 3), erlang:'bsr'(S9, 2))),
(erlang:'bor'(
erlang:'bor'(erlang:'bsl'(S9, 6), erlang:'bsl'(S10, 1)),
erlang:'bsr'(S11, 4)
)),
(erlang:'bor'(erlang:'bsl'(S11, 4), erlang:'bsr'(S12, 1))),
(erlang:'bor'(
erlang:'bor'(erlang:'bsl'(S12, 7), erlang:'bsl'(S13, 2)),
erlang:'bsr'(S14, 3)
)),
(erlang:'bor'(erlang:'bsl'(S14, 5), S15)),
(erlang:'bor'(erlang:'bsl'(S16, 3), erlang:'bsr'(S17, 2))),
(erlang:'bor'(
erlang:'bor'(erlang:'bsl'(S17, 6), erlang:'bsl'(S18, 1)),
erlang:'bsr'(S19, 4)
))>>.
-spec parse(binary()) -> xid().
parse(Str_xid) ->
_pipe = decode(Str_xid),
to_xid(_pipe).
-spec find_pid() -> integer().
find_pid() ->
_assert_subject = begin
_pipe = os:getpid(),
_pipe@1 = erlang:list_to_binary(_pipe),
gleam@int:parse(_pipe@1)
end,
{ok, Pid} = 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 => <<"gxid"/utf8>>,
function => <<"find_pid"/utf8>>,
line => 120})
end,
Pid.
-spec find_machine_id() -> integer().
find_machine_id() ->
_pipe = net_adm:localhost(),
gleam@list:fold(_pipe, 0, fun(Char, Acc) -> Char + Acc end).
-spec start() -> {ok, gleam@erlang@process:subject(message())} |
{error, gleam@otp@actor:start_error()}.
start() ->
gleam@otp@actor:start(
{state, find_machine_id(), find_pid(), gleam@int:random(16777215)},
fun handle/2
).
-spec generate(gleam@erlang@process:subject(message())) -> xid().
generate(Channel) ->
gleam@otp@actor:call(Channel, fun(Field@0) -> {generate, Field@0} end, 1000).