-module(qrkit@internal@structured_append).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/qrkit/internal/structured_append.gleam").
-export([parity_of/1, encode/3]).
-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).
-file("src/qrkit/internal/structured_append.gleam", 45).
?DOC(false).
-spec parity_of_bits(bitstring(), integer()) -> integer().
parity_of_bits(Bytes, Acc) ->
case Bytes of
<<>> ->
Acc;
<<Byte:8, Rest/bitstring>> ->
parity_of_bits(Rest, erlang:'bxor'(Acc, Byte));
_ ->
Acc
end.
-file("src/qrkit/internal/structured_append.gleam", 41).
?DOC(false).
-spec parity_of(binary()) -> integer().
parity_of(Data) ->
parity_of_bits(gleam_stdlib:identity(Data), 0).
-file("src/qrkit/internal/structured_append.gleam", 136).
?DOC(false).
-spec build_header(integer(), integer(), integer()) -> bitstring().
build_header(Index, Total, Parity) ->
_pipe = qrkit@internal@bitstream:new(),
_pipe@1 = qrkit@internal@bitstream:append_bits(_pipe, 2#0011, 4),
_pipe@2 = qrkit@internal@bitstream:append_bits(_pipe@1, Index, 4),
_pipe@3 = qrkit@internal@bitstream:append_bits(_pipe@2, Total - 1, 4),
_pipe@4 = qrkit@internal@bitstream:append_bits(_pipe@3, Parity, 8),
qrkit@internal@bitstream:to_bit_array(_pipe@4).
-file("src/qrkit/internal/structured_append.gleam", 103).
?DOC(false).
-spec encode_multiple_shards(
list(binary()),
binary(),
integer(),
integer(),
qrkit@types:error_correction(),
integer(),
list(qrkit@internal@standard:encoded())
) -> {ok, list(qrkit@internal@standard:encoded())} |
{error, qrkit@error:encode_error()}.
encode_multiple_shards(Chunks, Data, Total, Max_version, Ecc, Index, Acc) ->
case Chunks of
[] ->
{ok, lists:reverse(Acc)};
[Chunk | Rest] ->
Parity = parity_of(Data),
Header = build_header(Index, Total, Parity),
case qrkit@internal@standard:encode_prefixed(
Chunk,
Ecc,
1,
Max_version,
none,
auto,
Header
) of
{ok, Encoded} ->
encode_multiple_shards(
Rest,
Data,
Total,
Max_version,
Ecc,
Index + 1,
[Encoded | Acc]
);
{error, Error} ->
{error, Error}
end
end.
-file("src/qrkit/internal/structured_append.gleam", 72).
?DOC(false).
-spec encode_shards(
list(binary()),
binary(),
integer(),
integer(),
qrkit@types:error_correction()
) -> {ok, list(qrkit@internal@standard:encoded())} |
{error, qrkit@error:encode_error()}.
encode_shards(Chunks, Data, Total, Max_version, Ecc) ->
case Total of
1 ->
case Chunks of
[Chunk] ->
case qrkit@internal@standard:encode_prefixed(
Chunk,
Ecc,
1,
Max_version,
none,
auto,
<<>>
) of
{ok, Encoded} ->
{ok, [Encoded]};
{error, Error} ->
{error, Error}
end;
_ ->
{error, empty_input}
end;
_ ->
encode_multiple_shards(Chunks, Data, Total, Max_version, Ecc, 0, [])
end.
-file("src/qrkit/internal/structured_append.gleam", 171).
?DOC(false).
-spec take_chars(list(binary()), integer(), list(binary())) -> {list(binary()),
list(binary())}.
take_chars(Chars, Count, Acc) ->
case {Chars, Count} of
{Rest, 0} ->
{lists:reverse(Acc), Rest};
{[], _} ->
{lists:reverse(Acc), []};
{[First | Rest@1], _} ->
take_chars(Rest@1, Count - 1, [First | Acc])
end.
-file("src/qrkit/internal/structured_append.gleam", 183).
?DOC(false).
-spec ceil_div(integer(), integer()) -> integer().
ceil_div(Numerator, Denominator) ->
case Denominator =< 0 of
true ->
Numerator;
false ->
case Denominator of
0 -> 0;
Gleam@denominator -> ((Numerator + Denominator) - 1) div Gleam@denominator
end
end.
-file("src/qrkit/internal/structured_append.gleam", 151).
?DOC(false).
-spec do_split(list(binary()), integer(), integer(), list(binary())) -> list(binary()).
do_split(Chars, Remaining_parts, Remaining_chars, Acc) ->
case Remaining_parts of
0 ->
lists:reverse(Acc);
1 ->
lists:reverse([erlang:list_to_binary(Chars) | Acc]);
_ ->
Take_count = ceil_div(Remaining_chars, Remaining_parts),
{Taken, Rest} = take_chars(Chars, Take_count, []),
do_split(
Rest,
Remaining_parts - 1,
Remaining_chars - Take_count,
[erlang:list_to_binary(Taken) | Acc]
)
end.
-file("src/qrkit/internal/structured_append.gleam", 145).
?DOC(false).
-spec split_string(binary(), integer()) -> list(binary()).
split_string(Data, Parts) ->
Chars = qrkit@internal@util:characters(Data),
Total_chars = erlang:length(Chars),
do_split(Chars, Parts, Total_chars, []).
-file("src/qrkit/internal/structured_append.gleam", 54).
?DOC(false).
-spec find_split(binary(), integer(), qrkit@types:error_correction(), integer()) -> {ok,
list(qrkit@internal@standard:encoded())} |
{error, qrkit@error:encode_error()}.
find_split(Data, Max_version, Ecc, Total) ->
case Total > 16 of
true ->
{error, {data_exceeds_capacity, 0, 0}};
false ->
Chunks = split_string(Data, Total),
case encode_shards(Chunks, Data, Total, Max_version, Ecc) of
{ok, Encodes} ->
{ok, Encodes};
{error, _} ->
find_split(Data, Max_version, Ecc, Total + 1)
end
end.
-file("src/qrkit/internal/structured_append.gleam", 25).
?DOC(false).
-spec encode(binary(), integer(), qrkit@types:error_correction()) -> {ok,
list(qrkit@internal@standard:encoded())} |
{error, qrkit@error:encode_error()}.
encode(Data, Max_version, Ecc) ->
case Data =:= <<""/utf8>> of
true ->
{error, empty_input};
false ->
case (Max_version < 1) orelse (Max_version > 40) of
true ->
{error, {invalid_version, Max_version}};
false ->
find_split(Data, Max_version, Ecc, 1)
end
end.