-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 => <>, 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 => <>, 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.