% @doc These functions will read a value or error out immediately, with useful errorinfo applied on top. % % TODO: keep? remove? -module(jsonpull_expect). -export([ null/1, boolean/1, string/1, iolist/1, existing_atom/1, number/1, integer/1, float/1, array/1, element/1, object/1, key/1 ]). -export([ format_error/2 ]). -define(WRAP(X), X(Bin) when is_binary(Bin) -> case jsonpull:X(Bin) of {ok, V} -> V; {error, E} -> erlang:error(E, [Bin], [{error_info, #{cause => E}}]) end; X(Arg) -> erlang:error(badarg, [Arg], [{error_info, #{cause => not_binary}}])). -spec null(JSON :: binary()) -> {null, Rest :: binary()}. ?WRAP(null). -spec boolean(JSON :: binary()) -> {boolean, Rest :: binary()}. ?WRAP(boolean). -spec string(JSON :: binary()) -> {binary(), Rest :: binary()}. ?WRAP(string). -spec iolist(JSON :: binary()) -> {iolist(), Rest :: binary()}. ?WRAP(iolist). -spec existing_atom(JSON :: binary()) -> {atom(), Rest :: binary()}. ?WRAP(existing_atom). -spec number(JSON :: binary()) -> {binary(), Rest :: binary()}. ?WRAP(number). -spec integer(JSON :: binary()) -> {integer(), Rest :: binary()}. ?WRAP(integer). -spec float(JSON :: binary()) -> {float(), Rest :: binary()}. ?WRAP(float). -spec array(JSON :: binary()) -> {begin_array, Rest :: binary()}. ?WRAP(array). -spec element(JSON :: binary()) -> {element | end_array, Rest :: binary()}. ?WRAP(element). -spec object(JSON :: binary()) -> {begin_object, Rest :: binary()}. ?WRAP(object). -spec key(JSON :: binary()) -> {binary() | end_object, Rest :: binary()}. ?WRAP(key). % @private format_error(system_limit, _) -> #{}; format_error(_, [{_, F, As, Info}|_]) -> ErrorInfoMap = proplists:get_value(error_info, Info, #{}), Cause = maps:get(cause, ErrorInfoMap, none), do_format_error(F, As, Cause). do_format_error(_, _, not_binary) -> #{ 1 => "should be a binary" }; do_format_error(_, _, not_null) -> #{ reason => "the next value is not a null" }; do_format_error(_, _, not_boolean) -> #{ reason => "the next value is not a boolean" }; do_format_error(_, _, not_string) -> #{ reason => "the next value is not a string" }; do_format_error(_, _, unterminated_string) -> #{ reason => "the string is missing one or more terminators" }; do_format_error(_, _, invalid_escape_sequence) -> #{ reason => "the string contains an invalid escape sequence" }; do_format_error(_, _, not_existing_atom) -> #{ reason => "not an already existing atom" }; do_format_error(_, _, not_number) -> #{ reason => "the next value is not a number" }; do_format_error(_, _, not_integer) -> #{ reason => "the next value is not an integer" }; do_format_error(_, _, not_float) -> #{ reason => "the next value is not a float" }; do_format_error(_, _, not_array) -> #{ reason => "the next value is not an array" }; do_format_error(_, _, not_object) -> #{ reason => "the next value is not an object" }; do_format_error(_, _, missing_colon_after_key) -> #{ reason => "there is no : following the key" }; do_format_error(_, _, unterminated_key) -> #{ reason => "the key is missing one or more terminators" }; do_format_error(_, _, key_not_string) -> #{ reason => "the key is not a string" }.