-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( [<> | 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, [<> | 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).