Current section
Files
Jump to
Current section
Files
src/friendly_id@encoding.erl
-module(friendly_id@encoding).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/friendly_id/encoding.gleam").
-export([encoder_max_int/1, encode_int/2]).
-export_type([encoding_error/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.
-type encoding_error() :: out_of_bounds.
-file("src/friendly_id/encoding.gleam", 97).
-spec extract_raw_indices(integer(), integer(), integer(), list(integer())) -> list(integer()).
extract_raw_indices(Remaining_id, Pred_count, Count_left, Acc) ->
case Count_left =< 0 of
true ->
lists:reverse(Acc);
false ->
Pred_index = case Pred_count of
0 -> 0;
Gleam@denominator -> Remaining_id rem Gleam@denominator
end,
Next_remaining = case Pred_count of
0 -> 0;
Gleam@denominator@1 -> Remaining_id div Gleam@denominator@1
end,
extract_raw_indices(
Next_remaining,
Pred_count,
Count_left - 1,
[Pred_index | Acc]
)
end.
-file("src/friendly_id/encoding.gleam", 121).
-spec int_power_loop(integer(), integer(), integer()) -> integer().
int_power_loop(Base, Exponent, Acc) ->
case Exponent =< 0 of
true ->
Acc;
false ->
int_power_loop(Base, Exponent - 1, Acc * Base)
end.
-file("src/friendly_id/encoding.gleam", 117).
-spec int_power(integer(), integer()) -> integer().
int_power(Base, Exponent) ->
int_power_loop(Base, Exponent, 1).
-file("src/friendly_id/encoding.gleam", 87).
-spec encoder_max_int(friendly_id@generator:generator()) -> integer().
encoder_max_int(Generator) ->
Obj_count = erlang:tuple_size(friendly_id@generator:get_objects(Generator)),
Pred_count = erlang:tuple_size(
friendly_id@generator:get_predicates(Generator)
),
Total_combinations = Obj_count * int_power(
Pred_count,
friendly_id@generator:get_predicate_count(Generator)
),
Total_combinations - 1.
-file("src/friendly_id/encoding.gleam", 22).
?DOC(
" Encodes an int to a Friendly ID. This is a deterministic operation, which means an int will always return the same ID, and guarantees no collisions.\n"
"\n"
" # Examples\n"
"\n"
" ## Create a generator with defaults, then generate an ID by encoding an int\n"
"\n"
" ```gleam\n"
" let generator = generator.new()\n"
" echo encoding.encode_int(generator, 23)\n"
" ```\n"
).
-spec encode_int(friendly_id@generator:generator(), integer()) -> {ok, binary()} |
{error, encoding_error()}.
encode_int(Generator, Id) ->
Max_id = encoder_max_int(Generator),
case (Id < 0) orelse (Id > Max_id) of
true ->
{error, out_of_bounds};
false ->
Objects = friendly_id@generator:get_objects(Generator),
Predicates = friendly_id@generator:get_predicates(Generator),
Obj_count = erlang:tuple_size(Objects),
Pred_count = erlang:tuple_size(Predicates),
Raw_obj = case Obj_count of
0 -> 0;
Gleam@denominator -> Id rem Gleam@denominator
end,
Remaining_id = case Obj_count of
0 -> 0;
Gleam@denominator@1 -> Id div Gleam@denominator@1
end,
Raw_preds = extract_raw_indices(
Remaining_id,
Pred_count,
friendly_id@generator:get_predicate_count(Generator),
[]
),
Scrambled_obj = case Obj_count of
0 -> 0;
Gleam@denominator@2 -> ((Raw_obj * friendly_id@generator:get_obj_multiplier(
Generator
))
+ 1337)
rem Gleam@denominator@2
end,
{_, Scrambled_preds} = gleam@list:map_fold(
Raw_preds,
Scrambled_obj,
fun(Cascade, Raw_pred) ->
Scrambled_pred = case Pred_count of
0 -> 0;
Gleam@denominator@3 -> (((Raw_pred * friendly_id@generator:get_pred_multiplier(
Generator
))
+ 1337)
+ Cascade)
rem Gleam@denominator@3
end,
{Scrambled_pred, Scrambled_pred}
end
),
Object_word@1 = case glearray_ffi:get(Objects, Scrambled_obj) of
{ok, Object_word} -> Object_word;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"friendly_id/encoding"/utf8>>,
function => <<"encode_int"/utf8>>,
line => 70,
value => _assert_fail,
start => 1780,
'end' => 1845,
pattern_start => 1791,
pattern_end => 1806})
end,
Pred_words = gleam@list:map(
lists:reverse(Scrambled_preds),
fun(Idx) ->
Pred_word@1 = case glearray_ffi:get(Predicates, Idx) of
{ok, Pred_word} -> Pred_word;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"friendly_id/encoding"/utf8>>,
function => <<"encode_int"/utf8>>,
line => 74,
value => _assert_fail@1,
start => 1938,
'end' => 1994,
pattern_start => 1949,
pattern_end => 1962})
end,
Pred_word@1
end
),
Parts = lists:append(Pred_words, [Object_word@1]),
Transformed_parts = gleam@list:map(
Parts,
friendly_id@generator:get_transform_fn(Generator)
),
{ok,
gleam@string:join(
Transformed_parts,
friendly_id@generator:get_separator(Generator)
)}
end.