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
{error, _try} -> {error, _try};
{ok, Body} ->
case decode_body(Body, []) of
{error, _try@1} -> {error, _try@1};
{ok, Body@1} ->
{ok, {document, Body@1}}
end
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
{error, _try} -> {error, _try};
{ok, Key} ->
Key_size = gleam@bit_string:byte_size(Key),
case gleam@bit_string:to_string(Key) of
{error, _try@1} -> {error, _try@1};
{ok, Key@1} ->
case gleam@bit_string:slice(
Data@1,
Key_size
+ 1,
(Total_size
- Key_size)
- 1
) of
{error, _try@2} -> {error, _try@2};
{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@generic:from_bit_string(
Value
) of
{error, _try@3} -> {error, _try@3};
{ok, Value@1} ->
decode_body(
Rest@2,
gleam@list:append(
Storage,
[{Key@1,
{binary,
{generic,
Value@1}}}]
)
)
end;
Sub_kind@2 when Sub_kind@2 =:= {sub_kind,
<<16#5>>} ->
case bson@md5:from_bit_string(
Value
) of
{error, _try@4} -> {error, _try@4};
{ok, Value@2} ->
decode_body(
Rest@2,
gleam@list:append(
Storage,
[{Key@1,
{binary,
{md5,
Value@2}}}]
)
)
end;
Sub_kind@3 when Sub_kind@3 =:= {sub_kind,
<<16#4>>} ->
case bson@uuid:from_bit_string(
Value
) of
{error, _try@5} -> {error, _try@5};
{ok, Value@3} ->
decode_body(
Rest@2,
gleam@list:append(
Storage,
[{Key@1,
{binary,
{uuid,
Value@3}}}]
)
)
end;
_@1 when Sub_code >= 16#80 ->
case bson@custom:from_bit_string_with_code(
Sub_code,
Value
) of
{error, _try@6} -> {error, _try@6};
{ok, Value@4} ->
decode_body(
Rest@2,
gleam@list:append(
Storage,
[{Key@1,
{binary,
{custom,
Value@4}}}]
)
)
end;
_@2 ->
{error, nil}
end;
Kind@2 when Kind@2 =:= {kind, <<16#01>>} ->
<<Value@5/little-float,
Rest@3/bitstring>> = Rest,
decode_body(
Rest@3,
gleam@list:append(
Storage,
[{Key@1, {double, Value@5}}]
)
);
Kind@3 when Kind@3 =:= {kind, <<16#07>>} ->
<<Value@6:96/bitstring,
Rest@4/bitstring>> = Rest,
case bson@object_id:from_bit_string(
Value@6
) of
{error, _try@7} -> {error, _try@7};
{ok, Oid} ->
decode_body(
Rest@4,
gleam@list:append(
Storage,
[{Key@1,
{object_id, Oid}}]
)
)
end;
Kind@4 when Kind@4 =:= {kind, <<16#08>>} ->
<<Value@7:8, Rest@5/bitstring>> = Rest,
case Value@7 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}}]
)
);
_@3 ->
{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@8:32/little,
Rest@6/bitstring>> = Rest,
decode_body(
Rest@6,
gleam@list:append(
Storage,
[{Key@1, {integer, Value@8}}]
)
);
Kind@9 when Kind@9 =:= {kind, <<16#12>>} ->
<<Value@9:64/little,
Rest@7/bitstring>> = Rest,
decode_body(
Rest@7,
gleam@list:append(
Storage,
[{Key@1, {integer, Value@9}}]
)
);
Kind@10 when Kind@10 =:= {kind,
<<16#09>>} ->
<<Value@10:64/little,
Rest@8/bitstring>> = Rest,
decode_body(
Rest@8,
gleam@list:append(
Storage,
[{Key@1,
{date_time, Value@10}}]
)
);
Kind@11 when Kind@11 =:= {kind,
<<16#11>>} ->
<<Value@11:64/little-unsigned,
Rest@9/bitstring>> = Rest,
decode_body(
Rest@9,
gleam@list:append(
Storage,
[{Key@1,
{timestamp, Value@11}}]
)
);
Kind@12 when Kind@12 =:= {kind,
<<16#0B>>} ->
case consume_till_zero(Rest, <<>>) of
{error, _try@8} -> {error, _try@8};
{ok, Pattern_bytes} ->
Pattern_size = (gleam@bit_string:byte_size(
Pattern_bytes
)
+ 1)
* 8,
<<_@4:Pattern_size,
Rest@10/bitstring>> = Rest,
case consume_till_zero(
Rest@10,
<<>>
) of
{error, _try@9} -> {error, _try@9};
{ok, Options_bytes} ->
Options_size = (gleam@bit_string:byte_size(
Options_bytes
)
+ 1)
* 8,
<<_@5:Options_size,
Rest@11/bitstring>> = Rest@10,
case gleam@bit_string:to_string(
Pattern_bytes
) of
{error, _try@10} -> {error, _try@10};
{ok, Pattern} ->
case gleam@bit_string:to_string(
Options_bytes
) of
{error, _try@11} -> {error, _try@11};
{ok, Options} ->
decode_body(
Rest@11,
gleam@list:append(
Storage,
[{Key@1,
{regex,
{Pattern,
Options}}}]
)
)
end
end
end
end;
Kind@13 when Kind@13 =:= {kind,
<<16#02>>} ->
<<Given_size@1:32/little-integer,
Rest@12/bitstring>> = Rest,
case consume_till_zero(
Rest@12,
<<>>
) of
{error, _try@12} -> {error, _try@12};
{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
{error, _try@13} -> {error, _try@13};
{ok, Str@1} ->
case gleam@bit_string:slice(
Rest@12,
Str_size
+ 1,
(gleam@bit_string:byte_size(
Rest@12
)
- Str_size)
- 1
) of
{error, _try@14} -> {error, _try@14};
{ok, Rest@13} ->
decode_body(
Rest@13,
gleam@list:append(
Storage,
[{Key@1,
{str,
Str@1}}]
)
)
end
end;
false ->
{error, nil}
end
end;
Kind@14 when Kind@14 =:= {kind,
<<16#0D>>} ->
<<Given_size@2:32/little-integer,
Rest@14/bitstring>> = Rest,
case consume_till_zero(
Rest@14,
<<>>
) of
{error, _try@15} -> {error, _try@15};
{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
{error, _try@16} -> {error, _try@16};
{ok, Str@3} ->
case gleam@bit_string:slice(
Rest@14,
Str_size@1
+ 1,
(gleam@bit_string:byte_size(
Rest@14
)
- Str_size@1)
- 1
) of
{error, _try@17} -> {error, _try@17};
{ok, Rest@15} ->
decode_body(
Rest@15,
gleam@list:append(
Storage,
[{Key@1,
{js,
Str@3}}]
)
)
end
end;
false ->
{error, nil}
end
end;
Kind@15 when (Kind@15 =:= {kind,
<<16#03>>}) orelse (Kind@15 =:= {kind,
<<16#04>>}) ->
<<Doc_size:32/little-integer,
_@6/bitstring>> = Rest,
case gleam@bit_string:slice(
Rest,
0,
Doc_size
) of
{error, _try@18} -> {error, _try@18};
{ok, Doc} ->
case decode_document(Doc) of
{error, _try@19} -> {error, _try@19};
{ok, {document, Doc@1}} ->
case case Kind@15 of
Kind@16 when Kind@16 =:= {kind,
<<16#03>>} ->
{ok,
{document,
Doc@1}};
Kind@17 when Kind@17 =:= {kind,
<<16#04>>} ->
case begin
_pipe = Doc@1,
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
{error, _try@20} -> {error, _try@20};
{ok, First} ->
{ok,
{First,
begin
_pipe@3 = Item,
gleam@pair:second(
_pipe@3
)
end}}
end
end
)
end of
{error, _try@21} -> {error, _try@21};
{ok, Doc@2} ->
{ok,
{array,
begin
_pipe@4 = Doc@2,
_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;
_@7 ->
{error, nil}
end of
{error, _try@22} -> {error, _try@22};
{ok, Doc@3} ->
case Doc_size
=:= gleam@bit_string:byte_size(
Rest
) of
true ->
{ok,
gleam@list:append(
Storage,
[{Key@1,
Doc@3}]
)};
false ->
case gleam@bit_string:slice(
Rest,
Doc_size,
gleam@bit_string:byte_size(
Rest
)
- Doc_size
) of
{ok,
Rest@16} ->
decode_body(
Rest@16,
gleam@list:append(
Storage,
[{Key@1,
Doc@3}]
)
);
{error,
nil} ->
{error,
nil}
end
end
end
end
end;
_@8 ->
{error, nil}
end
end
end
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.