-module(qrkit@internal@segment).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/qrkit/internal/segment.gleam").
-export([mode/1, data/1, count/1, bits/1, encoded_bits/3, optimise/3, append_to_stream/4]).
-export_type([segment/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 segment() :: {segment,
qrkit@types:mode(),
binary(),
integer(),
integer(),
integer()}.
-file("src/qrkit/internal/segment.gleam", 18).
?DOC(false).
-spec mode(segment()) -> qrkit@types:mode().
mode(Segment) ->
{segment, Mode, _, _, _, _} = Segment,
Mode.
-file("src/qrkit/internal/segment.gleam", 23).
?DOC(false).
-spec data(segment()) -> binary().
data(Segment) ->
{segment, _, Data, _, _, _} = Segment,
Data.
-file("src/qrkit/internal/segment.gleam", 28).
?DOC(false).
-spec count(segment()) -> integer().
count(Segment) ->
{segment, _, _, Count, _, _} = Segment,
Count.
-file("src/qrkit/internal/segment.gleam", 33).
?DOC(false).
-spec bits(segment()) -> integer().
bits(Segment) ->
{segment, _, _, _, Bits, _} = Segment,
Bits.
-file("src/qrkit/internal/segment.gleam", 186).
?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/segment.gleam", 201).
?DOC(false).
-spec is_alnum_family(qrkit@types:mode()) -> boolean().
is_alnum_family(Value) ->
case Value of
numeric ->
true;
alphanumeric ->
true;
_ ->
false
end.
-file("src/qrkit/internal/segment.gleam", 209).
?DOC(false).
-spec build_segment(qrkit@types:mode(), binary(), integer()) -> segment().
build_segment(Current_mode, Text, Index) ->
{segment,
Current_mode,
Text,
qrkit@internal@mode:character_count(Text, Current_mode),
qrkit@internal@mode:data_bits_length(Text, Current_mode),
Index}.
-file("src/qrkit/internal/segment.gleam", 98).
?DOC(false).
-spec greedy_segments(
list(binary()),
integer(),
list(segment()),
gleam@option:option({qrkit@types:mode(), binary(), integer()})
) -> list(segment()).
greedy_segments(Chars, Index, Acc, Current) ->
case Chars of
[] ->
case Current of
{some, {Current_mode, Current_text, Start}} ->
lists:reverse(
[build_segment(Current_mode, Current_text, Start) | Acc]
);
none ->
lists:reverse(Acc)
end;
[Char | Rest] ->
Next_mode = classify_char(Char),
case Current of
{some, {Current_mode@1, Current_text@1, Start@1}} when Current_mode@1 =:= Next_mode ->
greedy_segments(
Rest,
Index + 1,
Acc,
{some,
{Current_mode@1,
<<Current_text@1/binary, Char/binary>>,
Start@1}}
);
{some, {Current_mode@2, Current_text@2, Start@2}} ->
greedy_segments(
Rest,
Index + 1,
[build_segment(Current_mode@2, Current_text@2, Start@2) |
Acc],
{some, {Next_mode, Char, Index}}
);
none ->
greedy_segments(
Rest,
Index + 1,
Acc,
{some, {Next_mode, Char, Index}}
)
end
end.
-file("src/qrkit/internal/segment.gleam", 254).
?DOC(false).
-spec append_eci(qrkit@internal@bitstream:bit_stream(), integer()) -> {ok,
qrkit@internal@bitstream:bit_stream()} |
{error, qrkit@error:encode_error()}.
append_eci(Stream, Designator) ->
case (Designator < 0) orelse (Designator > 999999) of
true ->
{error, {invalid_eci_designator, Designator}};
false ->
case Designator < 128 of
true ->
{ok,
begin
_pipe = Stream,
_pipe@1 = qrkit@internal@bitstream:append_bits(
_pipe,
2#0111,
4
),
qrkit@internal@bitstream:append_bits(
_pipe@1,
Designator,
8
)
end};
false ->
case Designator < 16384 of
true ->
{ok,
begin
_pipe@2 = Stream,
_pipe@3 = qrkit@internal@bitstream:append_bits(
_pipe@2,
2#0111,
4
),
_pipe@4 = qrkit@internal@bitstream:append_bits(
_pipe@3,
2#10,
2
),
qrkit@internal@bitstream:append_bits(
_pipe@4,
Designator,
14
)
end};
false ->
{ok,
begin
_pipe@5 = Stream,
_pipe@6 = qrkit@internal@bitstream:append_bits(
_pipe@5,
2#0111,
4
),
_pipe@7 = qrkit@internal@bitstream:append_bits(
_pipe@6,
2#110,
3
),
qrkit@internal@bitstream:append_bits(
_pipe@7,
Designator,
21
)
end}
end
end
end.
-file("src/qrkit/internal/segment.gleam", 289).
?DOC(false).
-spec eci_designator_bits(integer()) -> integer().
eci_designator_bits(Value) ->
case Value < 128 of
true ->
8;
false ->
case Value < 16384 of
true ->
16;
false ->
24
end
end.
-file("src/qrkit/internal/segment.gleam", 66).
?DOC(false).
-spec encoded_bits(list(segment()), integer(), gleam@option:option(integer())) -> integer().
encoded_bits(Segments, Version, Eci) ->
Eci_bits = case Eci of
none ->
0;
{some, Value} ->
4 + eci_designator_bits(Value)
end,
Eci_bits + gleam@list:fold(
Segments,
0,
fun(Acc, Segment) ->
((Acc + 4) + qrkit@internal@mode:char_count_bits(
mode(Segment),
Version
))
+ bits(Segment)
end
).
-file("src/qrkit/internal/segment.gleam", 300).
?DOC(false).
-spec segment_index(segment()) -> integer().
segment_index(Segment) ->
{segment, _, _, _, _, Index} = Segment,
Index.
-file("src/qrkit/internal/segment.gleam", 152).
?DOC(false).
-spec promote_pair(segment(), segment()) -> gleam@option:option(segment()).
promote_pair(First, Second) ->
First_mode = mode(First),
Second_mode = mode(Second),
case is_alnum_family(First_mode) andalso is_alnum_family(Second_mode) of
true ->
{some,
build_segment(
alphanumeric,
<<(data(First))/binary, (data(Second))/binary>>,
segment_index(First)
)};
false ->
none
end.
-file("src/qrkit/internal/segment.gleam", 141).
?DOC(false).
-spec merge_numeric_with_alphanumeric(list(segment())) -> list(segment()).
merge_numeric_with_alphanumeric(Segments) ->
case Segments of
[First, Second | Rest] ->
case promote_pair(First, Second) of
{some, Merged} ->
merge_numeric_with_alphanumeric([Merged | Rest]);
none ->
[First | merge_numeric_with_alphanumeric([Second | Rest])]
end;
_ ->
Segments
end.
-file("src/qrkit/internal/segment.gleam", 166).
?DOC(false).
-spec merge_adjacent_same_mode(list(segment())) -> list(segment()).
merge_adjacent_same_mode(Segments) ->
case Segments of
[First, Second | Rest] ->
case mode(First) =:= mode(Second) of
true ->
merge_adjacent_same_mode(
[build_segment(
mode(First),
<<(data(First))/binary, (data(Second))/binary>>,
segment_index(First)
) |
Rest]
);
false ->
[First | merge_adjacent_same_mode([Second | Rest])]
end;
[First@1 | Rest@1] ->
[First@1 | merge_adjacent_same_mode(Rest@1)];
[] ->
[]
end.
-file("src/qrkit/internal/segment.gleam", 135).
?DOC(false).
-spec normalise_segments(list(segment())) -> list(segment()).
normalise_segments(Segments) ->
_pipe = Segments,
_pipe@1 = merge_numeric_with_alphanumeric(_pipe),
merge_adjacent_same_mode(_pipe@1).
-file("src/qrkit/internal/segment.gleam", 38).
?DOC(false).
-spec optimise(binary(), integer(), qrkit@types:mode_preference()) -> {ok,
list(segment())} |
{error, qrkit@error:encode_error()}.
optimise(Text, Version, Preference) ->
case Preference of
force_byte ->
{ok, [build_segment(byte, Text, 0)]};
auto ->
Greedy = begin
_pipe = qrkit@internal@util:characters(Text),
_pipe@1 = greedy_segments(_pipe, 0, [], none),
normalise_segments(_pipe@1)
end,
Single_byte = [build_segment(byte, Text, 0)],
case encoded_bits(Greedy, Version, none) =< encoded_bits(
Single_byte,
Version,
none
) of
true ->
{ok, Greedy};
false ->
{ok, Single_byte}
end
end.
-file("src/qrkit/internal/segment.gleam", 219).
?DOC(false).
-spec do_append_segments(
qrkit@internal@bitstream:bit_stream(),
list(segment()),
integer()
) -> {ok, qrkit@internal@bitstream:bit_stream()} |
{error, qrkit@error:encode_error()}.
do_append_segments(Stream, Segments, Version) ->
case Segments of
[] ->
{ok, Stream};
[Segment | Rest] ->
case qrkit@internal@mode:encode(
data(Segment),
mode(Segment),
segment_index(Segment)
) of
{ok, Bits} ->
do_append_segments(
begin
_pipe = qrkit@internal@bitstream:append_bits(
Stream,
qrkit@internal@mode:mode_bits(mode(Segment)),
4
),
_pipe@1 = qrkit@internal@bitstream:append_bits(
_pipe,
count(Segment),
qrkit@internal@mode:char_count_bits(
mode(Segment),
Version
)
),
qrkit@internal@bitstream:append_bytes(_pipe@1, Bits)
end,
Rest,
Version
);
{error, Error} ->
{error, Error}
end
end.
-file("src/qrkit/internal/segment.gleam", 81).
?DOC(false).
-spec append_to_stream(
qrkit@internal@bitstream:bit_stream(),
list(segment()),
integer(),
gleam@option:option(integer())
) -> {ok, qrkit@internal@bitstream:bit_stream()} |
{error, qrkit@error:encode_error()}.
append_to_stream(Stream, Segments, Version, Eci) ->
With_eci = case Eci of
none ->
{ok, Stream};
{some, Value} ->
append_eci(Stream, Value)
end,
case With_eci of
{error, Error} ->
{error, Error};
{ok, Stream_with_eci} ->
do_append_segments(Stream_with_eci, Segments, Version)
end.