Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add return_truncated decode flag #158

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
11 changes: 10 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,12 @@ 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())}.