Current section
Files
Jump to
Current section
Files
src/jackson@internal@escaping.erl
-module(jackson@internal@escaping).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([descape_string/1, escape_string/1]).
-spec is_control_character(integer()) -> boolean().
is_control_character(Val) ->
gleam@bool:guard(
(Val >= 16#000) andalso (Val =< 16#001f),
true,
fun() ->
gleam@bool:guard(
(Val >= 16#007f) andalso (Val =< 16#009f),
true,
fun() ->
gleam@bool:guard(
((Val =:= 16#061c) orelse (Val =:= 16#200e)) orelse (Val
=:= 16#200f),
true,
fun() ->
gleam@bool:guard(
(Val >= 16#202a) andalso (Val =< 16#202e),
true,
fun() ->
gleam@bool:guard(
(Val >= 16#2066) andalso (Val =< 16#2069),
true,
fun() -> false end
)
end
)
end
)
end
)
end
).
-spec string_to_ints(binary()) -> list(integer()).
string_to_ints(In) ->
_pipe = gleam@string:to_utf_codepoints(In),
gleam@list:map(_pipe, fun gleam@string:utf_codepoint_to_int/1).
-spec descape_string_loop(binary()) -> gleam@string_builder:string_builder().
descape_string_loop(In) ->
Builder = gleam@string_builder:new(),
case gleam@string:pop_grapheme(In) of
{error, _} ->
Builder;
{ok, {<<"\\"/utf8>>, Next}} ->
{Escaped_char, Rest@10} = case gleam@string:pop_grapheme(Next) of
{ok, {<<"\""/utf8>>, Rest}} ->
{<<"\""/utf8>>, Rest};
{ok, {<<"\\"/utf8>>, Rest@1}} ->
{<<"\\"/utf8>>, Rest@1};
{ok, {<<"/"/utf8>>, Rest@2}} ->
{<<"/"/utf8>>, Rest@2};
{ok, {<<"b"/utf8>>, Rest@3}} ->
{<<"\x{0008}"/utf8>>, Rest@3};
{ok, {<<"f"/utf8>>, Rest@4}} ->
{<<"\f"/utf8>>, Rest@4};
{ok, {<<"n"/utf8>>, Rest@5}} ->
{<<"\n"/utf8>>, Rest@5};
{ok, {<<"r"/utf8>>, Rest@6}} ->
{<<"\r"/utf8>>, Rest@6};
{ok, {<<"t"/utf8>>, Rest@7}} ->
{<<"\t"/utf8>>, Rest@7};
{ok, {<<"u"/utf8>>, Rest@8}} ->
case gleam@string:to_graphemes(Rest@8) of
[A, B, C, D | Rest@9] ->
Codepoint = begin
_pipe = gleam@int:base_parse(
gleam@string:concat([A, B, C, D]),
16
),
gleam@result:'try'(
_pipe,
fun gleam@string:utf_codepoint/1
)
end,
case Codepoint of
{ok, Code} ->
{gleam_stdlib:utf_codepoint_list_to_string(
[Code]
),
gleam@string:concat(Rest@9)};
_ ->
erlang:error(#{gleam_error => panic,
message => <<"invalid json utf codepoint escape sequence"/utf8>>,
module => <<"jackson/internal/escaping"/utf8>>,
function => <<"descape_string_loop"/utf8>>,
line => 128})
end;
_ ->
erlang:error(#{gleam_error => panic,
message => <<"invalid json escape sequence"/utf8>>,
module => <<"jackson/internal/escaping"/utf8>>,
function => <<"descape_string_loop"/utf8>>,
line => 131})
end;
_ ->
erlang:error(#{gleam_error => panic,
message => <<"invalid json escape sequence"/utf8>>,
module => <<"jackson/internal/escaping"/utf8>>,
function => <<"descape_string_loop"/utf8>>,
line => 133})
end,
_pipe@1 = Builder,
_pipe@2 = gleam@string_builder:append(_pipe@1, Escaped_char),
gleam@string_builder:append_builder(
_pipe@2,
descape_string_loop(Rest@10)
);
{ok, {Char, Rest@11}} ->
_pipe@3 = Builder,
_pipe@4 = gleam@string_builder:append(_pipe@3, Char),
gleam@string_builder:append_builder(
_pipe@4,
descape_string_loop(Rest@11)
)
end.
-spec descape_string(binary()) -> binary().
descape_string(In) ->
_pipe = descape_string_loop(In),
gleam@string_builder:to_string(_pipe).
-spec escape_string_loop(list(integer())) -> list(integer()).
escape_string_loop(In) ->
case In of
[] ->
[];
[16#201c | Rest] ->
[16#005c, 16#201c | escape_string_loop(Rest)];
[16#005c | Rest@1] ->
[16#005c, 16#005c | escape_string_loop(Rest@1)];
[16#002f | Rest@2] ->
[16#005c, 16#002f | escape_string_loop(Rest@2)];
[16#0008 | Rest@3] ->
[16#005c, 16#0062 | escape_string_loop(Rest@3)];
[16#000c | Rest@4] ->
[16#005c, 16#0066 | escape_string_loop(Rest@4)];
[16#000a | Rest@5] ->
[16#005c, 16#006e | escape_string_loop(Rest@5)];
[16#000d | Rest@6] ->
[16#005c, 16#0072 | escape_string_loop(Rest@6)];
[16#2b7e | Rest@7] ->
[16#005c, 16#0074 | escape_string_loop(Rest@7)];
[Next_codepoint | Rest@8] ->
case is_control_character(Next_codepoint) of
false ->
[Next_codepoint | escape_string_loop(Rest@8)];
true ->
Escaped_ints = begin
_pipe = gleam@int:to_base16(Next_codepoint),
_pipe@1 = gleam@string:to_utf_codepoints(_pipe),
gleam@list:map(
_pipe@1,
fun gleam@string:utf_codepoint_to_int/1
)
end,
_assert_subject = case Escaped_ints of
[] ->
[16#0030, 16#0030, 16#0030, 16#0030];
[A] ->
[16#0030, 16#0030, 16#0030, A];
[A@1, B] ->
[16#0030, 16#0030, A@1, B];
[A@2, B@1, C] ->
[16#0030, A@2, B@1, C];
[A@3, B@2, C@1, D] ->
[A@3, B@2, C@1, D];
_ ->
erlang:error(#{gleam_error => panic,
message => <<"un encodable utf control character"/utf8>>,
module => <<"jackson/internal/escaping"/utf8>>,
function => <<"escape_string_loop"/utf8>>,
line => 87})
end,
[A@4, B@3, C@2, D@1] = case _assert_subject of
[_, _, _, _] -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"jackson/internal/escaping"/utf8>>,
function => <<"escape_string_loop"/utf8>>,
line => 81})
end,
[16#005c,
16#0075,
A@4,
B@3,
C@2,
D@1 |
escape_string_loop(Rest@8)]
end
end.
-spec escape_string(binary()) -> binary().
escape_string(In) ->
_pipe = gleam@string:to_utf_codepoints(In),
_pipe@1 = gleam@list:map(_pipe, fun gleam@string:utf_codepoint_to_int/1),
_pipe@2 = escape_string_loop(_pipe@1),
_pipe@3 = gleam@list:map(_pipe@2, fun gleam@string:utf_codepoint/1),
_pipe@4 = gleam@result:values(_pipe@3),
gleam_stdlib:utf_codepoint_list_to_string(_pipe@4).