-module(internal@encoder@bit).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/internal/encoder/bit.gleam").
-export([estimate_encoded_size/4, encode_string/4]).
-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(
" Encode bit strings according to RFC 2045.\n"
"\n"
" See the following link for reference:\n"
" - <https://tools.ietf.org/html/rfc2045#section-2.7>\n"
" - <https://tools.ietf.org/html/rfc2045#section-2.8>\n"
).
-file("src/internal/encoder/bit.gleam", 113).
-spec is_valid_character(binary(), gleam@option:option(binary())) -> boolean().
is_valid_character(Character, Max_ascii) ->
(((gleam@string:compare(Character, <<"\r"/utf8>>) /= eq) andalso (gleam@string:compare(
Character,
<<"\n"/utf8>>
)
/= eq))
andalso (gleam@string:compare(Character, <<"\x{0}"/utf8>>) =:= gt))
andalso begin
_pipe = Max_ascii,
_pipe@1 = gleam@option:map(
_pipe,
fun(Ascii) -> gleam@string:compare(Character, Ascii) =:= lt end
),
gleam@option:unwrap(_pipe@1, true)
end.
-file("src/internal/encoder/bit.gleam", 91).
-spec validate_line(binary(), gleam@option:option(binary()), integer()) -> {ok,
integer()} |
{error, internal@encoder@encoding:encoder_error()}.
validate_line(Line, Max_ascii, Maximum_size) ->
Line_size = erlang:byte_size(Line),
gleam@bool:guard(
Line_size > Maximum_size,
{error, {maximum_size_exceeded, Maximum_size}},
fun() ->
Validation = begin
_pipe = Line,
_pipe@1 = gleam@string:split(_pipe, <<""/utf8>>),
gleam@list:find(
_pipe@1,
fun(Character) ->
not is_valid_character(Character, Max_ascii)
end
)
end,
case Validation of
{ok, Character@1} ->
{error, {invalid_character, Character@1}};
{error, nil} ->
{ok, Line_size}
end
end
).
-file("src/internal/encoder/bit.gleam", 64).
-spec max_ascii_from_bits(integer(), internal@encoder@encoding:encoding_mode()) -> gleam@option:option(binary()).
max_ascii_from_bits(Bits, Mode) ->
case {Bits, Mode} of
{8, utf8} ->
none;
{_, ascii} ->
_pipe = gleam@int:power(2, erlang:float(Bits)),
_pipe@1 = gleam@result:map(
_pipe,
fun(Ascii_code) ->
gleam@int:min(erlang:trunc(Ascii_code) - 1, 127)
end
),
_pipe@2 = gleam@result:'try'(
_pipe@1,
fun gleam@string:utf_codepoint/1
),
_pipe@3 = gleam@result:map(
_pipe@2,
fun(Codepoint) ->
gleam_stdlib:utf_codepoint_list_to_string([Codepoint])
end
),
_pipe@4 = gleam@result:unwrap(_pipe@3, <<""/utf8>>),
{some, _pipe@4};
{_, utf8} ->
_pipe@5 = gleam@int:power(2, erlang:float(Bits)),
_pipe@6 = gleam@result:map(
_pipe@5,
fun(Ascii_code@1) -> erlang:trunc(Ascii_code@1) - 1 end
),
_pipe@7 = gleam@result:'try'(
_pipe@6,
fun gleam@string:utf_codepoint/1
),
_pipe@8 = gleam@result:map(
_pipe@7,
fun(Codepoint@1) ->
gleam_stdlib:utf_codepoint_list_to_string([Codepoint@1])
end
),
_pipe@9 = gleam@result:unwrap(_pipe@8, <<""/utf8>>),
{some, _pipe@9}
end.
-file("src/internal/encoder/bit.gleam", 20).
?DOC(
" Estimates the `bits' bit encoded size of a string in bytes, taking\n"
" maximum size of a line into account.\n"
).
-spec estimate_encoded_size(
binary(),
integer(),
internal@encoder@encoding:encoding_mode(),
integer()
) -> {ok, integer()} | {error, internal@encoder@encoding:encoder_error()}.
estimate_encoded_size(String, Bits, Mode, Maximum_size) ->
Max_ascii = max_ascii_from_bits(Bits, Mode),
_pipe = String,
_pipe@1 = gleam@string:split(_pipe, <<"\r\n"/utf8>>),
gleam@list:try_fold(
_pipe@1,
0,
fun(Size, Line) -> case validate_line(Line, Max_ascii, Maximum_size) of
{ok, Line_size} ->
{ok, Size + Line_size};
{error, _} = Error ->
Error
end end
).
-file("src/internal/encoder/bit.gleam", 41).
?DOC(
" Bit encode a string with the required number of bits, using the\n"
" specified encoding mode and taking into account the maximum allowed\n"
" line size.\n"
).
-spec encode_string(
binary(),
integer(),
internal@encoder@encoding:encoding_mode(),
integer()
) -> {ok, list(binary())} | {error, internal@encoder@encoding:encoder_error()}.
encode_string(String, Bits, Mode, Maximum_size) ->
case String of
<<""/utf8>> ->
{ok, []};
_ ->
Max_ascii = max_ascii_from_bits(Bits, Mode),
_pipe = String,
_pipe@1 = gleam@string:split(_pipe, <<"\r\n"/utf8>>),
gleam@list:try_map(
_pipe@1,
fun(Line) ->
case validate_line(Line, Max_ascii, Maximum_size) of
{ok, _} ->
{ok, Line};
{error, Error} ->
{error, Error}
end
end
)
end.