src/qrkit@internal@rmqr.erl

-module(qrkit@internal@rmqr).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/qrkit/internal/rmqr.gleam").
-export([version/1, width/1, height/1, rows/1, mask/1, dimensions/1, encode/4]).
-export_type([encoded/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).

-opaque encoded() :: {encoded,
        integer(),
        integer(),
        integer(),
        list(list(boolean()))}.

-file("src/qrkit/internal/rmqr.gleam", 26).
?DOC(false).
-spec version(encoded()) -> integer().
version(Encoded) ->
    {encoded, Version, _, _, _} = Encoded,
    Version.

-file("src/qrkit/internal/rmqr.gleam", 31).
?DOC(false).
-spec width(encoded()) -> integer().
width(Encoded) ->
    {encoded, _, Width, _, _} = Encoded,
    Width.

-file("src/qrkit/internal/rmqr.gleam", 36).
?DOC(false).
-spec height(encoded()) -> integer().
height(Encoded) ->
    {encoded, _, _, Height, _} = Encoded,
    Height.

-file("src/qrkit/internal/rmqr.gleam", 41).
?DOC(false).
-spec rows(encoded()) -> list(list(boolean())).
rows(Encoded) ->
    {encoded, _, _, _, Rows} = Encoded,
    Rows.

-file("src/qrkit/internal/rmqr.gleam", 49).
?DOC(false).
-spec mask(encoded()) -> integer().
mask(_) ->
    4.

-file("src/qrkit/internal/rmqr.gleam", 196).
?DOC(false).
-spec validate_ecc(qrkit@types:error_correction()) -> {ok, nil} |
    {error, qrkit@error:encode_error()}.
validate_ecc(Ecc) ->
    case Ecc of
        medium ->
            {ok, nil};

        high ->
            {ok, nil};

        _ ->
            {error,
                {incompatible_options,
                    <<"rMQR only supports M or H error correction levels"/utf8>>}}
    end.

-file("src/qrkit/internal/rmqr.gleam", 223).
?DOC(false).
-spec classify_char(binary()) -> qrkit@types:mode().
classify_char(Char) ->
    case qrkit@internal@mode:is_numeric_char(Char) of
        true ->
            numeric;

        false ->
            case qrkit@internal@mode:is_alphanumeric_char(Char) of
                true ->
                    alphanumeric;

                false ->
                    case qrkit@internal@mode:is_kanji_char(Char) of
                        true ->
                            kanji;

                        false ->
                            byte
                    end
            end
    end.

-file("src/qrkit/internal/rmqr.gleam", 238).
?DOC(false).
-spec refine_mode(qrkit@types:mode(), qrkit@types:mode()) -> qrkit@types:mode().
refine_mode(Current, Next) ->
    case {Current, Next} of
        {byte, _} ->
            byte;

        {_, byte} ->
            byte;

        {kanji, _} ->
            byte;

        {_, kanji} ->
            byte;

        {alphanumeric, numeric} ->
            alphanumeric;

        {numeric, alphanumeric} ->
            alphanumeric;

        {_, _} ->
            Next
    end.

-file("src/qrkit/internal/rmqr.gleam", 216).
?DOC(false).
-spec uniform_mode(list(binary()), qrkit@types:mode()) -> qrkit@types:mode().
uniform_mode(Chars, Best) ->
    case Chars of
        [] ->
            Best;

        [Char | Rest] ->
            uniform_mode(Rest, refine_mode(Best, classify_char(Char)))
    end.

-file("src/qrkit/internal/rmqr.gleam", 206).
?DOC(false).
-spec select_mode(binary(), qrkit@types:mode_preference()) -> {ok,
        qrkit@types:mode()} |
    {error, qrkit@error:encode_error()}.
select_mode(Text, Preference) ->
    case Preference of
        force_byte ->
            {ok, byte};

        auto ->
            {ok, uniform_mode(qrkit@internal@util:characters(Text), numeric)}
    end.

-file("src/qrkit/internal/rmqr.gleam", 291).
?DOC(false).
-spec lookup_int(list(integer()), integer()) -> integer().
lookup_int(Table, Index) ->
    qrkit@internal@util:at_or(Table, Index, 0).

-file("src/qrkit/internal/rmqr.gleam", 295).
?DOC(false).
-spec mode_indicator(qrkit@types:mode()) -> integer().
mode_indicator(Selected_mode) ->
    case Selected_mode of
        numeric ->
            2#001;

        alphanumeric ->
            2#010;

        byte ->
            2#011;

        kanji ->
            2#100
    end.

-file("src/qrkit/internal/rmqr.gleam", 334).
?DOC(false).
-spec append_terminator(qrkit@internal@bitstream:bit_stream(), integer()) -> qrkit@internal@bitstream:bit_stream().
append_terminator(Stream, Capacity) ->
    Remaining = Capacity - qrkit@internal@bitstream:length_bits(Stream),
    Bits = case Remaining < 3 of
        true ->
            Remaining;

        false ->
            3
    end,
    case Bits =< 0 of
        true ->
            Stream;

        false ->
            qrkit@internal@bitstream:append_bits(Stream, 0, Bits)
    end.

-file("src/qrkit/internal/rmqr.gleam", 356).
?DOC(false).
-spec do_pad_to_data(
    qrkit@internal@bitstream:bit_stream(),
    integer(),
    integer()
) -> qrkit@internal@bitstream:bit_stream().
do_pad_to_data(Stream, Data_bytes, Index) ->
    Current = erlang:length(qrkit@internal@bitstream:to_byte_list(Stream)),
    case Current >= Data_bytes of
        true ->
            Stream;

        false ->
            Byte = case (Index rem 2) =:= 0 of
                true ->
                    16#EC;

                false ->
                    16#11
            end,
            do_pad_to_data(
                qrkit@internal@bitstream:append_byte(Stream, Byte),
                Data_bytes,
                Index + 1
            )
    end.

-file("src/qrkit/internal/rmqr.gleam", 349).
?DOC(false).
-spec pad_to_data(qrkit@internal@bitstream:bit_stream(), integer()) -> qrkit@internal@bitstream:bit_stream().
pad_to_data(Stream, Data_bytes) ->
    do_pad_to_data(Stream, Data_bytes, 0).

-file("src/qrkit/internal/rmqr.gleam", 397).
?DOC(false).
-spec draw_timing_borders(qrkit@internal@matrix:matrix(), integer(), integer()) -> qrkit@internal@matrix:matrix().
draw_timing_borders(Target, H_size, V_size) ->
    Top_bottom = begin
        _pipe = qrkit@internal@util:range(0, H_size - 1),
        gleam@list:fold(
            _pipe,
            Target,
            fun(Acc, Col) ->
                Dark = (Col rem 2) =:= 0,
                _pipe@1 = Acc,
                _pipe@2 = qrkit@internal@matrix:set(_pipe@1, 0, Col, Dark, true),
                qrkit@internal@matrix:set(_pipe@2, V_size - 1, Col, Dark, true)
            end
        )
    end,
    _pipe@3 = qrkit@internal@util:range(0, V_size - 1),
    gleam@list:fold(
        _pipe@3,
        Top_bottom,
        fun(Acc@1, Row) ->
            Dark@1 = (Row rem 2) =:= 0,
            _pipe@4 = Acc@1,
            _pipe@5 = qrkit@internal@matrix:set(_pipe@4, Row, 0, Dark@1, true),
            qrkit@internal@matrix:set(_pipe@5, Row, H_size - 1, Dark@1, true)
        end
    ).

-file("src/qrkit/internal/rmqr.gleam", 419).
?DOC(false).
-spec draw_top_left_finder(qrkit@internal@matrix:matrix()) -> qrkit@internal@matrix:matrix().
draw_top_left_finder(Target) ->
    _pipe = qrkit@internal@util:range(0, 6),
    gleam@list:fold(
        _pipe,
        Target,
        fun(Acc, Row) -> _pipe@1 = qrkit@internal@util:range(0, 6),
            gleam@list:fold(
                _pipe@1,
                Acc,
                fun(Acc2, Col) ->
                    Dark = ((((Row =:= 0) orelse (Row =:= 6)) orelse (Col =:= 0))
                    orelse (Col =:= 6))
                    orelse ((((Row >= 2) andalso (Row =< 4)) andalso (Col >= 2))
                    andalso (Col =< 4)),
                    qrkit@internal@matrix:set(Acc2, Row, Col, Dark, true)
                end
            ) end
    ).

-file("src/qrkit/internal/rmqr.gleam", 435).
?DOC(false).
-spec draw_bottom_right_subfinder(
    qrkit@internal@matrix:matrix(),
    integer(),
    integer()
) -> qrkit@internal@matrix:matrix().
draw_bottom_right_subfinder(Target, H_size, V_size) ->
    _pipe = qrkit@internal@util:range(0, 4),
    gleam@list:fold(
        _pipe,
        Target,
        fun(Acc, Row) -> _pipe@1 = qrkit@internal@util:range(0, 4),
            gleam@list:fold(
                _pipe@1,
                Acc,
                fun(Acc2, Col) ->
                    Dark = ((((Row =:= 0) orelse (Row =:= 4)) orelse (Col =:= 0))
                    orelse (Col =:= 4))
                    orelse ((Row =:= 2) andalso (Col =:= 2)),
                    qrkit@internal@matrix:set(
                        Acc2,
                        (V_size - 5) + Row,
                        (H_size - 5) + Col,
                        Dark,
                        true
                    )
                end
            ) end
    ).

-file("src/qrkit/internal/rmqr.gleam", 451).
?DOC(false).
-spec draw_top_right_corner(qrkit@internal@matrix:matrix(), integer()) -> qrkit@internal@matrix:matrix().
draw_top_right_corner(Target, H_size) ->
    _pipe = Target,
    _pipe@1 = qrkit@internal@matrix:set(_pipe, 0, H_size - 2, true, true),
    _pipe@2 = qrkit@internal@matrix:set(_pipe@1, 1, H_size - 2, false, true),
    qrkit@internal@matrix:set(_pipe@2, 1, H_size - 1, true, true).

-file("src/qrkit/internal/rmqr.gleam", 458).
?DOC(false).
-spec draw_bottom_left_corner(qrkit@internal@matrix:matrix(), integer()) -> qrkit@internal@matrix:matrix().
draw_bottom_left_corner(Target, V_size) ->
    _pipe = Target,
    _pipe@1 = qrkit@internal@matrix:set(_pipe, V_size - 2, 0, true, true),
    _pipe@2 = qrkit@internal@matrix:set(_pipe@1, V_size - 2, 1, false, true),
    qrkit@internal@matrix:set(_pipe@2, V_size - 1, 1, true, true).

-file("src/qrkit/internal/rmqr.gleam", 465).
?DOC(false).
-spec draw_separator(qrkit@internal@matrix:matrix(), integer(), integer()) -> qrkit@internal@matrix:matrix().
draw_separator(Target, H_size, V_size) ->
    With_right = begin
        _pipe = qrkit@internal@util:range(0, 6),
        gleam@list:fold(
            _pipe,
            Target,
            fun(Acc, Row) ->
                qrkit@internal@matrix:set(Acc, Row, 7, false, true)
            end
        )
    end,
    case V_size > 7 of
        false ->
            With_right;

        true ->
            _pipe@1 = qrkit@internal@util:range(0, 7),
            gleam@list:fold(
                _pipe@1,
                With_right,
                fun(Acc@1, Col) -> case Col >= H_size of
                        true ->
                            Acc@1;

                        false ->
                            qrkit@internal@matrix:set(
                                Acc@1,
                                7,
                                Col,
                                false,
                                true
                            )
                    end end
            )
    end.

-file("src/qrkit/internal/rmqr.gleam", 504).
?DOC(false).
-spec alignment_row_for_width(integer()) -> {ok, integer()} | {error, nil}.
alignment_row_for_width(H_size) ->
    case H_size of
        43 ->
            {ok, 0};

        59 ->
            {ok, 1};

        77 ->
            {ok, 2};

        99 ->
            {ok, 3};

        139 ->
            {ok, 4};

        _ ->
            {error, nil}
    end.

-file("src/qrkit/internal/rmqr.gleam", 541).
?DOC(false).
-spec draw_alignment_column(
    qrkit@internal@matrix:matrix(),
    integer(),
    integer(),
    integer()
) -> qrkit@internal@matrix:matrix().
draw_alignment_column(Target, Column, _, V_size) ->
    With_line = begin
        _pipe = qrkit@internal@util:range(0, V_size - 1),
        gleam@list:fold(
            _pipe,
            Target,
            fun(Acc, Row) ->
                Dark = (Row rem 2) =:= 0,
                qrkit@internal@matrix:set(Acc, Row, Column, Dark, true)
            end
        )
    end,
    _pipe@1 = With_line,
    _pipe@2 = qrkit@internal@matrix:set(_pipe@1, 1, Column - 1, true, true),
    _pipe@3 = qrkit@internal@matrix:set(_pipe@2, 2, Column - 1, true, true),
    _pipe@4 = qrkit@internal@matrix:set(_pipe@3, 1, Column + 1, true, true),
    _pipe@5 = qrkit@internal@matrix:set(_pipe@4, 2, Column + 1, true, true),
    _pipe@6 = qrkit@internal@matrix:set(
        _pipe@5,
        V_size - 3,
        Column - 1,
        true,
        true
    ),
    _pipe@7 = qrkit@internal@matrix:set(
        _pipe@6,
        V_size - 2,
        Column - 1,
        true,
        true
    ),
    _pipe@8 = qrkit@internal@matrix:set(
        _pipe@7,
        V_size - 3,
        Column + 1,
        true,
        true
    ),
    qrkit@internal@matrix:set(_pipe@8, V_size - 2, Column + 1, true, true).

-file("src/qrkit/internal/rmqr.gleam", 564).
?DOC(false).
-spec reserve_format_info(qrkit@internal@matrix:matrix(), integer(), integer()) -> qrkit@internal@matrix:matrix().
reserve_format_info(Target, H_size, V_size) ->
    Left_main = begin
        _pipe = qrkit@internal@util:range(0, 4),
        gleam@list:fold(
            _pipe,
            Target,
            fun(Acc_i, I) -> _pipe@1 = qrkit@internal@util:range(0, 2),
                gleam@list:fold(
                    _pipe@1,
                    Acc_i,
                    fun(Acc_j, J) ->
                        qrkit@internal@matrix:set(
                            Acc_j,
                            I + 1,
                            J + 8,
                            false,
                            true
                        )
                    end
                ) end
        )
    end,
    Left_extra = begin
        _pipe@2 = qrkit@internal@util:range(1, 3),
        gleam@list:fold(
            _pipe@2,
            Left_main,
            fun(Acc, Row) ->
                qrkit@internal@matrix:set(Acc, Row, 11, false, true)
            end
        )
    end,
    Right_main = begin
        _pipe@3 = qrkit@internal@util:range(0, 4),
        gleam@list:fold(
            _pipe@3,
            Left_extra,
            fun(Acc_i@1, I@1) -> _pipe@4 = qrkit@internal@util:range(0, 2),
                gleam@list:fold(
                    _pipe@4,
                    Acc_i@1,
                    fun(Acc_j@1, J@1) ->
                        qrkit@internal@matrix:set(
                            Acc_j@1,
                            (V_size - 6) + I@1,
                            (H_size - 8) + J@1,
                            false,
                            true
                        )
                    end
                ) end
        )
    end,
    _pipe@5 = qrkit@internal@util:range(0, 2),
    gleam@list:fold(
        _pipe@5,
        Right_main,
        fun(Acc@1, K) ->
            qrkit@internal@matrix:set(
                Acc@1,
                V_size - 6,
                (H_size - 5) + K,
                false,
                true
            )
        end
    ).

-file("src/qrkit/internal/rmqr.gleam", 630).
?DOC(false).
-spec power_of_two(integer()) -> integer().
power_of_two(Index) ->
    case Index =< 0 of
        true ->
            1;

        false ->
            2 * power_of_two(Index - 1)
    end.

-file("src/qrkit/internal/rmqr.gleam", 626).
?DOC(false).
-spec bit_at(integer(), integer()) -> boolean().
bit_at(Byte, Position) ->
    ((case power_of_two(Position) of
        0 -> 0;
        Gleam@denominator -> Byte div Gleam@denominator
    end) rem 2) =:= 1.

-file("src/qrkit/internal/rmqr.gleam", 608).
?DOC(false).
-spec codewords_to_bits(list(integer()), list(boolean())) -> list(boolean()).
codewords_to_bits(Codewords, Acc) ->
    case Codewords of
        [] ->
            lists:reverse(Acc);

        [Byte | Rest] ->
            codewords_to_bits(
                Rest,
                [bit_at(Byte, 0),
                    bit_at(Byte, 1),
                    bit_at(Byte, 2),
                    bit_at(Byte, 3),
                    bit_at(Byte, 4),
                    bit_at(Byte, 5),
                    bit_at(Byte, 6),
                    bit_at(Byte, 7) |
                    Acc]
            )
    end.

-file("src/qrkit/internal/rmqr.gleam", 669).
?DOC(false).
-spec try_place(
    qrkit@internal@matrix:matrix(),
    integer(),
    integer(),
    list({integer(), integer()}),
    integer()
) -> {list({integer(), integer()}), integer()}.
try_place(Target, Row, Col, Acc, Collected) ->
    case (Col < 0) orelse (Col >= qrkit@internal@matrix:width(Target)) of
        true ->
            {Acc, Collected};

        false ->
            case qrkit@internal@matrix:is_reserved(Target, Row, Col) of
                true ->
                    {Acc, Collected};

                false ->
                    {[{Row, Col} | Acc], Collected + 1}
            end
    end.

-file("src/qrkit/internal/rmqr.gleam", 686).
?DOC(false).
-spec advance(integer(), integer(), integer(), integer()) -> {integer(),
    integer(),
    integer()}.
advance(V_size, X, Y, Direction) ->
    case Direction of
        1 ->
            case Y =:= 0 of
                true ->
                    {X - 2, 0, 0};

                false ->
                    {X, Y - 1, 1}
            end;

        _ ->
            case Y =:= (V_size - 1) of
                true ->
                    {X - 2, V_size - 1, 1};

                false ->
                    {X, Y + 1, 0}
            end
    end.

-file("src/qrkit/internal/rmqr.gleam", 648).
?DOC(false).
-spec do_data_positions(
    qrkit@internal@matrix:matrix(),
    integer(),
    integer(),
    integer(),
    integer(),
    integer(),
    list({integer(), integer()})
) -> list({integer(), integer()}).
do_data_positions(Target, X, Y, Direction, Collected, Needed, Acc) ->
    case (Collected >= Needed) orelse (X < 0) of
        true ->
            lists:reverse(Acc);

        false ->
            {Acc1, Count1} = try_place(Target, Y, X + 1, Acc, Collected),
            {Acc2, Count2} = try_place(Target, Y, X, Acc1, Count1),
            {Next_x, Next_y, Next_dir} = advance(
                qrkit@internal@matrix:height(Target),
                X,
                Y,
                Direction
            ),
            do_data_positions(
                Target,
                Next_x,
                Next_y,
                Next_dir,
                Count2,
                Needed,
                Acc2
            )
    end.

-file("src/qrkit/internal/rmqr.gleam", 637).
?DOC(false).
-spec data_positions(
    qrkit@internal@matrix:matrix(),
    integer(),
    integer(),
    integer()
) -> list({integer(), integer()}).
data_positions(Target, H_size, V_size, Total_codewords) ->
    Bits_needed = Total_codewords * 8,
    Initial_x = H_size - 3,
    do_data_positions(Target, Initial_x, V_size - 1, 1, 0, Bits_needed, []).

-file("src/qrkit/internal/rmqr.gleam", 701).
?DOC(false).
-spec write_bits(
    qrkit@internal@matrix:matrix(),
    list({integer(), integer()}),
    list(boolean())
) -> qrkit@internal@matrix:matrix().
write_bits(Target, Positions, Bits) ->
    case {Positions, Bits} of
        {[{Row, Col} | Rest_positions], [Bit | Rest_bits]} ->
            write_bits(
                qrkit@internal@matrix:set(Target, Row, Col, Bit, false),
                Rest_positions,
                Rest_bits
            );

        {_, _} ->
            Target
    end.

-file("src/qrkit/internal/rmqr.gleam", 596).
?DOC(false).
-spec place_data(
    qrkit@internal@matrix:matrix(),
    integer(),
    integer(),
    integer(),
    list(integer())
) -> qrkit@internal@matrix:matrix().
place_data(Target, H_size, V_size, Total_codewords, Codewords) ->
    Bits = codewords_to_bits(Codewords, []),
    Positions = data_positions(Target, H_size, V_size, Total_codewords),
    write_bits(Target, Positions, Bits).

-file("src/qrkit/internal/rmqr.gleam", 721).
?DOC(false).
-spec do_apply_mask(qrkit@internal@matrix:matrix(), integer(), integer()) -> qrkit@internal@matrix:matrix().
do_apply_mask(Target, Row, Col) ->
    case Row >= qrkit@internal@matrix:height(Target) of
        true ->
            Target;

        false ->
            case Col >= qrkit@internal@matrix:width(Target) of
                true ->
                    do_apply_mask(Target, Row + 1, 0);

                false ->
                    case qrkit@internal@matrix:is_reserved(Target, Row, Col) of
                        true ->
                            do_apply_mask(Target, Row, Col + 1);

                        false ->
                            do_apply_mask(
                                qrkit@internal@matrix:'xor'(
                                    Target,
                                    Row,
                                    Col,
                                    (((Row div 2) + (Col div 3)) rem 2) =:= 0
                                ),
                                Row,
                                Col + 1
                            )
                    end
            end
    end.

-file("src/qrkit/internal/rmqr.gleam", 717).
?DOC(false).
-spec apply_fixed_mask(qrkit@internal@matrix:matrix()) -> qrkit@internal@matrix:matrix().
apply_fixed_mask(Target) ->
    do_apply_mask(Target, 0, 0).

-file("src/qrkit/internal/rmqr.gleam", 758).
?DOC(false).
-spec place_left_format(qrkit@internal@matrix:matrix(), integer()) -> qrkit@internal@matrix:matrix().
place_left_format(Target, Bits) ->
    Main = begin
        _pipe = qrkit@internal@util:range(0, 4),
        gleam@list:fold(
            _pipe,
            Target,
            fun(Acc_i, I) -> _pipe@1 = qrkit@internal@util:range(0, 2),
                gleam@list:fold(
                    _pipe@1,
                    Acc_i,
                    fun(Acc_j, J) ->
                        Dark = bit_at(Bits, (J * 5) + I),
                        qrkit@internal@matrix:set(
                            Acc_j,
                            I + 1,
                            J + 8,
                            Dark,
                            true
                        )
                    end
                ) end
        )
    end,
    _pipe@2 = Main,
    _pipe@3 = qrkit@internal@matrix:set(_pipe@2, 1, 11, bit_at(Bits, 15), true),
    _pipe@4 = qrkit@internal@matrix:set(_pipe@3, 2, 11, bit_at(Bits, 16), true),
    qrkit@internal@matrix:set(_pipe@4, 3, 11, bit_at(Bits, 17), true).

-file("src/qrkit/internal/rmqr.gleam", 774).
?DOC(false).
-spec place_right_format(
    qrkit@internal@matrix:matrix(),
    integer(),
    integer(),
    integer()
) -> qrkit@internal@matrix:matrix().
place_right_format(Target, Bits, H_size, V_size) ->
    Main = begin
        _pipe = qrkit@internal@util:range(0, 4),
        gleam@list:fold(
            _pipe,
            Target,
            fun(Acc_i, I) -> _pipe@1 = qrkit@internal@util:range(0, 2),
                gleam@list:fold(
                    _pipe@1,
                    Acc_i,
                    fun(Acc_j, J) ->
                        Dark = bit_at(Bits, (J * 5) + I),
                        qrkit@internal@matrix:set(
                            Acc_j,
                            (V_size - 6) + I,
                            (H_size - 8) + J,
                            Dark,
                            true
                        )
                    end
                ) end
        )
    end,
    _pipe@2 = Main,
    _pipe@3 = qrkit@internal@matrix:set(
        _pipe@2,
        V_size - 6,
        H_size - 5,
        bit_at(Bits, 15),
        true
    ),
    _pipe@4 = qrkit@internal@matrix:set(
        _pipe@3,
        V_size - 6,
        H_size - 4,
        bit_at(Bits, 16),
        true
    ),
    qrkit@internal@matrix:set(
        _pipe@4,
        V_size - 6,
        H_size - 3,
        bit_at(Bits, 17),
        true
    ).

-file("src/qrkit/internal/rmqr.gleam", 795).
?DOC(false).
-spec result_try(
    {ok, ENZ} | {error, qrkit@error:encode_error()},
    fun((ENZ) -> {ok, EOC} | {error, qrkit@error:encode_error()})
) -> {ok, EOC} | {error, qrkit@error:encode_error()}.
result_try(Result, Callback) ->
    case Result of
        {ok, Value} ->
            Callback(Value);

        {error, Error} ->
            {error, Error}
    end.

-file("src/qrkit/internal/rmqr.gleam", 189).
?DOC(false).
-spec dimensions(integer()) -> {ok, {integer(), integer()}} |
    {error, qrkit@error:encode_error()}.
dimensions(Index) ->
    case (Index >= 0) andalso (Index < 32) of
        true ->
            {ok,
                {lookup_int(
                        [43,
                            59,
                            77,
                            99,
                            139,
                            43,
                            59,
                            77,
                            99,
                            139,
                            27,
                            43,
                            59,
                            77,
                            99,
                            139,
                            27,
                            43,
                            59,
                            77,
                            99,
                            139,
                            43,
                            59,
                            77,
                            99,
                            139,
                            43,
                            59,
                            77,
                            99,
                            139],
                        Index
                    ),
                    lookup_int(
                        [7,
                            7,
                            7,
                            7,
                            7,
                            9,
                            9,
                            9,
                            9,
                            9,
                            11,
                            11,
                            11,
                            11,
                            11,
                            11,
                            13,
                            13,
                            13,
                            13,
                            13,
                            13,
                            15,
                            15,
                            15,
                            15,
                            15,
                            17,
                            17,
                            17,
                            17,
                            17],
                        Index
                    )}};

        false ->
            {error, {invalid_version, Index + 1}}
    end.

-file("src/qrkit/internal/rmqr.gleam", 275).
?DOC(false).
-spec data_codewords(integer(), qrkit@types:error_correction()) -> integer().
data_codewords(Index, Ecc) ->
    case Ecc of
        high ->
            lookup_int(
                [3,
                    7,
                    10,
                    14,
                    24,
                    7,
                    11,
                    17,
                    22,
                    33,
                    5,
                    11,
                    15,
                    23,
                    29,
                    42,
                    7,
                    13,
                    20,
                    29,
                    35,
                    54,
                    15,
                    26,
                    31,
                    48,
                    69,
                    21,
                    28,
                    38,
                    56,
                    76],
                Index
            );

        _ ->
            lookup_int(
                [6,
                    12,
                    20,
                    28,
                    44,
                    12,
                    21,
                    31,
                    42,
                    63,
                    7,
                    19,
                    31,
                    43,
                    57,
                    84,
                    12,
                    27,
                    38,
                    53,
                    73,
                    106,
                    33,
                    48,
                    67,
                    88,
                    127,
                    39,
                    56,
                    78,
                    100,
                    152],
                Index
            )
    end.

-file("src/qrkit/internal/rmqr.gleam", 271).
?DOC(false).
-spec data_capacity_bits(integer(), qrkit@types:error_correction()) -> integer().
data_capacity_bits(Index, Ecc) ->
    data_codewords(Index, Ecc) * 8.

-file("src/qrkit/internal/rmqr.gleam", 282).
?DOC(false).
-spec lookup_cci(qrkit@types:mode(), integer()) -> integer().
lookup_cci(Selected_mode, Index) ->
    case Selected_mode of
        numeric ->
            lookup_int(
                [4,
                    5,
                    6,
                    7,
                    7,
                    5,
                    6,
                    7,
                    7,
                    8,
                    4,
                    6,
                    7,
                    7,
                    8,
                    8,
                    5,
                    6,
                    7,
                    7,
                    8,
                    8,
                    7,
                    7,
                    8,
                    8,
                    9,
                    7,
                    8,
                    8,
                    8,
                    9],
                Index
            );

        alphanumeric ->
            lookup_int(
                [3,
                    5,
                    5,
                    6,
                    6,
                    5,
                    5,
                    6,
                    6,
                    7,
                    4,
                    5,
                    6,
                    6,
                    7,
                    7,
                    5,
                    6,
                    6,
                    7,
                    7,
                    8,
                    6,
                    7,
                    7,
                    7,
                    8,
                    6,
                    7,
                    7,
                    8,
                    8],
                Index
            );

        byte ->
            lookup_int(
                [3,
                    4,
                    5,
                    5,
                    6,
                    4,
                    5,
                    5,
                    6,
                    6,
                    3,
                    5,
                    5,
                    6,
                    6,
                    7,
                    4,
                    5,
                    6,
                    6,
                    7,
                    7,
                    6,
                    6,
                    7,
                    7,
                    7,
                    6,
                    6,
                    7,
                    7,
                    8],
                Index
            );

        kanji ->
            lookup_int(
                [2,
                    3,
                    4,
                    5,
                    5,
                    3,
                    4,
                    5,
                    5,
                    6,
                    2,
                    4,
                    5,
                    5,
                    6,
                    6,
                    3,
                    5,
                    5,
                    6,
                    6,
                    7,
                    5,
                    5,
                    6,
                    6,
                    7,
                    5,
                    6,
                    6,
                    6,
                    7],
                Index
            )
    end.

-file("src/qrkit/internal/rmqr.gleam", 173).
?DOC(false).
-spec check_version(
    binary(),
    qrkit@types:mode(),
    qrkit@types:error_correction(),
    integer()
) -> {ok, integer()} | {error, qrkit@error:encode_error()}.
check_version(Text, Selected_mode, Ecc, Candidate) ->
    Count_bits = lookup_cci(Selected_mode, Candidate),
    Data_bits = (3 + Count_bits) + qrkit@internal@mode:data_bits_length(
        Text,
        Selected_mode
    ),
    Capacity = data_capacity_bits(Candidate, Ecc),
    case Data_bits =< Capacity of
        true ->
            {ok, Candidate};

        false ->
            {error, {data_exceeds_capacity, Data_bits, Capacity}}
    end.

-file("src/qrkit/internal/rmqr.gleam", 250).
?DOC(false).
-spec find_version(
    binary(),
    qrkit@types:mode(),
    qrkit@types:error_correction(),
    integer()
) -> {ok, integer()} | {error, qrkit@error:encode_error()}.
find_version(Text, Selected_mode, Ecc, Candidate) ->
    case Candidate >= 32 of
        true ->
            {error, {data_exceeds_capacity, 0, 0}};

        false ->
            Count_bits = lookup_cci(Selected_mode, Candidate),
            Data_bits = (3 + Count_bits) + qrkit@internal@mode:data_bits_length(
                Text,
                Selected_mode
            ),
            Capacity = data_capacity_bits(Candidate, Ecc),
            case Data_bits =< Capacity of
                true ->
                    {ok, Candidate};

                false ->
                    find_version(Text, Selected_mode, Ecc, Candidate + 1)
            end
    end.

-file("src/qrkit/internal/rmqr.gleam", 157).
?DOC(false).
-spec resolve_version(
    binary(),
    qrkit@types:mode(),
    qrkit@types:error_correction(),
    gleam@option:option(integer())
) -> {ok, integer()} | {error, qrkit@error:encode_error()}.
resolve_version(Text, Selected_mode, Ecc, Requested_version) ->
    case Requested_version of
        none ->
            find_version(Text, Selected_mode, Ecc, 0);

        {some, Value} ->
            case (Value < 1) orelse (Value > 32) of
                true ->
                    {error, {invalid_version, Value}};

                false ->
                    check_version(Text, Selected_mode, Ecc, Value - 1)
            end
    end.

-file("src/qrkit/internal/rmqr.gleam", 304).
?DOC(false).
-spec create_codewords(
    binary(),
    qrkit@types:mode(),
    qrkit@types:error_correction(),
    integer()
) -> {ok, list(integer())} | {error, qrkit@error:encode_error()}.
create_codewords(Text, Selected_mode, Ecc, Index) ->
    Count_bits = lookup_cci(Selected_mode, Index),
    Count_value = qrkit@internal@mode:character_count(Text, Selected_mode),
    result_try(
        qrkit@internal@mode:encode(Text, Selected_mode, 0),
        fun(Payload) ->
            Capacity = data_capacity_bits(Index, Ecc),
            Stream = begin
                _pipe = qrkit@internal@bitstream:new(),
                _pipe@1 = qrkit@internal@bitstream:append_bits(
                    _pipe,
                    mode_indicator(Selected_mode),
                    3
                ),
                _pipe@2 = qrkit@internal@bitstream:append_bits(
                    _pipe@1,
                    Count_value,
                    Count_bits
                ),
                _pipe@3 = qrkit@internal@bitstream:append_bytes(
                    _pipe@2,
                    Payload
                ),
                append_terminator(_pipe@3, Capacity)
            end,
            case qrkit@internal@bitstream:length_bits(Stream) > Capacity of
                true ->
                    {error,
                        {data_exceeds_capacity,
                            qrkit@internal@bitstream:length_bits(Stream),
                            Capacity}};

                false ->
                    Aligned = qrkit@internal@bitstream:pad_to_byte_boundary(
                        Stream
                    ),
                    Padded = pad_to_data(Aligned, data_codewords(Index, Ecc)),
                    Data_bytes = qrkit@internal@bitstream:to_byte_list(Padded),
                    Total = lookup_int(
                        [13,
                            21,
                            32,
                            44,
                            68,
                            21,
                            33,
                            49,
                            66,
                            99,
                            15,
                            31,
                            47,
                            67,
                            89,
                            132,
                            21,
                            41,
                            60,
                            85,
                            113,
                            166,
                            51,
                            74,
                            103,
                            136,
                            199,
                            61,
                            88,
                            122,
                            160,
                            232],
                        Index
                    ),
                    Ec_count = Total - data_codewords(Index, Ecc),
                    Ec_bytes = qrkit@internal@reed_solomon:encode(
                        Data_bytes,
                        Ec_count
                    ),
                    {ok, lists:append(Data_bytes, Ec_bytes)}
            end
        end
    ).

-file("src/qrkit/internal/rmqr.gleam", 741).
?DOC(false).
-spec place_format_info(
    qrkit@internal@matrix:matrix(),
    integer(),
    qrkit@types:error_correction(),
    integer(),
    integer()
) -> qrkit@internal@matrix:matrix().
place_format_info(Target, Index, Ecc, H_size, V_size) ->
    Table_index = case Ecc of
        high ->
            Index + 32;

        _ ->
            Index
    end,
    Left = lookup_int(
        [16#1FAB2,
            16#1E597,
            16#1DBDD,
            16#1C4F8,
            16#1B86C,
            16#1A749,
            16#19903,
            16#18626,
            16#17F0E,
            16#1602B,
            16#15E61,
            16#14144,
            16#13DD0,
            16#122F5,
            16#11CBF,
            16#1039A,
            16#0F1CA,
            16#0EEEF,
            16#0D0A5,
            16#0CF80,
            16#0B314,
            16#0AC31,
            16#0927B,
            16#08D5E,
            16#07476,
            16#06B53,
            16#05519,
            16#04A3C,
            16#036A8,
            16#0298D,
            16#017C7,
            16#008E2,
            16#3F367,
            16#3EC42,
            16#3D208,
            16#3CD2D,
            16#3B1B9,
            16#3AE9C,
            16#390D6,
            16#38FF3,
            16#376DB,
            16#369FE,
            16#357B4,
            16#34891,
            16#33405,
            16#32B20,
            16#3156A,
            16#30A4F,
            16#2F81F,
            16#2E73A,
            16#2D970,
            16#2C655,
            16#2BAC1,
            16#2A5E4,
            16#29BAE,
            16#2848B,
            16#27DA3,
            16#26286,
            16#25CCC,
            16#243E9,
            16#23F7D,
            16#22058,
            16#21E12,
            16#20137],
        Table_index
    ),
    Right = lookup_int(
        [16#20A7B,
            16#2155E,
            16#22B14,
            16#23431,
            16#248A5,
            16#25780,
            16#269CA,
            16#276EF,
            16#28FC7,
            16#290E2,
            16#2AEA8,
            16#2B18D,
            16#2CD19,
            16#2D23C,
            16#2EC76,
            16#2F353,
            16#30103,
            16#31E26,
            16#3206C,
            16#33F49,
            16#343DD,
            16#35CF8,
            16#362B2,
            16#37D97,
            16#384BF,
            16#39B9A,
            16#3A5D0,
            16#3BAF5,
            16#3C661,
            16#3D944,
            16#3E70E,
            16#3F82B,
            16#003AE,
            16#01C8B,
            16#022C1,
            16#03DE4,
            16#04170,
            16#05E55,
            16#0601F,
            16#07F3A,
            16#08612,
            16#09937,
            16#0A77D,
            16#0B858,
            16#0C4CC,
            16#0DBE9,
            16#0E5A3,
            16#0FA86,
            16#108D6,
            16#117F3,
            16#129B9,
            16#1369C,
            16#14A08,
            16#1552D,
            16#16B67,
            16#17442,
            16#18D6A,
            16#1924F,
            16#1AC05,
            16#1B320,
            16#1CFB4,
            16#1D091,
            16#1EEDB,
            16#1F1FE],
        Table_index
    ),
    With_left = place_left_format(Target, Left),
    place_right_format(With_left, Right, H_size, V_size).

-file("src/qrkit/internal/rmqr.gleam", 515).
?DOC(false).
-spec do_draw_alignment_columns(
    qrkit@internal@matrix:matrix(),
    integer(),
    integer(),
    integer(),
    integer()
) -> qrkit@internal@matrix:matrix().
do_draw_alignment_columns(Target, H_size, V_size, H_version, Index) ->
    case Index >= 4 of
        true ->
            Target;

        false ->
            Column = lookup_int(
                [21,
                    0,
                    0,
                    0,
                    19,
                    39,
                    0,
                    0,
                    25,
                    51,
                    0,
                    0,
                    23,
                    49,
                    75,
                    0,
                    27,
                    55,
                    83,
                    111],
                (H_version * 4) + Index
            ),
            case Column of
                0 ->
                    Target;

                _ ->
                    do_draw_alignment_columns(
                        draw_alignment_column(Target, Column, H_size, V_size),
                        H_size,
                        V_size,
                        H_version,
                        Index + 1
                    )
            end
    end.

-file("src/qrkit/internal/rmqr.gleam", 488).
?DOC(false).
-spec draw_alignment_patterns(
    qrkit@internal@matrix:matrix(),
    integer(),
    integer()
) -> qrkit@internal@matrix:matrix().
draw_alignment_patterns(Target, H_size, V_size) ->
    case H_size > 27 of
        false ->
            Target;

        true ->
            case alignment_row_for_width(H_size) of
                {error, _} ->
                    Target;

                {ok, H_version} ->
                    do_draw_alignment_columns(
                        Target,
                        H_size,
                        V_size,
                        H_version,
                        0
                    )
            end
    end.

-file("src/qrkit/internal/rmqr.gleam", 374).
?DOC(false).
-spec build_matrix(
    integer(),
    qrkit@types:error_correction(),
    integer(),
    integer(),
    integer(),
    list(integer())
) -> qrkit@internal@matrix:matrix().
build_matrix(Index, Ecc, H_size, V_size, Total_codewords, Codewords) ->
    Base = begin
        _pipe = qrkit@internal@matrix:new(H_size, V_size),
        _pipe@1 = draw_timing_borders(_pipe, H_size, V_size),
        _pipe@2 = draw_top_left_finder(_pipe@1),
        _pipe@3 = draw_bottom_right_subfinder(_pipe@2, H_size, V_size),
        _pipe@4 = draw_top_right_corner(_pipe@3, H_size),
        _pipe@5 = draw_bottom_left_corner(_pipe@4, V_size),
        _pipe@6 = draw_separator(_pipe@5, H_size, V_size),
        _pipe@7 = draw_alignment_patterns(_pipe@6, H_size, V_size),
        reserve_format_info(_pipe@7, H_size, V_size)
    end,
    Placed = place_data(Base, H_size, V_size, Total_codewords, Codewords),
    Masked = apply_fixed_mask(Placed),
    place_format_info(Masked, Index, Ecc, H_size, V_size).

-file("src/qrkit/internal/rmqr.gleam", 135).
?DOC(false).
-spec encode(
    binary(),
    qrkit@types:error_correction(),
    gleam@option:option(integer()),
    qrkit@types:mode_preference()
) -> {ok, encoded()} | {error, qrkit@error:encode_error()}.
encode(Text, Ecc, Requested_version, Preference) ->
    result_try(
        validate_ecc(Ecc),
        fun(_) ->
            result_try(
                select_mode(Text, Preference),
                fun(Selected_mode) ->
                    result_try(
                        resolve_version(
                            Text,
                            Selected_mode,
                            Ecc,
                            Requested_version
                        ),
                        fun(Chosen) ->
                            result_try(
                                create_codewords(
                                    Text,
                                    Selected_mode,
                                    Ecc,
                                    Chosen
                                ),
                                fun(Codewords) ->
                                    H_size = lookup_int(
                                        [43,
                                            59,
                                            77,
                                            99,
                                            139,
                                            43,
                                            59,
                                            77,
                                            99,
                                            139,
                                            27,
                                            43,
                                            59,
                                            77,
                                            99,
                                            139,
                                            27,
                                            43,
                                            59,
                                            77,
                                            99,
                                            139,
                                            43,
                                            59,
                                            77,
                                            99,
                                            139,
                                            43,
                                            59,
                                            77,
                                            99,
                                            139],
                                        Chosen
                                    ),
                                    V_size = lookup_int(
                                        [7,
                                            7,
                                            7,
                                            7,
                                            7,
                                            9,
                                            9,
                                            9,
                                            9,
                                            9,
                                            11,
                                            11,
                                            11,
                                            11,
                                            11,
                                            11,
                                            13,
                                            13,
                                            13,
                                            13,
                                            13,
                                            13,
                                            15,
                                            15,
                                            15,
                                            15,
                                            15,
                                            17,
                                            17,
                                            17,
                                            17,
                                            17],
                                        Chosen
                                    ),
                                    Total = lookup_int(
                                        [13,
                                            21,
                                            32,
                                            44,
                                            68,
                                            21,
                                            33,
                                            49,
                                            66,
                                            99,
                                            15,
                                            31,
                                            47,
                                            67,
                                            89,
                                            132,
                                            21,
                                            41,
                                            60,
                                            85,
                                            113,
                                            166,
                                            51,
                                            74,
                                            103,
                                            136,
                                            199,
                                            61,
                                            88,
                                            122,
                                            160,
                                            232],
                                        Chosen
                                    ),
                                    Final_matrix = build_matrix(
                                        Chosen,
                                        Ecc,
                                        H_size,
                                        V_size,
                                        Total,
                                        Codewords
                                    ),
                                    {ok,
                                        {encoded,
                                            Chosen + 1,
                                            H_size,
                                            V_size,
                                            qrkit@internal@matrix:rows(
                                                Final_matrix
                                            )}}
                                end
                            )
                        end
                    )
                end
            )
        end
    ).