Parcourir la source

API Change - No more {ok, Value} wrapping.

The encode and decode functions now return the value directly without
being wrapped in a tuple on success. If there is an error, it is
thrown. This is to more closely match the semantics of term_to_binary
and binary_to_term.
pull/8/merge
Paul J. Davis il y a 14 ans
Parent
révision
a2a7bc91af
7 fichiers modifiés avec 42 ajouts et 41 suppressions
  1. +5
    -1
      c_src/decoder.c
  2. +5
    -8
      c_src/encoder.c
  3. +12
    -7
      src/jiffy.erl
  4. +3
    -8
      test/001-yajl-tests.t
  5. +6
    -6
      test/002-literals.t
  6. +4
    -3
      test/004-strings.t
  7. +7
    -8
      test/util.erl

+ 5
- 1
c_src/decoder.c Voir le fichier

@ -284,6 +284,10 @@ dec_string(Decoder* d, ERL_NIF_TERM* value)
}
parse:
if(d->p[d->i-1] != '\"') {
return 0;
}
if(!has_escape) {
*value = enif_make_sub_binary(d->env, d->arg, st, (d->i - st - 1));
return 1;
@ -930,7 +934,7 @@ decode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
} else if(d->is_partial) {
ret = enif_make_tuple2(env, d->atoms->atom_partial, val);
} else {
ret = enif_make_tuple2(env, d->atoms->atom_ok, val);
ret = val;
}
done:

+ 5
- 8
c_src/encoder.c Voir le fichier

