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#05>>} ->
<<Byte_size:32/little-integer,
Sub_code:8,
Rest@1/bitstring>> = Rest,
Given_size = Byte_size
* 8,
<<Value:Given_size/bitstring,
Rest@2/bitstring>> = Rest@1,
Sub_kind = {sub_kind, <<Sub_code>>},
case Sub_kind of
Sub_kind@1 when Sub_kind@1 =:= {sub_kind,
<<16#0>>} ->
case bson@binary:from_bit_string(
Value
) of
{ok, Value@1} ->
decode_body(
Rest@2,
gleam@list:append(
Storage,
[{Key@1,
{binary,
Value@1}}]
)
);
{error, nil} ->
{error, nil}
end;
_@1 ->
{error, nil}
end;
Kind@2 when Kind@2 =:= {kind, <<16#01>>} ->
<<Value@2/little-float,
Rest@3/bitstring>> = Rest,
decode_body(
Rest@3,
gleam@list:append(
Storage,
[{Key@1, {double, Value@2}}]
)
);
Kind@3 when Kind@3 =:= {kind, <<16#07>>} ->
<<Value@3:96/bitstring,
Rest@4/bitstring>> = Rest,
case bson@object_id:from_bit_string(
Value@3
) of
{ok, Oid} ->
decode_body(
Rest@4,
gleam@list:append(
Storage,
[{Key@1,
{object_id, Oid}}]
)
);
{error, nil} ->
{error, nil}
end;
Kind@4 when Kind@4 =:= {kind, <<16#08>>} ->
<<Value@4:8, Rest@5/bitstring>> = Rest,
case Value@4 of
1 ->
decode_body(
Rest@5,
gleam@list:append(
Storage,
[{Key@1,
{boolean, true}}]
)
);
0 ->
decode_body(
Rest@5,
gleam@list:append(
Storage,
[{Key@1,
{boolean, false}}]
)
);
_@2 ->
{error, nil}
end;
Kind@5 when Kind@5 =:= {kind, <<16#0A>>} ->
decode_body(
Rest,
gleam@list:append(
Storage,
[{Key@1, null}]
)
);
Kind@6 when Kind@6 =:= {kind, <<16#FF>>} ->
decode_body(
Rest,
gleam@list:append(
Storage,
[{Key@1, min}]
)
);
Kind@7 when Kind@7 =:= {kind, <<16#7F>>} ->
decode_body(
Rest,
gleam@list:append(
Storage,
[{Key@1, max}]
)
);
Kind@8 when Kind@8 =:= {kind, <<16#10>>} ->
<<Value@5:32/little,
Rest@6/bitstring>> = Rest,
decode_body(
Rest@6,
gleam@list:append(
Storage,
[{Key@1, {integer, Value@5}}]
)
);
Kind@9 when Kind@9 =:= {kind, <<16#12>>} ->
<<Value@6:64/little,
Rest@7/bitstring>> = Rest,
decode_body(
Rest@7,
gleam@list:append(
Storage,
[{Key@1, {integer, Value@6}}]
)
);
Kind@10 when Kind@10 =:= {kind,
<<16#09>>} ->
<<Value@7:64/little,
Rest@8/bitstring>> = Rest,
decode_body(
Rest@8,
gleam@list:append(
Storage,
[{Key@1,
{date_time, Value@7}}]
)
);
Kind@11 when Kind@11 =:= {kind,
<<16#11>>} ->
<<Value@8:64/little-unsigned,
Rest@9/bitstring>> = Rest,
decode_body(
Rest@9,
gleam@list:append(
Storage,
[{Key@1,
{timestamp, Value@8}}]
)
);
Kind@12 when Kind@12 =:= {kind,
<<16#02>>} ->
<<Given_size@1:32/little-integer,
Rest@10/bitstring>> = Rest,
case consume_till_zero(
Rest@10,
<<>>
) of
{ok, Str} ->
Str_size = gleam@bit_string:byte_size(
Str
),
case Given_size@1
=:= (Str_size
+ 1) of
true ->
case gleam@bit_string:to_string(
Str
) of
{ok, Str@1} ->
case gleam@bit_string:slice(
Rest@10,
Str_size
+ 1,
(gleam@bit_string:byte_size(
Rest@10
)
- Str_size)
- 1
) of
{ok,
Rest@11} ->
decode_body(
Rest@11,
gleam@list:append(
Storage,
[{Key@1,
{str,
Str@1}}]
)
);
{error,
nil} ->
{error,
nil}
end;
{error, nil} ->
{error, nil}
end;
false ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
Kind@13 when Kind@13 =:= {kind,
<<16#0D>>} ->
<<Given_size@2:32/little-integer,
Rest@12/bitstring>> = Rest,
case consume_till_zero(
Rest@12,
<<>>
) of
{ok, Str@2} ->
Str_size@1 = gleam@bit_string:byte_size(
Str@2
),
case Given_size@2
=:= (Str_size@1
+ 1) of
true ->
case gleam@bit_string:to_string(
Str@2
) of
{ok, Str@3} ->
case gleam@bit_string:slice(
Rest@12,
Str_size@1
+ 1,
(gleam@bit_string:byte_size(
Rest@12
)
- Str_size@1)
- 1
) of
{ok,
Rest@13} ->
decode_body(
Rest@13,
gleam@list:append(
Storage,
[{Key@1,
{js,
Str@3}}]
)
);
{error,
nil} ->
{error,
nil}
end;
{error, nil} ->
{error, nil}
end;
false ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
Kind@14 when (Kind@14 =:= {kind,
<<16#03>>}) orelse (Kind@14 =:= {kind,
<<16#04>>}) ->
<<Doc_size:32/little-integer,
_@3/bitstring>> = Rest,
case gleam@bit_string:slice(
Rest,
0,
Doc_size
) of
{ok, Doc} ->
case decode_document(Doc) of
{ok, Doc@1} ->
Doc@4 = case Kind@14 of
Kind@15 when Kind@15 =:= {kind,
<<16#03>>} ->
{ok, Doc@1};
Kind@16 when Kind@16 =:= {kind,
<<16#04>>} ->
case Doc@1 of
{document,
Doc@2} ->
case begin
_pipe = Doc@2,
gleam@list:try_map(
_pipe,
fun(
Item
) ->
case begin
_pipe@1 = Item,
_pipe@2 = gleam@pair:first(
_pipe@1
),
gleam@int:parse(
_pipe@2
)
end of
{ok,
First} ->
{ok,
{First,
begin
_pipe@3 = Item,
gleam@pair:second(
_pipe@3
)
end}};
{error,
nil} ->
{error,
nil}
end
end
)
end of
{error,
nil} ->
{error,
nil};
{ok,
Doc@3} ->
{ok,
{array,
begin
_pipe@4 = Doc@3,
_pipe@7 = gleam@list:sort(
_pipe@4,
fun(
A,
B
) ->
A_index = begin
_pipe@5 = A,
gleam@pair:first(
_pipe@5
)
end,
B_index = begin
_pipe@6 = B,
gleam@pair:first(
_pipe@6
)
end,
gleam@int:compare(
A_index,
B_index
)
end
),
gleam@list:map(
_pipe@7,
fun(
Item@1
) ->
_pipe@8 = Item@1,
gleam@pair:second(
_pipe@8
)
end
)
end}}
end;
_@4 ->
{error,
nil}
end;
_@5 ->
{error, nil}
end,
case Doc@4 of
{ok, Doc@5} ->
case Doc_size
=:= gleam@bit_string:byte_size(
Rest
) of
true ->
{ok,
gleam@list:append(
Storage,
[{Key@1,
Doc@5}]
)};
false ->
case gleam@bit_string:slice(
Rest,
Doc_size,
gleam@bit_string:byte_size(
Rest
)
- Doc_size
) of
{ok,
Rest@14} ->
decode_body(
Rest@14,
gleam@list:append(
Storage,
[{Key@1,
Doc@5}]
)
);
{error,
nil} ->
{error,
nil}
end
end;
{error, nil} ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
_@6 ->
{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.