-module(internal@encoder@text).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/internal/encoder/text.gleam").
-export([estimate_encoded_size/4, encode_string/6]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/internal/encoder/text.gleam", 195).
-spec should_escape_character(binary(), internal@encoder@encoding:field_type()) -> boolean().
should_escape_character(Character, Field_type) ->
((Field_type =:= structured) andalso (gleam@string:compare(
Character,
<<"\t"/utf8>>
)
/= eq))
andalso (((gleam@string:compare(Character, <<"\x{20}"/utf8>>) =:= lt) orelse (gleam@string:compare(
Character,
<<"\\"/utf8>>
)
=:= eq))
orelse (gleam@string:compare(Character, <<"\""/utf8>>) =:= eq)).
-file("src/internal/encoder/text.gleam", 208).
-spec is_valid_character(binary(), internal@encoder@encoding:encoding_mode()) -> boolean().
is_valid_character(Character, Mode) ->
case Mode of
ascii ->
(gleam@string:compare(Character, <<"\x{1f}"/utf8>>) =:= gt) andalso (gleam@string:compare(
Character,
<<"\x{80}"/utf8>>
)
=:= lt);
utf8 ->
gleam@string:compare(Character, <<"\x{1f}"/utf8>>) =:= gt
end.
-file("src/internal/encoder/text.gleam", 130).
-spec validate_chunk(
binary(),
internal@encoder@encoding:field_type(),
internal@encoder@encoding:encoding_mode(),
integer()
) -> {ok, integer()} | {error, internal@encoder@encoding:encoder_error()}.
validate_chunk(Chunk, Field_type, Mode, Maximum_size) ->
Chunk_size = erlang:byte_size(Chunk),
_pipe = Chunk,
_pipe@1 = gleam@string:split(_pipe, <<""/utf8>>),
_pipe@2 = gleam@list:try_fold(
_pipe@1,
Chunk_size,
fun(Accumulator, Character) ->
gleam@bool:guard(
not is_valid_character(Character, Mode),
{error, {invalid_character, Character}},
fun() ->
{ok,
Accumulator + gleam@bool:guard(
should_escape_character(Character, Field_type),
1,
fun() -> 0 end
)}
end
)
end
),
gleam@result:'try'(
_pipe@2,
fun(Chunk_size@1) -> case Chunk_size@1 =< Maximum_size of
true ->
{ok, Chunk_size@1};
false ->
{error, {maximum_size_exceeded, Maximum_size}}
end end
).
-file("src/internal/encoder/text.gleam", 217).
-spec is_whitespace(binary()) -> boolean().
is_whitespace(Character) ->
(gleam@string:compare(Character, <<"\t"/utf8>>) =:= eq) orelse (gleam@string:compare(
Character,
<<" "/utf8>>
)
=:= eq).
-file("src/internal/encoder/text.gleam", 107).
-spec chunk_on_whitespace(binary()) -> list(binary()).
chunk_on_whitespace(Value) ->
case Value of
<<""/utf8>> ->
[];
_ ->
_pipe = Value,
_pipe@1 = gleam@string:split(_pipe, <<""/utf8>>),
_pipe@2 = gleam@list:index_fold(
_pipe@1,
[0],
fun(Accumulator, Character, Index) ->
case is_whitespace(Character) of
true ->
[Index | Accumulator];
false ->
Accumulator
end
end
),
_pipe@3 = gleam@list:prepend(_pipe@2, string:length(Value)),
_pipe@4 = lists:reverse(_pipe@3),
_pipe@5 = gleam@list:window_by_2(_pipe@4),
gleam@list:map(
_pipe@5,
fun(Chunk) ->
{Start, End} = Chunk,
gleam@string:slice(Value, Start, End - Start)
end
)
end.
-file("src/internal/encoder/text.gleam", 17).
?DOC(
" Estimates the quoted string encoded the size of string in bytes,\n"
" taking the encoding mode and the maximum size of a line into\n"
" account.\n"
).
-spec estimate_encoded_size(
binary(),
internal@encoder@encoding:field_type(),
internal@encoder@encoding:encoding_mode(),
integer()
) -> {ok, integer()} | {error, internal@encoder@encoding:encoder_error()}.
estimate_encoded_size(String, Field_type, Mode, Maximum_size) ->
_pipe = String,
_pipe@1 = chunk_on_whitespace(_pipe),
gleam@list:try_fold(
_pipe@1,
0,
fun(Current_size, Chunk) ->
case validate_chunk(Chunk, Field_type, Mode, Maximum_size - 2) of
{ok, Chunk_size} ->
{ok, Current_size + Chunk_size};
{error, _} = Error ->
Error
end
end
).
-file("src/internal/encoder/text.gleam", 184).
-spec should_encode_character(binary(), internal@encoder@encoding:field_type()) -> boolean().
should_encode_character(Character, Field_type) ->
should_escape_character(Character, Field_type) orelse ((Field_type =:= structured)
andalso gleam_stdlib:contains_string(<<"()<>@,;:.[]"/utf8>>, Character)).
-file("src/internal/encoder/text.gleam", 158).
-spec encode_chunk(
binary(),
internal@encoder@encoding:field_type(),
internal@encoder@encoding:encoding_mode()
) -> {ok, {boolean(), binary()}} |
{error, internal@encoder@encoding:encoder_error()}.
encode_chunk(Chunk, Field_type, Mode) ->
_pipe = Chunk,
_pipe@1 = gleam@string:split(_pipe, <<""/utf8>>),
gleam@list:try_fold(
_pipe@1,
{false, <<""/utf8>>},
fun(Accumulator, Character) ->
gleam@bool:guard(
not is_valid_character(Character, Mode),
{error, {invalid_character, Character}},
fun() ->
{Should_quote, Characters} = Accumulator,
Should_quote@1 = Should_quote orelse should_encode_character(
Character,
Field_type
),
case should_escape_character(Character, Field_type) of
true ->
{ok,
{Should_quote@1,
begin
_pipe@2 = Characters,
_pipe@3 = gleam@string:append(
_pipe@2,
<<"\\"/utf8>>
),
gleam@string:append(_pipe@3, Character)
end}};
false ->
{ok,
{Should_quote@1,
begin
_pipe@4 = Characters,
gleam@string:append(_pipe@4, Character)
end}}
end
end
)
end
).
-file("src/internal/encoder/text.gleam", 51).
-spec join_chunks(
list(binary()),
internal@encoder@encoding:field_type(),
internal@encoder@encoding:encoding_mode(),
integer(),
integer(),
integer()
) -> {ok, list(binary())} | {error, internal@encoder@encoding:encoder_error()}.
join_chunks(Chunks, Field_type, Mode, Count, Preferred_size, Maximum_size) ->
_pipe = Chunks,
_pipe@1 = gleam@list:try_fold(
_pipe,
{false, []},
fun(Accumulator, Chunk) ->
{Needs_quoting, Chunks@1} = Accumulator,
case encode_chunk(Chunk, Field_type, Mode) of
{ok, {Chunk_needs_quoting, Encoded_chunk}} ->
{ok,
{Needs_quoting orelse Chunk_needs_quoting,
[Encoded_chunk | Chunks@1]}};
{error, Error} ->
{error, Error}
end
end
),
gleam@result:'try'(
_pipe@1,
fun(Result) ->
{Should_quote, Chunks@2} = Result,
Chunks@3 = case {Should_quote, Chunks@2} of
{true, [Chunk@1 | Other_chunks]} ->
lists:reverse(
[<<Chunk@1/binary, "\""/utf8>> | Other_chunks]
);
{true, []} ->
lists:reverse(Chunks@2);
{false, _} ->
lists:reverse(Chunks@2)
end,
Chunks@4 = case {Should_quote, Chunks@3} of
{true, [Chunk@2 | Other_chunks@1]} ->
[<<"\""/utf8, Chunk@2/binary>> | Other_chunks@1];
{true, []} ->
Chunks@3;
{false, _} ->
Chunks@3
end,
_pipe@2 = Chunks@4,
_pipe@3 = gleam@list:try_fold(
_pipe@2,
{Count, []},
fun(Accumulator@1, Chunk@3) ->
{Used_size, Lines} = Accumulator@1,
Chunk_size = erlang:byte_size(Chunk@3),
gleam@bool:guard(
Chunk_size > Maximum_size,
{error, {maximum_size_exceeded, Maximum_size}},
fun() -> case Lines of
[] ->
{ok, {Chunk_size, [Chunk@3]}};
Lines@1 when (Used_size + Chunk_size) > Preferred_size ->
{ok, {Chunk_size, [Chunk@3 | Lines@1]}};
[First_line | Other_lines] ->
{ok,
{Used_size + Chunk_size,
[<<First_line/binary,
Chunk@3/binary>> |
Other_lines]}}
end end
)
end
),
gleam@result:map(_pipe@3, fun gleam@pair:second/1)
end
).
-file("src/internal/encoder/text.gleam", 37).
?DOC(
" Quoted string encode a string, using the specified encoding mode,\n"
" taking the preferred line size and maximum line size into account,\n"
" and pretending to start the first line at the passed start\n"
" position.\n"
).
-spec encode_string(
binary(),
internal@encoder@encoding:field_type(),
internal@encoder@encoding:encoding_mode(),
integer(),
integer(),
integer()
) -> {ok, list(binary())} | {error, internal@encoder@encoding:encoder_error()}.
encode_string(String, Field_type, Mode, Position, Preferred_size, Maximum_size) ->
_pipe = String,
_pipe@1 = chunk_on_whitespace(_pipe),
_pipe@2 = join_chunks(
_pipe@1,
Field_type,
Mode,
Position,
Preferred_size,
Maximum_size
),
gleam@result:map(_pipe@2, fun lists:reverse/1).