diff options
author | Louis Pilfold <louis@lpil.uk> | 2021-09-07 19:36:31 +0100 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2021-09-07 19:36:31 +0100 |
commit | 945152e8075e04d91aac193608ecc84b769c7ba4 (patch) | |
tree | 3a60c06153419138ab58d97997709eb0d7fee5ee /src/gleam_stdlib.erl | |
parent | b611364f02679c6c44592082db6012f2c27a0750 (diff) | |
download | gleam_stdlib-945152e8075e04d91aac193608ecc84b769c7ba4.tar.gz gleam_stdlib-945152e8075e04d91aac193608ecc84b769c7ba4.zip |
URI percent encode and decode for JS
Diffstat (limited to 'src/gleam_stdlib.erl')
-rw-r--r-- | src/gleam_stdlib.erl | 71 |
1 files changed, 68 insertions, 3 deletions
diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl index f8f6851..9429f71 100644 --- a/src/gleam_stdlib.erl +++ b/src/gleam_stdlib.erl @@ -9,9 +9,22 @@ string_ends_with/2, string_pad/4, decode_tuple2/1, decode_tuple3/1, decode_tuple4/1, decode_tuple5/1, decode_tuple6/1, decode_map/1, bit_string_int_to_u32/1, bit_string_int_from_u32/1, decode_result/1, - bit_string_slice/3, decode_bit_string/1, compile_regex/2, - regex_check/2, regex_split/2, regex_scan/2, base_decode64/1, - parse_query/1, bit_string_concat/1]). + bit_string_slice/3, decode_bit_string/1, compile_regex/2, regex_scan/2, + percent_encode/1, percent_decode/1, regex_check/2, regex_split/2, + base_decode64/1, parse_query/1, bit_string_concat/1]). + +%% Taken from OTP's uri_string module +-define(DEC2HEX(X), + if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0; + ((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10 + end). + +%% Taken from OTP's uri_string module +-define(HEX2DEC(X), + if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0; + ((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10; + ((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10 + end). should_equal(Actual, Expected) -> ?assertEqual(Expected, Actual), @@ -245,3 +258,55 @@ parse_query(Query) -> end, Pairs), {ok, Pairs1} end. + +percent_encode(B) -> percent_encode(B, <<>>). +percent_encode(<<>>, Acc) -> + Acc; +percent_encode(<<H,T/binary>>, Acc) -> + case percent_ok(H) of + true -> + percent_encode(T, <<Acc/binary,H>>); + false -> + <<A:4,B:4>> = <<H>>, + percent_encode(T, <<Acc/binary,$%,(?DEC2HEX(A)),(?DEC2HEX(B))>>) + end. + +percent_decode(Cs) -> percent_decode(Cs, <<>>). +percent_decode(<<$%, C0, C1, Cs/binary>>, Acc) -> + case is_hex_digit(C0) andalso is_hex_digit(C1) of + true -> + B = ?HEX2DEC(C0)*16+?HEX2DEC(C1), + percent_decode(Cs, <<Acc/binary, B>>); + false -> + {error, nil} + end; +percent_decode(<<C,Cs/binary>>, Acc) -> + percent_decode(Cs, <<Acc/binary, C>>); +percent_decode(<<>>, Acc) -> + check_utf8(Acc). + +percent_ok($!) -> true; +percent_ok($$) -> true; +percent_ok($') -> true; +percent_ok($() -> true; +percent_ok($)) -> true; +percent_ok($*) -> true; +percent_ok($+) -> true; +percent_ok($-) -> true; +percent_ok($.) -> true; +percent_ok($_) -> true; +percent_ok($~) -> true; +percent_ok(C) when $0 =< C, C =< $9 -> true; +percent_ok(C) when $A =< C, C =< $Z -> true; +percent_ok(C) when $a =< C, C =< $z -> true; +percent_ok(_) -> false. + +is_hex_digit(C) -> + ($0 =< C andalso C =< $9) orelse ($a =< C andalso C =< $f) orelse ($A =< C andalso C =< $F). + +check_utf8(Cs) -> + case unicode:characters_to_list(Cs) of + {incomplete, _, _} -> {error, nil}; + {error, _, _} -> {error, nil}; + _ -> {ok, Cs} + end. |