-module(ywt_core_ffi). -export([decode_json_to_dynamic/1, is_base64url_unpadded/1, random_id/0]). random_id() -> binary:encode_hex( crypto:strong_rand_bytes(16)). is_base64url_unpadded(Bin) when is_binary(Bin) -> byte_size(Bin) rem 4 =/= 1 andalso is_base64url_bytes(Bin). is_base64url_bytes(<<>>) -> true; is_base64url_bytes(<>) when C >= $A, C =< $Z; C >= $a, C =< $z; C >= $0, C =< $9; C =:= $-; C =:= $_ -> is_base64url_bytes(Rest); is_base64url_bytes(_) -> false. decode_json_to_dynamic(Json) -> try Decoders = #{object_finish => fun object_finish_keep_last/2}, case json:decode(Json, ok, Decoders) of {Decoded, ok, <<>>} -> {ok, Decoded}; {_, ok, <>} -> {error, {unexpected_byte, hex(ExtraByte)}} end catch error:unexpected_end -> {error, unexpected_end_of_input}; error:{invalid_byte, InvalidByte} -> {error, {unexpected_byte, hex(InvalidByte)}}; error:{unexpected_sequence, Bytes} -> {error, {unexpected_sequence, Bytes}} end. object_finish_keep_last(Pairs, Acc) -> {maps:from_list(lists:reverse(Pairs)), Acc}. hex(I) -> H = list_to_binary(integer_to_list(I, 16)), <<"0x"/utf8, H/binary>>.