Packages

A Gleam implementation of CUID2, the secure, collision-resistant ids optimized for horizontal scaling and performance.

Current section

Files

Jump to
glecuid src glecuid@cuid2.erl
Raw

src/glecuid@cuid2.erl

-module(glecuid@cuid2).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/glecuid/cuid2.gleam").
-export([generate/1, is_cuid/1, with_counter/2, with_fingerprint/2, with_length/2, with_randomizer/2, new/0, create_id/0]).
-export_type([generator/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-opaque generator() :: {generator,
glecuid@internals@counter:counter(),
binary(),
integer(),
fun(() -> float())}.
-file("src/glecuid/cuid2.gleam", 58).
?DOC(
" Generates a CUIDv2 using custom generator.\n"
" \n"
" ## Examples\n"
" \n"
" ```gleam\n"
" cuid2.new()\n"
" |> cuid2.with_length(10)\n"
" |> cuid2.with_fingerprint(\"my_machine\")\n"
" |> cuid2.generate()\n"
" // -> \"av77nekw5e\"\n"
" ```\n"
).
-spec generate(generator()) -> binary().
generate(G) ->
{generator, Counter, Fingerprint, Length, Randomizer} = G,
First_letter = glecuid@internals@util:random_letter(Randomizer),
Time = begin
_pipe = gleam@time@timestamp:system_time(),
_pipe@1 = gleam@time@timestamp:to_unix_seconds_and_nanoseconds(_pipe),
_pipe@2 = gleam@pair:first(_pipe@1),
gleam@int:to_base36(_pipe@2)
end,
Count = begin
_pipe@3 = glecuid@internals@counter:bump(Counter),
gleam@int:to_base36(_pipe@3)
end,
Salt = glecuid@internals@util:create_entropy(Randomizer, Length),
<<First_letter/binary,
(begin
_pipe@4 = (<<<<<<Time/binary, Salt/binary>>/binary, Count/binary>>/binary,
Fingerprint/binary>>),
_pipe@5 = glecuid@internals@util:hash(_pipe@4),
_pipe@6 = gleam@string:slice(_pipe@5, 1, Length - 1),
string:lowercase(_pipe@6)
end)/binary>>.
-file("src/glecuid/cuid2.gleam", 80).
?DOC(" Determines whether or not the string is a valid CUIDv2.\n").
-spec is_cuid(binary()) -> boolean().
is_cuid(Input) ->
Length = begin
_pipe = Input,
string:length(_pipe)
end,
Regex@1 = case gleam@regexp:from_string(<<"^[a-z][0-9a-z]+$"/utf8>>) of
{ok, Regex} -> Regex;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"glecuid/cuid2"/utf8>>,
function => <<"is_cuid"/utf8>>,
line => 82,
value => _assert_fail,
start => 1853,
'end' => 1914,
pattern_start => 1864,
pattern_end => 1873})
end,
case gleam@regexp:check(Regex@1, Input) of
true when (2 =< Length) andalso (Length =< 32) ->
true;
_ ->
false
end.
-file("src/glecuid/cuid2.gleam", 110).
?DOC(
" Sets a custom counter to be used by the `Generator`.\n"
" \n"
" Counter is a function that returns an incrementing `Int` \n"
" every time it is called.\n"
).
-spec with_counter(generator(), fun(() -> integer())) -> generator().
with_counter(G, Counter) ->
{generator,
begin
_pipe = Counter,
glecuid@internals@counter:from_function(_pipe)
end,
erlang:element(3, G),
erlang:element(4, G),
erlang:element(5, G)}.
-file("src/glecuid/cuid2.gleam", 119).
?DOC(
" Sets a custom fingerprint to be used by the `Generator`.\n"
" \n"
" Fingerprint is a unique `String` to help prevent collision \n"
" when generating ids in a distributed system.\n"
).
-spec with_fingerprint(generator(), binary()) -> generator().
with_fingerprint(G, Fingerprint) ->
{generator,
erlang:element(2, G),
Fingerprint,
erlang:element(4, G),
erlang:element(5, G)}.
-file("src/glecuid/cuid2.gleam", 125).
?DOC(" Sets the length of the ids generated by the `Generator`.\n").
-spec with_length(generator(), integer()) -> generator().
with_length(G, Length) ->
{generator,
erlang:element(2, G),
erlang:element(3, G),
Length,
erlang:element(5, G)}.
-file("src/glecuid/cuid2.gleam", 134).
?DOC(
" Sets a custom randomizer to be used by the `Generator`.\n"
" \n"
" Randomizer is a function that returns a random `Float` \n"
" between zero (inclusive) and one (exclusive).\n"
).
-spec with_randomizer(generator(), fun(() -> float())) -> generator().
with_randomizer(G, Randomizer) ->
{generator,
erlang:element(2, G),
erlang:element(3, G),
erlang:element(4, G),
Randomizer}.
-file("src/glecuid/cuid2.gleam", 94).
?DOC(" Creates a `Generator` with default values to be customized.\n").
-spec new() -> generator().
new() ->
Randomizer = fun rand:uniform/0,
{generator,
begin
_pipe = glecuid@internals@util:random_int(Randomizer, 476782367),
glecuid@internals@counter:new(_pipe)
end,
glecuid@internals@util:create_fingerprint(Randomizer),
24,
Randomizer}.
-file("src/glecuid/cuid2.gleam", 42).
?DOC(
" Generates a CUIDv2 using the default generator.\n"
" \n"
" ## Examples\n"
" \n"
" ```gleam\n"
" cuid2.create_id()\n"
" // -> \"avu4793cnw6ljhov1s7Oxidg\" \n"
" ```\n"
).
-spec create_id() -> binary().
create_id() ->
generate(new()).