-module(packkit@internal@bcj2). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/packkit/internal/bcj2.gleam"). -export([decode/5]). -export_type([bcj2_error/0, state/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 bcj2_error() :: range_coder_header_invalid | {stream_exhausted, binary()} | {output_size_mismatch, integer(), integer()}. -type state() :: {state, bitstring(), bitstring(), bitstring(), bitstring(), gleam@dict:dict(integer(), integer()), integer(), integer(), integer(), integer(), bitstring(), integer()}. -file("src/packkit/internal/bcj2.gleam", 143). ?DOC(false). -spec init_range_coder(bitstring()) -> {ok, {integer(), bitstring()}} | {error, bcj2_error()}. init_range_coder(Rc) -> case Rc of <> -> case First =:= 0 of true -> Code = erlang:'bor'( erlang:'bor'(erlang:'bsl'(C1, 24), erlang:'bsl'(C2, 16)), erlang:'bor'(erlang:'bsl'(C3, 8), C4) ), {ok, {Code, Rest}}; false -> {error, range_coder_header_invalid} end; _ -> {error, range_coder_header_invalid} end. -file("src/packkit/internal/bcj2.gleam", 209). ?DOC(false). -spec consume_main_byte(state(), integer(), bitstring()) -> state(). consume_main_byte(State, Byte, Main_rest) -> {state, Main_rest, erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State) + 1, Byte, <<(erlang:element(11, State))/bitstring, Byte>>, erlang:element(12, State)}. -file("src/packkit/internal/bcj2.gleam", 223). ?DOC(false). -spec is_branch_candidate(integer(), integer()) -> boolean(). is_branch_candidate(Byte, Prev_byte) -> case Byte of 16#E8 -> true; 16#E9 -> true; _ -> case (Prev_byte =:= 16#0F) andalso (erlang:'band'(Byte, 16#F0) =:= 16#80) of true -> true; false -> false end end. -file("src/packkit/internal/bcj2.gleam", 269). ?DOC(false). -spec prev_byte_for_call(state()) -> integer(). prev_byte_for_call(State) -> Output_size = erlang:byte_size(erlang:element(11, State)), case Output_size < 2 of true -> 0; false -> case gleam_stdlib:bit_array_slice( erlang:element(11, State), Output_size - 2, 1 ) of {ok, <>} -> Single; _ -> 0 end end. -file("src/packkit/internal/bcj2.gleam", 283). ?DOC(false). -spec range_decode_bit(integer(), integer(), integer()) -> {integer(), integer(), integer(), integer()}. range_decode_bit(Range, Code, Prob) -> Bound = begin _pipe = erlang:'bsr'(Range, 11), _pipe@1 = gleam@int:multiply(_pipe, Prob), erlang:'band'(_pipe@1, 16#FFFFFFFF) end, case Code < Bound of true -> New_prob = Prob + erlang:'bsr'(16#800 - Prob, 5), {0, Bound, Code, New_prob}; false -> New_range = erlang:'band'(Range - Bound, 16#FFFFFFFF), New_code = erlang:'band'(Code - Bound, 16#FFFFFFFF), New_prob@1 = Prob - erlang:'bsr'(Prob, 5), {1, New_range, New_code, New_prob@1} end. -file("src/packkit/internal/bcj2.gleam", 336). ?DOC(false). -spec emit_branch_target(state(), integer()) -> {ok, state()} | {error, bcj2_error()}. emit_branch_target(State, Opcode) -> {Dest_stream, Dest_label} = case Opcode =:= 16#E8 of true -> {erlang:element(3, State), <<"call"/utf8>>}; false -> {erlang:element(4, State), <<"jump"/utf8>>} end, case Dest_stream of <> -> Target = erlang:'bor'( erlang:'bor'(erlang:'bsl'(B0, 24), erlang:'bsl'(B1, 16)), erlang:'bor'(erlang:'bsl'(B2, 8), B3) ), New_ip = erlang:element(9, State) + 4, Relative = erlang:'band'(Target - New_ip, 16#FFFFFFFF), R0 = erlang:'band'(Relative, 16#FF), R1 = erlang:'band'(erlang:'bsr'(Relative, 8), 16#FF), R2 = erlang:'band'(erlang:'bsr'(Relative, 16), 16#FF), R3 = erlang:'band'(erlang:'bsr'(Relative, 24), 16#FF), New_output = <<(erlang:element(11, State))/bitstring, R0, R1, R2, R3>>, Next_state = {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), New_ip, R3, New_output, erlang:element(12, State)}, case Opcode =:= 16#E8 of true -> {ok, {state, erlang:element(2, Next_state), Dest_rest, erlang:element(4, Next_state), erlang:element(5, Next_state), erlang:element(6, Next_state), erlang:element(7, Next_state), erlang:element(8, Next_state), erlang:element(9, Next_state), erlang:element(10, Next_state), erlang:element(11, Next_state), erlang:element(12, Next_state)}}; false -> {ok, {state, erlang:element(2, Next_state), erlang:element(3, Next_state), Dest_rest, erlang:element(5, Next_state), erlang:element(6, Next_state), erlang:element(7, Next_state), erlang:element(8, Next_state), erlang:element(9, Next_state), erlang:element(10, Next_state), erlang:element(11, Next_state), erlang:element(12, Next_state)}} end; _ -> {error, {stream_exhausted, Dest_label}} end. -file("src/packkit/internal/bcj2.gleam", 129). ?DOC(false). -spec init_probs(integer(), gleam@dict:dict(integer(), integer())) -> gleam@dict:dict(integer(), integer()). init_probs(Index, Acc) -> case gleam@int:compare(Index, 258) of lt -> init_probs(Index + 1, gleam@dict:insert(Acc, Index, 16#800 div 2)); _ -> Acc end. -file("src/packkit/internal/bcj2.gleam", 178). ?DOC(false). -spec decode_loop_step(state()) -> {ok, state()} | {error, bcj2_error()}. decode_loop_step(State) -> case erlang:element(2, State) of <<>> -> {ok, State}; <> -> After_consume = consume_main_byte(State, Byte, Main_rest), gleam@result:'try'( decode_main_byte(After_consume, Byte, erlang:element(10, State)), fun(Stepped) -> decode_loop(Stepped) end ); _ -> {error, {stream_exhausted, <<"main"/utf8>>}} end. -file("src/packkit/internal/bcj2.gleam", 166). ?DOC(false). -spec decode_loop(state()) -> {ok, state()} | {error, bcj2_error()}. decode_loop(State) -> case gleam@int:compare( erlang:byte_size(erlang:element(11, State)), erlang:element(12, State) ) of lt -> decode_loop_step(State); _ -> {ok, State} end. -file("src/packkit/internal/bcj2.gleam", 80). ?DOC(false). -spec decode(bitstring(), bitstring(), bitstring(), bitstring(), integer()) -> {ok, bitstring()} | {error, bcj2_error()}. decode(Main, Call, Jump, Rc, Output_size) -> gleam@result:'try'( init_range_coder(Rc), fun(_use0) -> {Code, Rc_rest} = _use0, Probs = init_probs(0, maps:new()), Initial = {state, Main, Call, Jump, Rc_rest, Probs, 16#FFFFFFFF, Code, 0, 0, <<>>, Output_size}, gleam@result:'try'( decode_loop(Initial), fun(Final_state) -> Actual = erlang:byte_size(erlang:element(11, Final_state)), case Actual =:= Output_size of true -> {ok, erlang:element(11, Final_state)}; false -> {error, {output_size_mismatch, Output_size, Actual}} end end ) end ). -file("src/packkit/internal/bcj2.gleam", 317). ?DOC(false). -spec refill_rc_step(state()) -> {ok, state()} | {error, bcj2_error()}. refill_rc_step(State) -> case erlang:element(5, State) of <> -> New_range = begin _pipe = erlang:'bsl'(erlang:element(7, State), 8), erlang:'band'(_pipe, 16#FFFFFFFF) end, New_code = begin _pipe@1 = erlang:'bor'( erlang:'bsl'(erlang:element(8, State), 8), Next ), erlang:'band'(_pipe@1, 16#FFFFFFFF) end, maybe_refill_rc( {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), Rc_rest, erlang:element(6, State), New_range, New_code, erlang:element(9, State), erlang:element(10, State), erlang:element(11, State), erlang:element(12, State)} ); _ -> {error, {stream_exhausted, <<"range_coder"/utf8>>}} end. -file("src/packkit/internal/bcj2.gleam", 308). ?DOC(false). -spec maybe_refill_rc(state()) -> {ok, state()} | {error, bcj2_error()}. maybe_refill_rc(State) -> case gleam@int:compare(erlang:element(7, State), 16#1000000) of lt -> refill_rc_step(State); _ -> {ok, State} end. -file("src/packkit/internal/bcj2.gleam", 239). ?DOC(false). -spec decode_branch(state(), integer()) -> {ok, state()} | {error, bcj2_error()}. decode_branch(State, Opcode) -> Prob_index = case Opcode of 16#E8 -> 2 + prev_byte_for_call(State); 16#E9 -> 1; _ -> 0 end, Prob = begin _pipe = gleam_stdlib:map_get(erlang:element(6, State), Prob_index), gleam@result:unwrap(_pipe, 16#800 div 2) end, {Bit, Range_after, Code_after, Prob_after} = range_decode_bit( erlang:element(7, State), erlang:element(8, State), Prob ), Probs_after = gleam@dict:insert( erlang:element(6, State), Prob_index, Prob_after ), Intermediate = {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), Probs_after, Range_after, Code_after, erlang:element(9, State), erlang:element(10, State), erlang:element(11, State), erlang:element(12, State)}, gleam@result:'try'( maybe_refill_rc(Intermediate), fun(Refilled) -> case Bit of 0 -> {ok, Refilled}; _ -> emit_branch_target(Refilled, Opcode) end end ). -file("src/packkit/internal/bcj2.gleam", 194). ?DOC(false). -spec decode_main_byte(state(), integer(), integer()) -> {ok, state()} | {error, bcj2_error()}. decode_main_byte(State, Byte, Prev_byte_before_consume) -> gleam@bool:guard( not is_branch_candidate(Byte, Prev_byte_before_consume), {ok, State}, fun() -> decode_branch(State, Byte) end ).