@ -424,8 +424,6 @@ encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
double dval;
long lval;
int is_partial = 0;
if(argc != 1) {
return enif_make_badarg(env);
}
@ -563,15 +561,15 @@ encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
goto done;
}
if(!enif_get_tuple(env, item, &arity, &tuple)) {
ret = enc_error(e, "invalid_object_pair");
ret = enc_error(e, "invalid_object_member");
goto done;
}
if(arity != 2) {
ret = enc_error(e, "invalid_object_pair");
ret = enc_error(e, "invalid_object_member_arity");
goto done;
}
if(!enc_string(e, tuple[0])) {
ret = enc_error(e, "invalid_object_key");
ret = enc_error(e, "invalid_object_member_key");
goto done;
}
if(!enc_colon(e)) {
@ -601,7 +599,6 @@ encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
stack = enif_make_list_cell(env, item, stack);
} else {
is_partial = 1;
if(!enc_unknown(e, curr)) {
ret = enc_error(e, "internal_error");
goto done;
@ -614,8 +611,8 @@ encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
goto done;
}
if(!is_partial) {
ret = enif_make_tuple2(env, e->atoms->atom_ok, item);
if(e->iolen == 0) {
ret = item;
} else {
ret = enif_make_tuple2(env, e->atoms->atom_partial, item);
}

+ 12
- 7
src/jiffy.erl Voir le fichier

@ -9,18 +9,23 @@
decode(Data) ->
case nif_decode(Data) of
{error, _} = Error ->
throw(Error);
{partial, EJson} ->
{ok, finish_decode(EJson)};
Else ->
Else
finish_decode(EJson);
EJson ->
EJson
end.
encode(Data) ->
case nif_encode(Data) of
{error, _} = Error ->
throw(Error);
{partial, IOData} ->
finish_encode(IOData, []);
Else ->
Else
IOData ->
IOData
end.
@ -59,14 +64,14 @@ finish_decode_arr([V | Vals], Acc) ->
finish_encode([], Acc) ->
%% No reverse! The NIF returned us
%% the pieces in reverse order.
{ok, Acc};
Acc;
finish_encode([<<_/binary>>=B | Rest], Acc) ->
finish_encode(Rest, [B | Acc]);
finish_encode([Val | Rest], Acc) when is_integer(Val) ->
Bin = list_to_binary(integer_to_list(Val)),
finish_encode(Rest, [Bin | Acc]);
finish_encode(_, _) ->
{error, invalid_ejson}.
throw({error, invalid_ejson}).
init() ->

+ 3
- 8
test/001-yajl-tests.t Voir le fichier

@ -12,6 +12,8 @@ main([]) ->
lists:foreach(fun(Case) -> test(Case) end, Cases),
etap:end_tests().
test({Name, Json, {error, _}=Erl}) ->
etap:is((catch jiffy:decode(Json)), Erl, Name);
test({Name, Json, Erl}) ->
etap:is(jiffy:decode(Json), Erl, Name).
@ -25,11 +27,4 @@ make_pair(FileName) ->
{BaseName, _} = lists:splitwith(fun(C) -> C /= $. end, FileName),
ErlFname = BaseName ++ ".erl",
{ok, [Term]} = file:consult(ErlFname),
case Term of
{error, _} ->
{BaseName, Json, Term};
{error, _, _} ->
{BaseName, Json, Term};
_ ->
{BaseName, Json, {ok, Term}}
end.
{BaseName, Json, Term}.

+ 6
- 6
test/002-literals.t Voir le fichier

@ -7,14 +7,14 @@ main([]) ->
code:add_pathz("test"),
etap:plan(6),
etap:is(jiffy:decode(<<"true">>), {ok, true}, "DEC: true -> true"),
etap:is(jiffy:encode(true), {ok, <<"true">>}, "ENC: true -> true"),
etap:is(jiffy:decode(<<"true">>), true, "DEC: true -> true"),
etap:is(jiffy:encode(true), <<"true">>, "ENC: true -> true"),
etap:is(jiffy:decode(<<"false">>), {ok, false}, "DEC: false -> false"),
etap:is(jiffy:encode(false), {ok, <<"false">>}, "ENC: false -> false"),
etap:is(jiffy:decode(<<"false">>), false, "DEC: false -> false"),
etap:is(jiffy:encode(false), <<"false">>, "ENC: false -> false"),
etap:is(jiffy:decode(<<"null">>), {ok, null}, "DEC: null -> null"),
etap:is(jiffy:encode(null), {ok, <<"null">>}, "ENC: null -> null"),
etap:is(jiffy:decode(<<"null">>), null, "DEC: null -> null"),
etap:is(jiffy:encode(null), <<"null">>, "ENC: null -> null"),
etap:end_tests().

+ 4
- 3
test/004-strings.t Voir le fichier

@ -6,7 +6,7 @@ main([]) ->
code:add_pathz("ebin"),
code:add_pathz("test"),
etap:plan(75),
etap:plan(76),
util:test_good(good()),
util:test_errors(errors()),
@ -32,6 +32,7 @@ good() ->
errors() ->
[
<<"\"foo">>,
<<"\"", 0, "\"">>,
<<"\"\\g\"">>,
<<"\"\\uFFFF\"">>,
@ -45,13 +46,13 @@ test_utf8([]) ->
test_utf8([Case | Rest]) ->
etap:fun_is(
fun({error, invalid_string}) -> true; (Else) -> Else end,
jiffy:encode(Case),
(catch jiffy:encode(Case)),
lists:flatten(io_lib:format("Invalid utf-8: ~p", [Case]))
),
Case2 = <<34, Case/binary, 34>>,
etap:fun_is(
fun({error, {_, invalid_string}}) -> true; (Else) -> Else end,
jiffy:decode(Case2),
(catch jiffy:decode(Case2)),
lists:flatten(io_lib:format("Invalid utf-8: ~p", [Case2]))
),
test_utf8(Rest).

+ 7
- 8
test/util.erl Voir le fichier

@ -14,29 +14,28 @@ ok_enc(E, _J) ->
lists:flatten(io_lib:format("Encoded ~p", [E])).
do_encode(E) ->
{ok, Data} = jiffy:encode(E),
{ok, iolist_to_binary(Data)}.
iolist_to_binary(jiffy:encode(E)).
error_mesg(J) ->
lists:flatten(io_lib:format("Decoding ~p returns an error.", [J])).
check_good({J, E}) ->
etap:is(jiffy:decode(J), {ok, E}, ok_dec(J, E)),
etap:is(do_encode(E), {ok, J}, ok_enc(E, J));
etap:is(jiffy:decode(J), E, ok_dec(J, E)),
etap:is(do_encode(E), J, ok_enc(E, J));
check_good({J, E, J2}) ->
etap:is(jiffy:decode(J), {ok, E}, ok_dec(J, E)),
etap:is(do_encode(E), {ok, J2}, ok_enc(E, J2)).
etap:is(jiffy:decode(J), E, ok_dec(J, E)),
etap:is(do_encode(E), J2, ok_enc(E, J2)).
check_error({J, E}) ->
etap:fun_is(
fun({error, E1}) when E1 == E -> true; (E1) -> E1 end,
jiffy:decode(J),
(catch jiffy:decode(J)),
error_mesg(J)
);
check_error(J) ->
etap:fun_is(
fun({error, _}) -> true; (Else) -> Else end,
jiffy:decode(J),
(catch jiffy:decode(J)),
error_mesg(J)
).

Chargement…
Annuler
Enregistrer