Current section

Files

Jump to
gleam_bson src bson@decoder.erl
Raw

src/bson@decoder.erl

-module(bson@decoder).
-compile(no_auto_import).
-export([decode/1]).
-spec decode(bitstring()) -> {ok, list({binary(), bson@types:value()})} |
{error, nil}.
decode(Data) ->
case decode_document(Data) of
{ok, {document, Doc}} ->
{ok, Doc};
{error, nil} ->
{error, nil}
end.
-spec decode_document(bitstring()) -> {ok, bson@types:value()} | {error, nil}.
decode_document(Data) ->
Total_size = gleam@bit_string:byte_size(Data),
Last_byte = gleam@bit_string:slice(Data, Total_size, -1),
case Last_byte =:= {ok, <<0>>} of
true ->
<<Given_size:32/little-integer, Rest/bitstring>> = Data,
case Total_size =:= Given_size of
true ->
case gleam@bit_string:slice(Rest, 0, (Total_size - 4) - 1) of
{ok, Body} ->
case decode_body(Body, []) of
{ok, Body@1} ->
{ok, {document, Body@1}};
{error, nil} ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
false ->
{error, nil}
end;
false ->
{error, nil}
end.
-spec decode_body(bitstring(), list({binary(), bson@types:value()})) -> {ok,
list({binary(),
bson@types:value()})} |
{error, nil}.
decode_body(Data, Storage) ->
case gleam@bit_string:byte_size(Data) =:= 0 of
true ->
{ok, Storage};
false ->
<<Code:8, Data@1/bitstring>> = Data,
Total_size = gleam@bit_string:byte_size(Data@1),
case consume_till_zero(Data@1, <<>>) of
{ok, Key} ->
Key_size = gleam@bit_string:byte_size(Key),
case gleam@bit_string:to_string(Key) of
{ok, Key@1} ->
case gleam@bit_string:slice(
Data@1,
Key_size
+ 1,
(Total_size
- Key_size)
- 1
) of
{ok, Rest} ->
Kind = {kind, <<Code>>},
case Kind of
Kind@1 when Kind@1 =:= {kind, <<16#01>>} ->
<<Value/little-float,
Rest@1/bitstring>> = Rest,
decode_body(
Rest@1,
[{Key@1, {double, Value}} |
Storage]
);
Kind@2 when Kind@2 =:= {kind, <<16#07>>} ->
<<Value@1:96/bitstring,
Rest@2/bitstring>> = Rest,
case bson@object_id:from_bit_string(
Value@1
) of
{ok, Oid} ->
decode_body(
Rest@2,
[{Key@1,
{object_id, Oid}} |
Storage]
);
{error, nil} ->
{error, nil}
end;
Kind@3 when Kind@3 =:= {kind, <<16#08>>} ->
<<Value@2:8, Rest@3/bitstring>> = Rest,
case Value@2 of
1 ->
decode_body(
Rest@3,
[{Key@1,
{boolean, true}} |
Storage]
);
0 ->
decode_body(
Rest@3,
[{Key@1,
{boolean, false}} |
Storage]
);
_@1 ->
{error, nil}
end;
Kind@4 when Kind@4 =:= {kind, <<16#0A>>} ->
decode_body(
Rest,
[{Key@1, null} | Storage]
);
Kind@5 when Kind@5 =:= {kind, <<16#10>>} ->
<<Value@3:32/little,
Rest@4/bitstring>> = Rest,
decode_body(
Rest@4,
[{Key@1, {integer, Value@3}} |
Storage]
);
Kind@6 when Kind@6 =:= {kind, <<16#12>>} ->
<<Value@4:64/little,
Rest@5/bitstring>> = Rest,
decode_body(
Rest@5,
[{Key@1, {integer, Value@4}} |
Storage]
);
Kind@7 when Kind@7 =:= {kind, <<16#02>>} ->
<<Given_size:32/little-integer,
Rest@6/bitstring>> = Rest,
case consume_till_zero(Rest@6, <<>>) of
{ok, Str} ->
Str_size = gleam@bit_string:byte_size(
Str
),
case Given_size
=:= (Str_size
+ 1) of
true ->
case gleam@bit_string:to_string(
Str
) of
{ok, Str@1} ->
case gleam@bit_string:slice(
Rest@6,
Str_size
+ 1,
(gleam@bit_string:byte_size(
Rest@6
)
- Str_size)
- 1
) of
{ok,
Rest@7} ->
decode_body(
Rest@7,
[{Key@1,
{str,
Str@1}} |
Storage]
);
{error,
nil} ->
{error,
nil}
end;
{error, nil} ->
{error, nil}
end;
false ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
Kind@8 when (Kind@8 =:= {kind,
<<16#03>>}) orelse (Kind@8 =:= {kind,
<<16#04>>}) ->
<<Doc_size:32/little-integer,
_@2/bitstring>> = Rest,
case gleam@bit_string:slice(
Rest,
0,
Doc_size
) of
{ok, Doc} ->
case decode_document(Doc) of
{ok, Doc@1} ->
Doc@3 = case Kind@8 of
Kind@9 when Kind@9 =:= {kind,
<<16#03>>} ->
{ok, Doc@1};
Kind@10 when Kind@10 =:= {kind,
<<16#04>>} ->
case Doc@1 of
{document,
Doc@2} ->
List = begin
_pipe = Doc@2,
gleam@list:map(
_pipe,
fun(
Item
) ->
{begin
_pipe@1 = Item,
_pipe@2 = gleam@pair:first(
_pipe@1
),
gleam@int:parse(
_pipe@2
)
end,
begin
_pipe@3 = Item,
gleam@pair:second(
_pipe@3
)
end}
end
)
end,
case gleam@list:any(
List,
fun(
Item@1
) ->
gleam@result:is_error(
begin
_pipe@4 = Item@1,
gleam@pair:first(
_pipe@4
)
end
)
end
) of
true ->
{error,
nil};
false ->
{ok,
{array,
begin
_pipe@5 = List,
_pipe@8 = gleam@list:map(
_pipe@5,
fun(
Item@2
) ->
{ok,
First@1} = case begin
_pipe@6 = Item@2,
gleam@pair:first(
_pipe@6
)
end of
{ok,
First} -> {ok,
First};
_try ->
erlang:error(
#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"bson/decoder"/utf8>>,
function => <<"decode_body"/utf8>>,
line => 179}
)
end,
{First@1,
begin
_pipe@7 = Item@2,
gleam@pair:second(
_pipe@7
)
end}
end
),
_pipe@11 = gleam@list:sort(
_pipe@8,
fun(
A,
B
) ->
A_index = begin
_pipe@9 = A,
gleam@pair:first(
_pipe@9
)
end,
B_index = begin
_pipe@10 = B,
gleam@pair:first(
_pipe@10
)
end,
gleam@int:compare(
A_index,
B_index
)
end
),
gleam@list:map(
_pipe@11,
fun(
Item@3
) ->
_pipe@12 = Item@3,
gleam@pair:second(
_pipe@12
)
end
)
end}}
end;
_@3 ->
{error,
nil}
end;
_@4 ->
{error, nil}
end,
case Doc@3 of
{ok, Doc@4} ->
case Doc_size
=:= gleam@bit_string:byte_size(
Rest
) of
true ->
{ok,
[{Key@1,
Doc@4} |
Storage]};
false ->
case gleam@bit_string:slice(
Rest,
Doc_size,
gleam@bit_string:byte_size(
Rest
)
- Doc_size
) of
{ok,
Rest@8} ->
decode_body(
Rest@8,
[{Key@1,
Doc@4} |
Storage]
);
{error,
nil} ->
{error,
nil}
end
end;
{error, nil} ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
_@5 ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end
end.
-spec consume_till_zero(bitstring(), bitstring()) -> {ok, bitstring()} |
{error, nil}.
consume_till_zero(Data, Storage) ->
case gleam@bit_string:byte_size(Data) =:= 0 of
false ->
<<Ch:8, Rest/bitstring>> = Data,
case Ch =:= 0 of
true ->
{ok, Storage};
false ->
consume_till_zero(
Rest,
gleam@bit_string:append(Storage, <<Ch>>)
)
end;
true ->
{error, nil}
end.