-module(packkit@internal@fse).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/packkit/internal/fse.gleam").
-export([predefined_literal_length/0, predefined_match_length/0, predefined_offset/0, predefined_literal_length_log/0, predefined_match_length_log/0, predefined_offset_log/0, high_bit_position/1, build_state_table/2, predefined_literal_length_table/0, predefined_match_length_table/0, predefined_offset_table/0, state_count/1, read_backward_bits/2, read_backward_bits_padded/2, new_backward_reader/1, ll_base/1, ll_extra_bits/1, ml_base/1, ml_extra_bits/1, decode_state/3, distribution_total/1]).
-export_type([state_entry/0, backward_reader/0, fse_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.
?MODULEDOC(false).
-type state_entry() :: {state_entry, integer(), integer(), integer()}.
-opaque backward_reader() :: {backward_reader,
integer(),
integer(),
list(integer())}.
-type fse_error() :: fse_empty_bitstream | fse_truncated.
-file("src/packkit/internal/fse.gleam", 18).
?DOC(false).
-spec predefined_literal_length() -> list(integer()).
predefined_literal_length() ->
[4,
3,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
1,
1,
1,
2,
2,
2,
2,
2,
2,
2,
2,
2,
3,
2,
1,
1,
1,
1,
1,
-1,
-1,
-1,
-1].
-file("src/packkit/internal/fse.gleam", 28).
?DOC(false).
-spec predefined_match_length() -> list(integer()).
predefined_match_length() ->
[1,
4,
3,
2,
2,
2,
2,
2,
2,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
-1,
-1,
-1,
-1,
-1,
-1,
-1].
-file("src/packkit/internal/fse.gleam", 37).
?DOC(false).
-spec predefined_offset() -> list(integer()).
predefined_offset() ->
[1,
1,
1,
1,
1,
1,
2,
2,
2,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
-1,
-1,
-1,
-1,
-1].
-file("src/packkit/internal/fse.gleam", 45).
?DOC(false).
-spec predefined_literal_length_log() -> integer().
predefined_literal_length_log() ->
6.
-file("src/packkit/internal/fse.gleam", 49).
?DOC(false).
-spec predefined_match_length_log() -> integer().
predefined_match_length_log() ->
6.
-file("src/packkit/internal/fse.gleam", 53).
?DOC(false).
-spec predefined_offset_log() -> integer().
predefined_offset_log() ->
5.
-file("src/packkit/internal/fse.gleam", 92).
?DOC(false).
-spec real_counts(
list(integer()),
gleam@dict:dict(integer(), integer()),
integer()
) -> gleam@dict:dict(integer(), integer()).
real_counts(Normalized, Acc, Symbol) ->
case Normalized of
[] ->
Acc;
[N | Rest] ->
Count = case N of
-1 ->
1;
V ->
V
end,
real_counts(Rest, gleam@dict:insert(Acc, Symbol, Count), Symbol + 1)
end.
-file("src/packkit/internal/fse.gleam", 132).
?DOC(false).
-spec place_less_probable(
list(integer()),
integer(),
integer(),
gleam@dict:dict(integer(), integer())
) -> {gleam@dict:dict(integer(), integer()), integer()}.
place_less_probable(Normalized, Symbol, High_cursor, Acc) ->
case Normalized of
[] ->
{Acc, High_cursor};
[N | Rest] ->
case N of
-1 ->
place_less_probable(
Rest,
Symbol + 1,
High_cursor - 1,
gleam@dict:insert(Acc, High_cursor, Symbol)
);
_ ->
place_less_probable(Rest, Symbol + 1, High_cursor, Acc)
end
end.
-file("src/packkit/internal/fse.gleam", 229).
?DOC(false).
-spec advance_cursor(integer(), integer(), integer(), integer()) -> integer().
advance_cursor(Cursor, Mask, Step, High_threshold) ->
Next = erlang:'band'(Cursor + Step, Mask),
case Next > High_threshold of
true ->
advance_cursor(Next, Mask, Step, High_threshold);
false ->
Next
end.
-file("src/packkit/internal/fse.gleam", 202).
?DOC(false).
-spec place_one_symbol(
integer(),
integer(),
integer(),
gleam@dict:dict(integer(), integer()),
integer(),
integer(),
integer()
) -> {integer(), gleam@dict:dict(integer(), integer())}.
place_one_symbol(
Symbol,
Remaining,
Cursor,
Positions,
Mask,
Step,
High_threshold
) ->
case Remaining of
0 ->
{Cursor, Positions};
_ ->
Positions@1 = gleam@dict:insert(Positions, Cursor, Symbol),
New_cursor = advance_cursor(Cursor, Mask, Step, High_threshold),
place_one_symbol(
Symbol,
Remaining - 1,
New_cursor,
Positions@1,
Mask,
Step,
High_threshold
)
end.
-file("src/packkit/internal/fse.gleam", 154).
?DOC(false).
-spec place_normal(
list(integer()),
integer(),
integer(),
gleam@dict:dict(integer(), integer()),
integer(),
integer(),
integer()
) -> gleam@dict:dict(integer(), integer()).
place_normal(Normalized, Cursor, Symbol, Positions, Mask, Step, High_threshold) ->
case Normalized of
[] ->
Positions;
[N | Rest] ->
case N of
V when V =< 0 ->
place_normal(
Rest,
Cursor,
Symbol + 1,
Positions,
Mask,
Step,
High_threshold
);
V@1 ->
{New_cursor, Positions@1} = place_one_symbol(
Symbol,
V@1,
Cursor,
Positions,
Mask,
Step,
High_threshold
),
place_normal(
Rest,
New_cursor,
Symbol + 1,
Positions@1,
Mask,
Step,
High_threshold
)
end
end.
-file("src/packkit/internal/fse.gleam", 112).
?DOC(false).
-spec assign_positions(list(integer()), integer(), integer()) -> gleam@dict:dict(integer(), integer()).
assign_positions(Normalized, _, Table_size) ->
Mask = Table_size - 1,
Step = (erlang:'bsr'(Table_size, 1) + erlang:'bsr'(Table_size, 3)) + 3,
High_threshold = Table_size - 1,
{Positions, Next_high} = place_less_probable(
Normalized,
0,
High_threshold,
maps:new()
),
place_normal(Normalized, 0, 0, Positions, Mask, Step, Next_high).
-file("src/packkit/internal/fse.gleam", 287).
?DOC(false).
-spec high_bit_position(integer()) -> integer().
high_bit_position(Value) ->
case Value of
N when N =< 1 ->
0;
_ ->
1 + high_bit_position(erlang:'bsr'(Value, 1))
end.
-file("src/packkit/internal/fse.gleam", 237).
?DOC(false).
-spec build_entries(
gleam@dict:dict(integer(), integer()),
gleam@dict:dict(integer(), integer()),
gleam@dict:dict(integer(), integer()),
integer(),
integer(),
integer(),
gleam@dict:dict(integer(), state_entry())
) -> gleam@dict:dict(integer(), state_entry()).
build_entries(
Positions,
Counts,
Symbol_next,
Accuracy_log,
Table_size,
State_index,
Acc
) ->
case State_index >= Table_size of
true ->
Acc;
false ->
Symbol = case gleam_stdlib:map_get(Positions, State_index) of
{ok, V} ->
V;
{error, _} ->
0
end,
Count = case gleam_stdlib:map_get(Counts, Symbol) of
{ok, V@1} ->
V@1;
{error, _} ->
1
end,
Next_value = case gleam_stdlib:map_get(Symbol_next, Symbol) of
{ok, V@2} ->
V@2;
{error, _} ->
Count
end,
Nb_bits = Accuracy_log - high_bit_position(Next_value),
Baseline = erlang:'bsl'(Next_value, Nb_bits) - Table_size,
Entry = {state_entry, Symbol, Nb_bits, Baseline},
build_entries(
Positions,
Counts,
gleam@dict:insert(Symbol_next, Symbol, Next_value + 1),
Accuracy_log,
Table_size,
State_index + 1,
gleam@dict:insert(Acc, State_index, Entry)
)
end.
-file("src/packkit/internal/fse.gleam", 71).
?DOC(false).
-spec build_state_table(list(integer()), integer()) -> gleam@dict:dict(integer(), state_entry()).
build_state_table(Normalized, Accuracy_log) ->
Table_size = erlang:'bsl'(1, Accuracy_log),
Position_dict = assign_positions(Normalized, Accuracy_log, Table_size),
Symbol_counts = real_counts(Normalized, maps:new(), 0),
build_entries(
Position_dict,
Symbol_counts,
maps:new(),
Accuracy_log,
Table_size,
0,
maps:new()
).
-file("src/packkit/internal/fse.gleam", 295).
?DOC(false).
-spec predefined_literal_length_table() -> gleam@dict:dict(integer(), state_entry()).
predefined_literal_length_table() ->
build_state_table(
predefined_literal_length(),
predefined_literal_length_log()
).
-file("src/packkit/internal/fse.gleam", 303).
?DOC(false).
-spec predefined_match_length_table() -> gleam@dict:dict(integer(), state_entry()).
predefined_match_length_table() ->
build_state_table(predefined_match_length(), predefined_match_length_log()).
-file("src/packkit/internal/fse.gleam", 308).
?DOC(false).
-spec predefined_offset_table() -> gleam@dict:dict(integer(), state_entry()).
predefined_offset_table() ->
build_state_table(predefined_offset(), predefined_offset_log()).
-file("src/packkit/internal/fse.gleam", 313).
?DOC(false).
-spec state_count(integer()) -> integer().
state_count(Accuracy_log) ->
erlang:'bsl'(1, Accuracy_log).
-file("src/packkit/internal/fse.gleam", 412).
?DOC(false).
-spec refill_backward(backward_reader(), integer()) -> backward_reader().
refill_backward(Reader, Needed) ->
case erlang:element(3, Reader) >= Needed of
true ->
Reader;
false ->
case erlang:element(4, Reader) of
[Byte | Rest] ->
New_buffer = erlang:'bor'(
erlang:'bsl'(erlang:element(2, Reader), 8),
Byte
),
refill_backward(
{backward_reader,
New_buffer,
erlang:element(3, Reader) + 8,
Rest},
Needed
);
[] ->
Reader
end
end.
-file("src/packkit/internal/fse.gleam", 357).
?DOC(false).
-spec read_backward_bits(backward_reader(), integer()) -> {ok,
{integer(), backward_reader()}} |
{error, fse_error()}.
read_backward_bits(Reader, Count) ->
Reader@1 = refill_backward(Reader, Count),
case erlang:element(3, Reader@1) >= Count of
false ->
{error, fse_truncated};
true ->
Shift = erlang:element(3, Reader@1) - Count,
Mask = erlang:'bsl'(1, Count) - 1,
Value = erlang:'band'(
erlang:'bsr'(erlang:element(2, Reader@1), Shift),
Mask
),
Leftover_mask = erlang:'bsl'(1, Shift) - 1,
{ok,
{Value,
{backward_reader,
erlang:'band'(
erlang:element(2, Reader@1),
Leftover_mask
),
Shift,
erlang:element(4, Reader@1)}}}
end.
-file("src/packkit/internal/fse.gleam", 387).
?DOC(false).
-spec read_backward_bits_padded(backward_reader(), integer()) -> {ok,
{integer(), backward_reader()}} |
{error, fse_error()}.
read_backward_bits_padded(Reader, Count) ->
Reader@1 = refill_backward(Reader, Count),
case erlang:element(3, Reader@1) >= Count of
true ->
read_backward_bits(Reader@1, Count);
false ->
case erlang:element(3, Reader@1) of
0 ->
{error, fse_empty_bitstream};
Available ->
Pad = Count - Available,
Mask = erlang:'bsl'(1, Available) - 1,
Value = begin
_pipe = erlang:'band'(erlang:element(2, Reader@1), Mask),
erlang:'bsl'(_pipe, Pad)
end,
{ok,
{Value,
{backward_reader, 0, 0, erlang:element(4, Reader@1)}}}
end
end.
-file("src/packkit/internal/fse.gleam", 434).
?DOC(false).
-spec bytes_to_reverse_list(bitstring(), list(integer())) -> list(integer()).
bytes_to_reverse_list(Bytes, Acc) ->
case Bytes of
<<B, Rest/binary>> ->
bytes_to_reverse_list(Rest, [B | Acc]);
_ ->
Acc
end.
-file("src/packkit/internal/fse.gleam", 329).
?DOC(false).
-spec new_backward_reader(bitstring()) -> {ok, backward_reader()} |
{error, fse_error()}.
new_backward_reader(Bytes) ->
Bytes_rev = bytes_to_reverse_list(Bytes, []),
case Bytes_rev of
[] ->
{error, fse_empty_bitstream};
[Last | Rest] ->
High = high_bit_position(Last),
case Last =:= 0 of
true ->
{error, fse_empty_bitstream};
false ->
Bits_below = High,
Mask = erlang:'bsl'(1, Bits_below) - 1,
Initial = erlang:'band'(Last, Mask),
{ok, {backward_reader, Initial, Bits_below, Rest}}
end
end.
-file("src/packkit/internal/fse.gleam", 447).
?DOC(false).
-spec ll_base(integer()) -> integer().
ll_base(Code) ->
case Code of
N when (N >= 0) andalso (N =< 15) ->
N;
16 ->
16;
17 ->
18;
18 ->
20;
19 ->
22;
20 ->
24;
21 ->
28;
22 ->
32;
23 ->
40;
24 ->
48;
25 ->
64;
26 ->
128;
27 ->
256;
28 ->
512;
29 ->
1024;
30 ->
2048;
31 ->
4096;
32 ->
8192;
33 ->
16384;
34 ->
32768;
35 ->
65536;
_ ->
0
end.
-file("src/packkit/internal/fse.gleam", 475).
?DOC(false).
-spec ll_extra_bits(integer()) -> integer().
ll_extra_bits(Code) ->
case Code of
N when (N >= 0) andalso (N =< 15) ->
0;
N@1 when (N@1 >= 16) andalso (N@1 =< 19) ->
1;
N@2 when (N@2 >= 20) andalso (N@2 =< 21) ->
2;
N@3 when (N@3 >= 22) andalso (N@3 =< 23) ->
3;
24 ->
4;
25 ->
6;
26 ->
7;
27 ->
8;
28 ->
9;
29 ->
10;
30 ->
11;
31 ->
12;
32 ->
13;
33 ->
14;
34 ->
15;
35 ->
16;
_ ->
0
end.
-file("src/packkit/internal/fse.gleam", 501).
?DOC(false).
-spec ml_base(integer()) -> integer().
ml_base(Code) ->
case Code of
N when (N >= 0) andalso (N =< 31) ->
3 + N;
32 ->
35;
33 ->
37;
34 ->
39;
35 ->
41;
36 ->
43;
37 ->
47;
38 ->
51;
39 ->
59;
40 ->
67;
41 ->
83;
42 ->
99;
43 ->
131;
44 ->
259;
45 ->
515;
46 ->
1027;
47 ->
2051;
48 ->
4099;
49 ->
8195;
50 ->
16387;
51 ->
32771;
52 ->
65539;
_ ->
3
end.
-file("src/packkit/internal/fse.gleam", 530).
?DOC(false).
-spec ml_extra_bits(integer()) -> integer().
ml_extra_bits(Code) ->
case Code of
N when (N >= 0) andalso (N =< 31) ->
0;
N@1 when (N@1 >= 32) andalso (N@1 =< 35) ->
1;
N@2 when (N@2 >= 36) andalso (N@2 =< 37) ->
2;
N@3 when (N@3 >= 38) andalso (N@3 =< 39) ->
3;
40 ->
4;
41 ->
4;
42 ->
5;
43 ->
7;
44 ->
8;
45 ->
9;
46 ->
10;
47 ->
11;
48 ->
12;
49 ->
13;
50 ->
14;
51 ->
15;
52 ->
16;
_ ->
0
end.
-file("src/packkit/internal/fse.gleam", 556).
?DOC(false).
-spec decode_state(
gleam@dict:dict(integer(), state_entry()),
integer(),
backward_reader()
) -> {ok, {integer(), integer(), backward_reader()}} | {error, fse_error()}.
decode_state(Table, State, Reader) ->
Entry = case gleam_stdlib:map_get(Table, State) of
{ok, E} ->
E;
{error, _} ->
{state_entry, 0, 0, 0}
end,
gleam@result:'try'(
read_backward_bits(Reader, erlang:element(3, Entry)),
fun(_use0) ->
{Extra, Reader@1} = _use0,
{ok,
{erlang:element(2, Entry),
erlang:element(4, Entry) + Extra,
Reader@1}}
end
).
-file("src/packkit/internal/fse.gleam", 571).
?DOC(false).
-spec distribution_total(list(integer())) -> integer().
distribution_total(Normalized) ->
gleam@list:fold(Normalized, 0, fun(Acc, N) -> case N of
-1 ->
Acc + 1;
V ->
Acc + V
end end).