Skip to content

Commit

Permalink
feat: Allow explicit encoding of long integers (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alberdi authored Aug 27, 2024
1 parent 40a8c1a commit 17500ac
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 9 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ The following table represents the association between Erlang types and BSON typ
| `{javascript, [ tuple() \| _ ], binary()}` | JavaScript code with scope (15) |
| `I32 :: integer() when -16#80000000 =< I32, I32 =< 16#7fffffff` | 32-bit integer (16) |
| `{timestamp, binary(), binary()}` | Timestamp (17) |
| `I64 :: integer() when -16#80000000 =< I64, I64 =< 16#7fffffff` | 64-bit integer (18) |
| `I64 :: integer() when -16#8000000000000000 =< I64, I64 =< 16#7fffffffffffffff` | 64-bit integer (18) |
| `{long, I64 :: integer()} when -16#8000000000000000 =< I64, I64 =< 16#7fffffffffffffff` | 64-bit integer (18) |
| `max_key` | Max key (127) |
| `min_key` | Min key (-1) |

Expand Down
1 change: 1 addition & 0 deletions src/nbson.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
-type value() ::
float()
| integer()
| {long, integer()}
| binary()
| undefined
| null
Expand Down
4 changes: 2 additions & 2 deletions src/nbson_decoder.erl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ decode(_Other) ->
Current :: term(),
Next :: [term()],
Result :: nbson:document() | {error, nbson:decode_error_reason()}.
next(<<>>, Current, [document]) ->
next(<<>>, Current, [document]) when is_map(Current) ->
Current;
next(<<Bin/binary>>, Current, [evalue, Type, ?EDOCUMENT, Elements | Next]) ->
evalue(Bin, Type, [elist, Current, Elements | Next]);
Expand All @@ -95,7 +95,7 @@ next(<<Bin/binary>>, Current, [pointer, Collection | Next]) ->
next(Bin, {pointer, Collection, Current}, Next);
next(<<Bin/binary>>, Current, [jscode | Next]) ->
next(Bin, {javascript, #{}, Current}, Next);
next(<<Bin/binary>>, Current, [label | Next]) ->
next(<<Bin/binary>>, Current, [label | Next]) when is_binary(Current) ->
next(Bin, binary_to_atom(Current, utf8), Next);
next(<<Bin/binary>>, Current, [jscodews | Next]) ->
document(Bin, #{}, [javascript, Current | Next]);
Expand Down
8 changes: 6 additions & 2 deletions src/nbson_encoder.erl
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,17 @@ encode_value({javascript, Scope, Code}) when is_map(Scope), is_binary(Code) ->
Encoded = <<?INT32(byte_size(CStringCode)), CStringCode/binary, (EncodedScope)/binary>>,
{?JSCODEWS_TYPE, <<?INT32(byte_size(Encoded) + 4), Encoded/binary>>}
end;
encode_value(V) when is_integer(V), -16#80000000 =< V, V =< 16#7fffffff ->
{?INT32_TYPE, <<?INT32(V)>>};
encode_value({timestamp, Inc, Time}) ->
{?TIMESTAMP_TYPE, <<?INT32(Inc), ?INT32(Time)>>};
encode_value(V) when is_integer(V), -16#80000000 =< V, V =< 16#7fffffff ->
{?INT32_TYPE, <<?INT32(V)>>};
encode_value(V) when is_integer(V), -16#8000000000000000 =< V, V =< 16#7fffffffffffffff ->
{?INT64_TYPE, <<?INT64(V)>>};
encode_value(V) when is_integer(V) ->
{error, {integer_too_large, V}};
encode_value({long, V}) when is_integer(V), -16#8000000000000000 =< V, V =< 16#7fffffffffffffff ->
{?INT64_TYPE, <<?INT64(V)>>};
encode_value({long, V}) when is_integer(V) ->
{error, {integer_too_large, V}}.

-spec foldwhile(F, AccIn, List) -> Result when
Expand Down
8 changes: 8 additions & 0 deletions test/nbson_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ all() ->
double,
embdoc,
int64,
int64_explicit,
js,
js_ws,
max_key,
Expand Down Expand Up @@ -227,6 +228,13 @@ int64(_Config) ->
{ok, BaseMap} = nbson:decode(BaseBin),
{ok, BaseBin} = nbson:encode(BaseMap).

int64_explicit() ->
[{userdata, [{doc, "Tests explicit int64 data type BSON decoder API."}]}].
int64_explicit(_Config) ->
BaseBin = <<20, 0, 0, 0, 18, 105, 110, 116, 54, 52, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0>>,
BaseMap = #{<<"int64">> => {long, 64}},
{ok, BaseBin} = nbson:encode(BaseMap).

js() ->
[{userdata, [{doc, "Tests javascript data type BSON decoder API."}]}].
js(_Config) ->
Expand Down
13 changes: 9 additions & 4 deletions test/nbson_monad_errors_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,14 @@ decode_errors(_Config) ->
encode_errors() ->
[{userdata, [{doc, "Tests errors on BSON encoder API."}]}].
encode_errors(_Config) ->
BaseMap = #{<<"int64">> => (16#7fffffffffffffff + 1)},
{error, {integer_too_large, V}} = nbson:encode(BaseMap),
TooBigInt = 16#7fffffffffffffff + 1,
BaseMap = #{<<"int64">> => TooBigInt},
{error, {integer_too_large, TooBigInt}} = nbson:encode(BaseMap),

BasePL = [{<<"int64">>, TooBigInt}],
{error, {integer_too_large, TooBigInt}} = nbson:encode(BasePL),

BaseLongPL = [{<<"int64">>, {long, TooBigInt}}],
{error, {integer_too_large, TooBigInt}} = nbson:encode(BaseLongPL),

BasePL = [{<<"int64">>, (16#7fffffffffffffff + 1)}],
{error, {integer_too_large, V}} = nbson:encode(BasePL),
ok.

0 comments on commit 17500ac

Please sign in to comment.