Current section

Files

Jump to
gleam_bson src bson@encoder.erl
Raw

src/bson@encoder.erl

-module(bson@encoder).
-compile(no_auto_import).
-export([encode/1]).
-export_type([entity/0]).
-type entity() :: {entity, bson@types:kind(), bitstring()}.
-spec encode(list({binary(), bson@types:value()})) -> bitstring().
encode(Doc) ->
case document(Doc) of
{entity, _@1, Value} ->
Value
end.
-spec document(list({binary(), bson@types:value()})) -> entity().
document(Doc) ->
Doc@1 = begin
_pipe = Doc,
_pipe@1 = gleam@list:reverse(_pipe),
_pipe@2 = gleam@list:map(_pipe@1, fun(Kv) -> encode_kv(Kv) end),
gleam@bit_string:concat(_pipe@2)
end,
Size = gleam@bit_string:byte_size(Doc@1) + 5,
{entity,
{kind, <<16#03>>},
begin
_pipe@3 = [<<Size:32/little>>, Doc@1, <<0>>],
gleam@bit_string:concat(_pipe@3)
end}.
-spec encode_kv({binary(), bson@types:value()}) -> bitstring().
encode_kv(Pair) ->
Key = <<(erlang:element(1, Pair))/binary, 0>>,
Value@7 = case erlang:element(2, Pair) of
null ->
null();
{str, Value} ->
string(Value);
{array, Value@1} ->
array(Value@1);
{double, Value@2} ->
double(Value@2);
{boolean, Value@3} ->
boolean(Value@3);
{integer, Value@4} ->
integer(Value@4);
{document, Value@5} ->
document(Value@5);
{object_id, Value@6} ->
object_id(Value@6)
end,
case Value@7 of
{entity, Kind, Value@8} ->
_pipe = [erlang:element(2, Kind), Key, Value@8],
gleam@bit_string:concat(_pipe)
end.
-spec array(list(bson@types:value())) -> entity().
array(List) ->
case begin
_pipe = List,
_pipe@2 = gleam@list:index_map(
_pipe,
fun(Index, Item) ->
{begin
_pipe@1 = Index,
gleam@int:to_string(_pipe@1)
end,
Item}
end
),
_pipe@3 = gleam@list:reverse(_pipe@2),
document(_pipe@3)
end of
{entity, _@1, Value} ->
{entity, {kind, <<16#04>>}, Value}
end.
-spec string(binary()) -> entity().
string(Value) ->
Length = gleam@bit_string:byte_size(<<Value/binary>>) + 1,
{entity, {kind, <<16#02>>}, <<Length:32/little, Value/binary, 0>>}.
-spec double(float()) -> entity().
double(Value) ->
{entity, {kind, <<16#01>>}, <<Value/little-float>>}.
-spec null() -> entity().
null() ->
{entity, {kind, <<16#0A>>}, <<>>}.
-spec boolean(boolean()) -> entity().
boolean(Value) ->
case Value of
true ->
{entity, {kind, <<16#08>>}, <<1>>};
false ->
{entity, {kind, <<16#08>>}, <<0>>}
end.
-spec integer(integer()) -> entity().
integer(Value) ->
case (Value < 2147483647) andalso (Value > -2147483648) of
true ->
{entity, {kind, <<16#10>>}, <<Value:32/little>>};
false ->
{entity, {kind, <<16#12>>}, <<Value:64/little>>}
end.
-spec object_id(bson@object_id:object_id()) -> entity().
object_id(Value) ->
{entity,
{kind, <<16#07>>},
begin
_pipe = Value,
bson@object_id:to_bit_string(_pipe)
end}.