-module(thoas_encode). -compile([ {no_auto_import, [float/1]}, {inline, [{float, 1}, {integer, 1}, {error_invalid_byte_error, 2}]} ]). %%% Normal reflection based API that turns Erlang terms into JSON. -export([encode/2]). %%% Non-recursive API that expects sub-objects to already be encoded. Likely %%% useful for statically typed languages such as Gleam. -export([ true/0, false/0, null/0, boolean/1, integer/1, float/1, string/1, non_recursive_array/1, non_recursive_object/1 ]). %%% A boolean value as JSON. -spec boolean(boolean()) -> iodata(). boolean('true') -> <<"true">>; boolean('false') -> <<"false">>. %%% The JSON value `true`. -spec true() -> iodata(). true() -> <<"true">>. %%% The JSON value `false`. -spec false() -> iodata(). false() -> <<"false">>. %%% The JSON value `null`. -spec null() -> iodata(). null() -> <<"null">>. %%% A float in JSON format. -spec float(float()) -> iodata(). float(Float) -> erlang:float_to_binary(Float, [short]). %%% An integer in JSON format. -spec integer(integer()) -> iodata(). integer(Int) -> integer_to_list(Int). %%% A string in JSON format, using normal JSON escaping of the contents. -spec string(binary()) -> iodata(). string(String) -> encode_string(String, fun escape_json/3). %%% An array of JSON values. %%% %%% Important: The values supplied in the list are not processed and **must** %%% already encoded into JSON using one of the other functions, such as %%% `integer/1` or `string/1`. %%% -spec non_recursive_array(list(iodata())) -> iodata(). non_recursive_array([]) -> <<"[]">>; non_recursive_array([First | Rest]) -> [$[, First | non_recursive_array_loop(Rest)]. non_recursive_array_loop([]) -> [$]]; non_recursive_array_loop([First | Rest]) -> [$,, First | non_recursive_array_loop(Rest)]. %%% An object of JSON values. %%% %%% Important: The values supplied in the list are not processed and **must** %%% already encoded into JSON using one of the other functions, such as %%% `integer/1` or `string/1`. %%% Keys are processed as strings and get escaped using normal JSON escaping. %%% -spec non_recursive_object(list({binary(), iodata()})) -> iodata(). non_recursive_object([]) -> <<"{}">>; non_recursive_object([{Key, Value} | Tail]) -> Escape = fun escape_json/3, [ <<"{\"">>, key(Key, Escape), <<"\":">>, Value | non_recursive_object_loop(Tail, Escape) ]. non_recursive_object_loop([], _Escape) -> [$}]; non_recursive_object_loop([{Key, Value} | Tail], Escape) -> [ <<",\"">>, key(Key, Escape), <<"\":">>, Value | non_recursive_object_loop(Tail, Escape) ]. %%%% %%%% Recursive encoding functions %%%% encode(Value, Opts) -> value(Value, escape_function(Opts)). encode_atom(null, _Escape) -> <<"null">>; encode_atom(true, _Escape) -> <<"true">>; encode_atom(false, _Escape) -> <<"false">>; encode_atom(Atom, Escape) -> encode_string(atom_to_binary(Atom, utf8), Escape). encode_string(String, Escape) -> [$", Escape(String, String, 0), $"]. escape(0) -> <<"\\u0000">>; escape(1) -> <<"\\u0001">>; escape(2) -> <<"\\u0002">>; escape(3) -> <<"\\u0003">>; escape(4) -> <<"\\u0004">>; escape(5) -> <<"\\u0005">>; escape(6) -> <<"\\u0006">>; escape(7) -> <<"\\u0007">>; escape(8) -> <<"\\b">>; escape(9) -> <<"\\t">>; escape(10) -> <<"\\n">>; escape(11) -> <<"\\u000B">>; escape(12) -> <<"\\f">>; escape(13) -> <<"\\r">>; escape(14) -> <<"\\u000E">>; escape(15) -> <<"\\u000F">>; escape(16) -> <<"\\u0010">>; escape(17) -> <<"\\u0011">>; escape(18) -> <<"\\u0012">>; escape(19) -> <<"\\u0013">>; escape(20) -> <<"\\u0014">>; escape(21) -> <<"\\u0015">>; escape(22) -> <<"\\u0016">>; escape(23) -> <<"\\u0017">>; escape(24) -> <<"\\u0018">>; escape(25) -> <<"\\u0019">>; escape(26) -> <<"\\u001A">>; escape(27) -> <<"\\u001B">>; escape(28) -> <<"\\u001C">>; escape(29) -> <<"\\u001D">>; escape(30) -> <<"\\u001E">>; escape(31) -> <<"\\u001F">>; escape(32) -> throw(error); escape(33) -> throw(error); escape(34) -> <<"\\\"">>; escape(X) when X < 47 andalso X > 34 -> throw(error); escape(47) -> <<"\\/">>; escape(X) when X < 92 andalso X > 47 -> throw(error); escape(92) -> <<"\\\\">>. escape_function(Options) -> case maps:get(escape, Options, json) of json -> fun escape_json/3; html -> fun escape_html/3; unicode -> fun escape_unicode/3; javascript -> fun escape_js/3 end. escape_html(Data, Input, Skip) -> escape_html(Data, [], Input, Skip). escape_html(<>, Acc, Input, Skip) when Byte < 33 -> Acc2 = [Acc | escape(Byte)], escape_html(Rest, Acc2, Input, Skip + 1); escape_html(<>, Acc, Input, Skip) when Byte =:= 33 -> escape_html_chunk(Rest, Acc, Input, Skip, 1); escape_html(<>, Acc, Input, Skip) when Byte =:= 34 -> Acc2 = [Acc | escape(Byte)], escape_html(Rest, Acc2, Input, Skip + 1); escape_html(<>, Acc, Input, Skip) when Byte < 47 -> escape_html_chunk(Rest, Acc, Input, Skip, 1); escape_html(<>, Acc, Input, Skip) when Byte =:= 47 -> Acc2 = [Acc | escape(Byte)], escape_html(Rest, Acc2, Input, Skip + 1); escape_html(<>, Acc, Input, Skip) when Byte < 92 -> escape_html_chunk(Rest, Acc, Input, Skip, 1); escape_html(<>, Acc, Input, Skip) when Byte =:= 92 -> Acc2 = [Acc | escape(Byte)], escape_html(Rest, Acc2, Input, Skip + 1); escape_html(<>, Acc, Input, Skip) when Byte < 128 -> escape_html_chunk(Rest, Acc, Input, Skip, 1); escape_html(<>, Acc, Input, Skip) when Char =< 2047 -> escape_html_chunk(Rest, Acc, Input, Skip, 2); escape_html(<<8232/utf8,Rest/bitstring>>, Acc, Input, Skip) -> Acc2 = [Acc | <<"\\u2028">>], escape_html(Rest, Acc2, Input, Skip + 3); escape_html(<<8233/utf8,Rest/bitstring>>, Acc, Input, Skip) -> Acc2 = [Acc | <<"\\u2029">>], escape_html(Rest, Acc2, Input, Skip + 3); escape_html(<>, Acc, Input, Skip) when Char =< 65535 -> escape_html_chunk(Rest, Acc, Input, Skip, 3); escape_html(<<_Char/utf8,Rest/bitstring>>, Acc, Input, Skip) -> escape_html_chunk(Rest, Acc, Input, Skip, 4); escape_html(<<>>, Acc, _Input, _Skip) -> Acc; escape_html(<>, _Acc, Input, _Skip) -> error_invalid_byte_error(Byte, Input). escape_html_chunk(<>, Acc, Input, Skip, Len) when Byte < 32 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_html(Rest, Acc2, Input, Skip + Len + 1); escape_html_chunk(<>, Acc, Input, Skip, Len) when Byte < 34 -> escape_html_chunk(Rest, Acc, Input, Skip, Len + 1); escape_html_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 34 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_html(Rest, Acc2, Input, Skip + Len + 1); escape_html_chunk(<>, Acc, Input, Skip, Len) when Byte < 47 -> escape_html_chunk(Rest, Acc, Input, Skip, Len + 1); escape_html_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 47 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_html(Rest, Acc2, Input, Skip + Len + 1); escape_html_chunk(<>, Acc, Input, Skip, Len) when Byte < 92 -> escape_html_chunk(Rest, Acc, Input, Skip, Len + 1); escape_html_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 92 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_html(Rest, Acc2, Input, Skip + Len + 1); escape_html_chunk(<>, Acc, Input, Skip, Len) when Byte < 128 -> escape_html_chunk(Rest, Acc, Input, Skip, Len + 1); escape_html_chunk(<>, Acc, Input, Skip, Len) when Char =< 2047 -> escape_html_chunk(Rest, Acc, Input, Skip, Len + 2); escape_html_chunk(<<8232/utf8,Rest/bitstring>>, Acc, Input, Skip, Len) -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | <<"\\u2028">>], escape_html(Rest, Acc2, Input, Skip + Len + 3); escape_html_chunk(<<8233/utf8,Rest/bitstring>>, Acc, Input, Skip, Len) -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | <<"\\u2029">>], escape_html(Rest, Acc2, Input, Skip + Len + 3); escape_html_chunk(<>, Acc, Input, Skip, Len) when Char =< 65535 -> escape_html_chunk(Rest, Acc, Input, Skip, Len + 3); escape_html_chunk(<<_Char/utf8,Rest/bitstring>>, Acc, Input, Skip, Len) -> escape_html_chunk(Rest, Acc, Input, Skip, Len + 4); escape_html_chunk(<<>>, Acc, Input, Skip, Len) -> Part = binary_part(Input, Skip, Len), [Acc | Part]; escape_html_chunk(<>, _Acc, Input, _Skip, _Len) -> error_invalid_byte_error(Byte, Input). escape_js(Data, Input, Skip) -> escape_js(Data, [], Input, Skip). escape_js(<>, Acc, Input, Skip) when Byte < 32 -> Acc2 = [Acc | escape(Byte)], escape_js(Rest, Acc2, Input, Skip + 1); escape_js(<>, Acc, Input, Skip) when Byte < 34 -> escape_js_chunk(Rest, Acc, Input, Skip, 1); escape_js(<>, Acc, Input, Skip) when Byte =:= 34 -> Acc2 = [Acc | escape(Byte)], escape_js(Rest, Acc2, Input, Skip + 1); escape_js(<>, Acc, Input, Skip) when Byte < 92 -> escape_js_chunk(Rest, Acc, Input, Skip, 1); escape_js(<>, Acc, Input, Skip) when Byte =:= 92 -> Acc2 = [Acc | escape(Byte)], escape_js(Rest, Acc2, Input, Skip + 1); escape_js(<>, Acc, Input, Skip) when Byte < 128 -> escape_js_chunk(Rest, Acc, Input, Skip, 1); escape_js(<>, Acc, Input, Skip) when Char =< 2047 -> escape_js_chunk(Rest, Acc, Input, Skip, 2); escape_js(<<8232/utf8,Rest/bitstring>>, Acc, Input, Skip) -> Acc2 = [Acc | <<"\\u2028">>], escape_js(Rest, Acc2, Input, Skip + 3); escape_js(<<8233/utf8,Rest/bitstring>>, Acc, Input, Skip) -> Acc2 = [Acc | <<"\\u2029">>], escape_js(Rest, Acc2, Input, Skip + 3); escape_js(<>, Acc, Input, Skip) when Char =< 65535 -> escape_js_chunk(Rest, Acc, Input, Skip, 3); escape_js(<<_Char/utf8,Rest/bitstring>>, Acc, Input, Skip) -> escape_js_chunk(Rest, Acc, Input, Skip, 4); escape_js(<<>>, Acc, _Input, _Skip) -> Acc; escape_js(<>, _Acc, Input, _Skip) -> error_invalid_byte_error(Byte, Input). escape_js_chunk(<>, Acc, Input, Skip, Len) when Byte < 32 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_js(Rest, Acc2, Input, Skip + Len + 1); escape_js_chunk(<>, Acc, Input, Skip, Len) when Byte < 34 -> escape_js_chunk(Rest, Acc, Input, Skip, Len + 1); escape_js_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 34 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_js(Rest, Acc2, Input, Skip + Len + 1); escape_js_chunk(<>, Acc, Input, Skip, Len) when Byte < 92 -> escape_js_chunk(Rest, Acc, Input, Skip, Len + 1); escape_js_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 92 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_js(Rest, Acc2, Input, Skip + Len + 1); escape_js_chunk(<>, Acc, Input, Skip, Len) when Byte < 128 -> escape_js_chunk(Rest, Acc, Input, Skip, Len + 1); escape_js_chunk(<>, Acc, Input, Skip, Len) when Char =< 2047 -> escape_js_chunk(Rest, Acc, Input, Skip, Len + 2); escape_js_chunk(<<8232/utf8,Rest/bitstring>>, Acc, Input, Skip, Len) -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | <<"\\u2028">>], escape_js(Rest, Acc2, Input, Skip + Len + 3); escape_js_chunk(<<8233/utf8,Rest/bitstring>>, Acc, Input, Skip, Len) -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | <<"\\u2029">>], escape_js(Rest, Acc2, Input, Skip + Len + 3); escape_js_chunk(<>, Acc, Input, Skip, Len) when Char =< 65535 -> escape_js_chunk(Rest, Acc, Input, Skip, Len + 3); escape_js_chunk(<<_Char/utf8,Rest/bitstring>>, Acc, Input, Skip, Len) -> escape_js_chunk(Rest, Acc, Input, Skip, Len + 4); escape_js_chunk(<<>>, Acc, Input, Skip, Len) -> Part = binary_part(Input, Skip, Len), [Acc | Part]; escape_js_chunk(<>, _Acc, Input, _Skip, _Len) -> error_invalid_byte_error(Byte, Input). escape_json(Data, Input, Skip) -> escape_json(Data, [], Input, Skip). escape_json(<>, Acc1, Input, Skip) when Byte < 32 -> Acc2 = [Acc1 | escape(Byte)], escape_json(Rest, Acc2, Input, Skip + 1); escape_json(<>, Acc1, Input, Skip) when Byte < 34 -> escape_json_chunk(Rest, Acc1, Input, Skip, 1); escape_json(<>, Acc1, Input, Skip) when Byte =:= 34 -> Acc2 = [Acc1 | escape(Byte)], escape_json(Rest, Acc2, Input, Skip + 1); escape_json(<>, Acc1, Input, Skip) when Byte < 92 -> escape_json_chunk(Rest, Acc1, Input, Skip, 1); escape_json(<>, Acc, Input, Skip) when Byte =:= 92 -> Acc2 = [Acc | escape(Byte)], escape_json(Rest, Acc2, Input, Skip + 1); escape_json(<>, Acc, Input, Skip) when Byte < 128 -> escape_json_chunk(Rest, Acc, Input, Skip, 1); escape_json(<>, Acc, Input, Skip) when Char =< 2047 -> escape_json_chunk(Rest, Acc, Input, Skip, 2); escape_json(<>, Acc, Input, Skip) when Char =< 65535 -> escape_json_chunk(Rest, Acc, Input, Skip, 3); escape_json(<<_Char/utf8,Rest/bitstring>>, Acc, Input, Skip) -> escape_json_chunk(Rest, Acc, Input, Skip, 4); escape_json(<<>>, Acc, _Input, _Skip) -> Acc; escape_json(<>, _Acc, Input, _Skip) -> error_invalid_byte_error(Byte, Input). escape_json_chunk(<>, Acc, Input, Skip, Len) when Byte < 32 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_json(Rest, Acc2, Input, Skip + Len + 1); escape_json_chunk(<>, Acc, Input, Skip, Len) when Byte < 34 -> escape_json_chunk(Rest, Acc, Input, Skip, Len + 1); escape_json_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 34 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_json(Rest, Acc2, Input, Skip + Len + 1); escape_json_chunk(<>, Acc, Input, Skip, Len) when Byte < 92 -> escape_json_chunk(Rest, Acc, Input, Skip, Len + 1); escape_json_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 92 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_json(Rest, Acc2, Input, Skip + Len + 1); escape_json_chunk(<>, Acc, Input, Skip, Len) when Byte < 128 -> escape_json_chunk(Rest, Acc, Input, Skip, Len + 1); escape_json_chunk(<>, Acc, Input, Skip, Len) when Char =< 2047 -> escape_json_chunk(Rest, Acc, Input, Skip, Len + 2); escape_json_chunk(<>, Acc, Input, Skip, Len) when Char =< 65535 -> escape_json_chunk(Rest, Acc, Input, Skip, Len + 3); escape_json_chunk(<<_Char/utf8,Rest/bitstring>>, Acc, Input, Skip, Len) -> escape_json_chunk(Rest, Acc, Input, Skip, Len + 4); escape_json_chunk(<<>>, Acc, Input, Skip, Len) -> Part = binary_part(Input, Skip, Len), [Acc | Part]; escape_json_chunk(<>, _Acc, Input, _Skip, _Len) -> error_invalid_byte_error(Byte, Input). escape_unicode(Data, Input, Skip) -> escape_unicode(Data, [], Input, Skip). escape_unicode(<>, Acc, Input, Skip) when Byte =:= 0 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 1 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 2 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 3 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 4 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 5 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 6 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 7 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 8 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 9 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 10 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 11 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 12 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 13 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 14 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 15 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 16 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 17 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 18 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 19 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 20 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 21 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 22 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 23 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 24 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 25 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 26 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 27 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 28 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 29 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 30 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 31 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 32 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 33 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 34 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 35 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 36 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 37 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 38 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 39 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 40 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 41 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 42 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 43 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 44 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 45 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 46 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 47 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 48 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 49 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 50 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 51 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 52 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 53 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 54 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 55 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 56 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 57 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 58 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 59 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 60 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 61 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 62 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 63 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 64 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 65 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 66 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 67 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 68 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 69 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 70 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 71 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 72 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 73 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 74 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 75 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 76 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 77 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 78 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 79 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 80 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 81 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 82 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 83 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 84 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 85 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 86 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 87 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 88 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 89 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 90 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 91 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 92 -> Acc2 = [Acc | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 93 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 94 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 95 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 96 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 97 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 98 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 99 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 100 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 101 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 102 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 103 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 104 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 105 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 106 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 107 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 108 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 109 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 110 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 111 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 112 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 113 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 114 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 115 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 116 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 117 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 118 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 119 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 120 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 121 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 122 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 123 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 124 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 125 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 126 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Byte =:= 127 -> escape_unicode_chunk(Rest, Acc, Input, Skip, 1); escape_unicode(<>, Acc, Input, Skip) when Char =< 255 -> Acc2 = [Acc, <<"\\u00">> | integer_to_list(Char, 16)], escape_unicode(Rest, Acc2, Input, Skip + 2); escape_unicode(<>, Acc, Input, Skip) when Char =< 2047 -> Acc2 = [Acc, <<"\\u0">> | integer_to_list(Char, 16)], escape_unicode(Rest, Acc2, Input, Skip + 2); escape_unicode(<>, Acc, Input, Skip) when Char =< 4095 -> Acc2 = [Acc, <<"\\u0">> | integer_to_list(Char, 16)], escape_unicode(Rest, Acc2, Input, Skip + 3); escape_unicode(<>, Acc, Input, Skip) when Char =< 65535 -> Acc2 = [Acc, <<"\\u">> | integer_to_list(Char, 16)], escape_unicode(Rest, Acc2, Input, Skip + 3); escape_unicode(<>, Acc, Input, Skip) -> _char@2 = Char - 65536, Acc2 = [Acc, <<"\\uD">>, integer_to_list(2048 bor (_char@2 bsr 10), 16), <<"\\uD">> | integer_to_list(3072 bor _char@2 band 1023, 16)], escape_unicode(Rest, Acc2, Input, Skip + 4); escape_unicode(<<>>, Acc, _Input, _Skip) -> Acc; escape_unicode(<>, _Acc, Input, _Skip) -> error_invalid_byte_error(Byte, Input). escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 0 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 1 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 2 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 3 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 4 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 5 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 6 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 7 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 8 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 9 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 10 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 11 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 12 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 13 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 14 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 15 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 16 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 17 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 18 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 19 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 20 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 21 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 22 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 23 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 24 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 25 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 26 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 27 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 28 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 29 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 30 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 31 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 32 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 33 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 34 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 35 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 36 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 37 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 38 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 39 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 40 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 41 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 42 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 43 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 44 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 45 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 46 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 47 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 48 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 49 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 50 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 51 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 52 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 53 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 54 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 55 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 56 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 57 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 58 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 59 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 60 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 61 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 62 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 63 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 64 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 65 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 66 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 67 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 68 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 69 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 70 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 71 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 72 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 73 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 74 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 75 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 76 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 77 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 78 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 79 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 80 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 81 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 82 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 83 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 84 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 85 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 86 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 87 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 88 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 89 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 90 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 91 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 92 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part | escape(Byte)], escape_unicode(Rest, Acc2, Input, Skip + Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 93 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 94 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 95 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 96 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 97 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 98 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 99 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 100 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 101 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 102 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 103 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 104 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 105 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 106 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 107 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 108 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 109 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 110 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 111 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 112 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 113 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 114 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 115 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 116 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 117 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 118 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 119 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 120 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 121 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 122 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 123 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 124 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 125 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 126 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Byte =:= 127 -> escape_unicode_chunk(Rest, Acc, Input, Skip, Len + 1); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Char =< 255 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part, <<"\\u00">> | integer_to_list(Char, 16)], escape_unicode(Rest, Acc2, Input, Skip + Len + 2); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Char =< 2047 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part, <<"\\u0">> | integer_to_list(Char, 16)], escape_unicode(Rest, Acc2, Input, Skip + Len + 2); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Char =< 4095 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part, <<"\\u0">> | integer_to_list(Char, 16)], escape_unicode(Rest, Acc2, Input, Skip + Len + 3); escape_unicode_chunk(<>, Acc, Input, Skip, Len) when Char =< 65535 -> Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part, <<"\\u">> | integer_to_list(Char, 16)], escape_unicode(Rest, Acc2, Input, Skip + Len + 3); escape_unicode_chunk(<>, Acc, Input, Skip, Len) -> _char@2 = Char - 65536, Part = binary_part(Input, Skip, Len), Acc2 = [Acc, Part, <<"\\uD">>, integer_to_list(2048 bor (_char@2 bsr 10), 16), <<"\\uD">> | integer_to_list(3072 bor _char@2 band 1023, 16) ], escape_unicode(Rest, Acc2, Input, Skip + Len + 4); escape_unicode_chunk(<<>>, Acc, Input, Skip, Len) -> Part = binary_part(Input, Skip, Len), [Acc | Part]; escape_unicode_chunk(<>, _Acc, Input, _Skip, _Len) -> error_invalid_byte_error(Byte, Input). key(String, Escape) when is_binary(String) -> Escape(String, String, 0); key(Atom, Escape) when is_atom(Atom) -> String = atom_to_binary(Atom, utf8), Escape(String, String, 0); key(_charlist@1, Escape) when is_list(_charlist@1) -> String = list_to_binary(_charlist@1), Escape(String, String, 0); key(Int, Escape) when is_integer(Int) -> String = integer_to_binary(Int), Escape(String, String, 0). list([], _Escape) -> <<"[]">>; list([First | Tail], Escape) -> [91, value(First, Escape) | list_loop(Tail, Escape)]. list_loop([], _Escape) -> [93]; list_loop([First | Tail], Escape) -> [44, value(First, Escape) | list_loop(Tail, Escape)]. map_naive([{Key, Value} | Tail], Escape) -> [<<"{\"">>, key(Key, Escape), <<"\":">>, value(Value, Escape) | map_naive_loop(Tail, Escape)]. map_naive_loop([], _Escape) -> [$}]; map_naive_loop([{Key, Value} | Tail], Escape) -> [<<",\"">>, key(Key, Escape), <<"\":">>, value(Value, Escape) | map_naive_loop(Tail, Escape)]. error_invalid_byte_error(Byte, Input) -> error({invalid_byte, <<"0x"/utf8,(integer_to_binary(Byte, 16))/binary>>, Input}). value(Value, Escape) when is_atom(Value) -> encode_atom(Value, Escape); value(Value, Escape) when is_binary(Value) -> encode_string(Value, Escape); value(Value, _Escape) when is_integer(Value) -> integer(Value); value(Value, _Escape) when is_float(Value) -> float(Value); value([{_, _} | _] = Keyword, Escape) -> map_naive(Keyword, Escape); value({Y, M, D}, Escape) when is_integer(Y) andalso Y >= 0 andalso Y =< 9999 andalso is_integer(M) andalso M >= 1 andalso M =< 12 andalso is_integer(D) andalso D >= 1 andalso D =< 31 -> DateTime = io_lib:format("~4..0b-~2..0b-~2..0b", [Y, M, D]), encode_string(iolist_to_binary(DateTime), Escape); value({{Y, M, D}, {H, I, S}}, Escape) when is_integer(Y) andalso Y >= 0 andalso Y =< 9999 andalso is_integer(M) andalso M >= 1 andalso M =< 12 andalso is_integer(D) andalso D >= 1 andalso D =< 31 andalso is_integer(H) andalso H >= 0 andalso H =< 23 andalso is_integer(I) andalso I >= 0 andalso I =< 59 andalso is_integer(S) andalso S >= 0 andalso S =< 59 -> Dt = io_lib:format("~4..0b-~2..0b-~2..0bT~2..0b:~2..0b:~sZ", [Y, M, D, H, I, integer_to_list(S)]), encode_string(iolist_to_binary(Dt), Escape); value({{Y, M, D}, {H, I, S}}, Escape) when is_integer(Y) andalso Y >= 0 andalso Y =< 9999 andalso is_integer(M) andalso M >= 1 andalso M =< 12 andalso is_integer(D) andalso D >= 1 andalso D =< 31 andalso is_integer(H) andalso H >= 0 andalso H =< 23 andalso is_integer(I) andalso I >= 0 andalso I =< 59 andalso is_float(S) andalso S >= 0 andalso S < 60 -> Dt = io_lib:format("~4..0b-~2..0b-~2..0bT~2..0b:~2..0b:~sZ", [Y, M, D, H, I, float_to_binary(S, [short])]), encode_string(iolist_to_binary(Dt), Escape); value(Value, Escape) when is_list(Value) -> list(Value, Escape); value(Value, Escape) when is_map(Value) -> case maps:to_list(Value) of [] -> <<"{}">>; Keyword -> map_naive(Keyword, Escape) end.