Skip to content

Commit

Permalink
Add return_truncated decode flag
Browse files Browse the repository at this point in the history
  • Loading branch information
sargun committed Nov 22, 2017
1 parent dddb392 commit eac9574
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 2 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ The options for decode are:
JSON term is decoded the return value of decode/2 becomes
`{has_trailer, FirstTerm, RestData::iodata()}`. This is useful to
decode multiple terms in a single binary.
* `return_truncated` - If the JSON passed to the decoder is incomplete
return `{truncated, Pos}`, where `Pos`, is the length of JSON read
before hitting the end of the interpretable term.
* `dedupe_keys` - If a key is repeated in a JSON object this flag
will ensure that the parsed object only contains a single entry
containing the last value seen. This mirrors the parsing beahvior
Expand Down
10 changes: 9 additions & 1 deletion c_src/decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ typedef struct {
size_t bytes_per_red;
int is_partial;
int return_maps;
int return_truncated;
int return_trailer;
int dedupe_keys;
int copy_strings;
Expand Down Expand Up @@ -84,6 +85,7 @@ dec_new(ErlNifEnv* env)
d->is_partial = 0;
d->return_maps = 0;
d->return_trailer = 0;
d->return_truncated = 0;
d->dedupe_keys = 0;
d->copy_strings = 0;
d->null_term = d->atoms->atom_null;
Expand Down Expand Up @@ -689,6 +691,8 @@ decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
#endif
} else if(enif_compare(val, d->atoms->atom_return_trailer) == 0) {
d->return_trailer = 1;
} else if(enif_compare(val, d->atoms->atom_return_truncated) == 0) {
d->return_truncated = 1;
} else if(enif_compare(val, d->atoms->atom_dedupe_keys) == 0) {
d->dedupe_keys = 1;
} else if(enif_compare(val, d->atoms->atom_copy_strings) == 0) {
Expand Down Expand Up @@ -1035,7 +1039,11 @@ decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}

if(dec_curr(d) != st_done) {
ret = dec_error(d, "truncated_json");
if (d->return_truncated)
ret = enif_make_tuple2(env, d->atoms->atom_truncated,
enif_make_int(d->env, d->i+1));
else
ret = dec_error(d, "truncated_json");
} else if(d->is_partial) {
ret = enif_make_tuple2(env, d->atoms->atom_partial, val);
} else {
Expand Down
2 changes: 2 additions & 0 deletions c_src/jiffy.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
st->atom_pretty = make_atom(env, "pretty");
st->atom_force_utf8 = make_atom(env, "force_utf8");
st->atom_iter = make_atom(env, "iter");
st->atom_truncated = make_atom(env, "truncated");
st->atom_bytes_per_iter = make_atom(env, "bytes_per_iter");
st->atom_return_maps = make_atom(env, "return_maps");
st->atom_return_trailer = make_atom(env, "return_trailer");
st->atom_return_truncated = make_atom(env, "return_truncated");
st->atom_has_trailer = make_atom(env, "has_trailer");
st->atom_nil = make_atom(env, "nil");
st->atom_use_nil = make_atom(env, "use_nil");
Expand Down
2 changes: 2 additions & 0 deletions c_src/jiffy.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ typedef struct {
ERL_NIF_TERM atom_pretty;
ERL_NIF_TERM atom_force_utf8;
ERL_NIF_TERM atom_iter;
ERL_NIF_TERM atom_truncated;
ERL_NIF_TERM atom_bytes_per_iter;
ERL_NIF_TERM atom_return_maps;
ERL_NIF_TERM atom_return_trailer;
ERL_NIF_TERM atom_return_truncated;
ERL_NIF_TERM atom_has_trailer;
ERL_NIF_TERM atom_nil;
ERL_NIF_TERM atom_use_nil;
Expand Down
4 changes: 3 additions & 1 deletion src/jiffy.erl
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@
-endif.

-type jiffy_decode_result() :: json_value()
| {has_trailer, json_value(), binary()}.
| {has_trailer, json_value(), binary()}
| {truncated, non_neg_integer()}.

-type decode_option() :: return_maps
| use_nil
| return_trailer
| return_truncated
| dedupe_keys
| {null_term, any()}
| {bytes_per_iter, non_neg_integer()}
Expand Down
25 changes: 25 additions & 0 deletions test/jiffy_18_return_truncated_tests.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
% This file is part of Jiffy released under the MIT license.
% See the LICENSE file for more information.

-module(jiffy_18_return_truncated_tests).

-include_lib("eunit/include/eunit.hrl").

cases() ->
[
{<<"">>, 1},
{<<"{">>, 2}
].

return_truncated_test_() ->
Opts = [return_truncated],
{"Test return_truncated", lists:map(fun({Data, Pos}) ->
?_assertEqual({truncated, Pos}, jiffy:decode(Data, Opts))
end, cases())}.

error_truncated_test_() ->
Opts = [],
{"Test truncated error case", lists:map(fun({Data, Pos}) ->
Error = {error, {Pos, truncated_json}},
?_assertException(throw, Error, jiffy:decode(Data, Opts))
end, cases())}.

0 comments on commit eac9574

Please sign in to comment.