-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 of {ok, <<0>>} -> <> = 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; _@1 -> {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) of 0 -> {ok, Storage}; _@1 -> <> = 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, <>}, case Kind of Kind@1 when Kind@1 =:= {kind, <<16#05>>} -> <> = Rest, Given_size = Byte_size * 8, <> = Rest@1, Sub_kind = {sub_kind, <>}, 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, begin _pipe = Storage, _pipe@1 = gleam@list:reverse( _pipe ), _pipe@2 = gleam@list:prepend( _pipe@1, {Key@1, {binary, {generic, Value@1}}} ), gleam@list:reverse( _pipe@2 ) end ) 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, begin _pipe@3 = Storage, _pipe@4 = gleam@list:reverse( _pipe@3 ), _pipe@5 = gleam@list:prepend( _pipe@4, {Key@1, {binary, {md5, Value@2}}} ), gleam@list:reverse( _pipe@5 ) end ) 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, begin _pipe@6 = Storage, _pipe@7 = gleam@list:reverse( _pipe@6 ), _pipe@8 = gleam@list:prepend( _pipe@7, {Key@1, {binary, {uuid, Value@3}}} ), gleam@list:reverse( _pipe@8 ) end ) end; _@2 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, begin _pipe@9 = Storage, _pipe@10 = gleam@list:reverse( _pipe@9 ), _pipe@11 = gleam@list:prepend( _pipe@10, {Key@1, {binary, {custom, Value@4}}} ), gleam@list:reverse( _pipe@11 ) end ) end; _@3 -> {error, nil} end; Kind@2 when Kind@2 =:= {kind, <<16#01>>} -> <> = Rest, decode_body( Rest@3, begin _pipe@12 = Storage, _pipe@13 = gleam@list:reverse( _pipe@12 ), _pipe@14 = gleam@list:prepend( _pipe@13, {Key@1, {double, Value@5}} ), gleam@list:reverse(_pipe@14) end ); Kind@3 when Kind@3 =:= {kind, <<16#07>>} -> <> = Rest, case bson@object_id:from_bit_string( Value@6 ) of {error, _try@7} -> {error, _try@7}; {ok, Oid} -> decode_body( Rest@4, begin _pipe@15 = Storage, _pipe@16 = gleam@list:reverse( _pipe@15 ), _pipe@17 = gleam@list:prepend( _pipe@16, {Key@1, {object_id, Oid}} ), gleam@list:reverse( _pipe@17 ) end ) end; Kind@4 when Kind@4 =:= {kind, <<16#08>>} -> <> = Rest, case Value@7 of 1 -> decode_body( Rest@5, begin _pipe@18 = Storage, _pipe@19 = gleam@list:reverse( _pipe@18 ), _pipe@20 = gleam@list:prepend( _pipe@19, {Key@1, {boolean, true}} ), gleam@list:reverse( _pipe@20 ) end ); 0 -> decode_body( Rest@5, begin _pipe@21 = Storage, _pipe@22 = gleam@list:reverse( _pipe@21 ), _pipe@23 = gleam@list:prepend( _pipe@22, {Key@1, {boolean, false}} ), gleam@list:reverse( _pipe@23 ) end ); _@4 -> {error, nil} end; Kind@5 when Kind@5 =:= {kind, <<16#0A>>} -> decode_body( Rest, begin _pipe@24 = Storage, _pipe@25 = gleam@list:reverse( _pipe@24 ), _pipe@26 = gleam@list:prepend( _pipe@25, {Key@1, null} ), gleam@list:reverse(_pipe@26) end ); Kind@6 when Kind@6 =:= {kind, <<16#FF>>} -> decode_body( Rest, begin _pipe@27 = Storage, _pipe@28 = gleam@list:reverse( _pipe@27 ), _pipe@29 = gleam@list:prepend( _pipe@28, {Key@1, min} ), gleam@list:reverse(_pipe@29) end ); Kind@7 when Kind@7 =:= {kind, <<16#7F>>} -> decode_body( Rest, begin _pipe@30 = Storage, _pipe@31 = gleam@list:reverse( _pipe@30 ), _pipe@32 = gleam@list:prepend( _pipe@31, {Key@1, max} ), gleam@list:reverse(_pipe@32) end ); Kind@8 when Kind@8 =:= {kind, <<16#10>>} -> <> = Rest, decode_body( Rest@6, begin _pipe@33 = Storage, _pipe@34 = gleam@list:reverse( _pipe@33 ), _pipe@35 = gleam@list:prepend( _pipe@34, {Key@1, {integer, Value@8}} ), gleam@list:reverse(_pipe@35) end ); Kind@9 when Kind@9 =:= {kind, <<16#12>>} -> <> = Rest, decode_body( Rest@7, begin _pipe@36 = Storage, _pipe@37 = gleam@list:reverse( _pipe@36 ), _pipe@38 = gleam@list:prepend( _pipe@37, {Key@1, {integer, Value@9}} ), gleam@list:reverse(_pipe@38) end ); Kind@10 when Kind@10 =:= {kind, <<16#09>>} -> <> = Rest, decode_body( Rest@8, begin _pipe@39 = Storage, _pipe@40 = gleam@list:reverse( _pipe@39 ), _pipe@41 = gleam@list:prepend( _pipe@40, {Key@1, {date_time, Value@10}} ), gleam@list:reverse(_pipe@41) end ); Kind@11 when Kind@11 =:= {kind, <<16#11>>} -> <> = Rest, decode_body( Rest@9, begin _pipe@42 = Storage, _pipe@43 = gleam@list:reverse( _pipe@42 ), _pipe@44 = gleam@list:prepend( _pipe@43, {Key@1, {timestamp, Value@11}} ), gleam@list:reverse(_pipe@44) end ); 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, <<_@5: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, <<_@6: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, begin _pipe@45 = Storage, _pipe@46 = gleam@list:reverse( _pipe@45 ), _pipe@47 = gleam@list:prepend( _pipe@46, {Key@1, {regex, {Pattern, Options}}} ), gleam@list:reverse( _pipe@47 ) end ) end end end end; Kind@13 when Kind@13 =:= {kind, <<16#02>>} -> <> = 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, begin _pipe@48 = Storage, _pipe@49 = gleam@list:reverse( _pipe@48 ), _pipe@50 = gleam@list:prepend( _pipe@49, {Key@1, {str, Str@1}} ), gleam@list:reverse( _pipe@50 ) end ) end end; false -> {error, nil} end end; Kind@14 when Kind@14 =:= {kind, <<16#0D>>} -> <> = 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, begin _pipe@51 = Storage, _pipe@52 = gleam@list:reverse( _pipe@51 ), _pipe@53 = gleam@list:prepend( _pipe@52, {Key@1, {js, Str@3}} ), gleam@list:reverse( _pipe@53 ) end ) end end; false -> {error, nil} end end; Kind@15 when (Kind@15 =:= {kind, <<16#03>>}) orelse (Kind@15 =:= {kind, <<16#04>>}) -> <> = 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 gleam@list:try_map( Doc@1, fun( Item ) -> case begin _pipe@54 = Item, _pipe@55 = gleam@pair:first( _pipe@54 ), gleam@int:parse( _pipe@55 ) end of {error, _try@20} -> {error, _try@20}; {ok, First} -> {ok, {First, gleam@pair:second( Item )}} end end ) of {error, _try@21} -> {error, _try@21}; {ok, Doc@2} -> _pipe@57 = {array, begin _pipe@56 = gleam@list:sort( Doc@2, fun( A, B ) -> A_index = gleam@pair:first( A ), B_index = gleam@pair:first( B ), gleam@int:compare( A_index, B_index ) end ), gleam@list:map( _pipe@56, fun gleam@pair:second/1 ) end}, {ok, _pipe@57} end; _@8 -> {error, nil} end of {error, _try@22} -> {error, _try@22}; {ok, Doc@3} -> case Doc_size =:= gleam@bit_string:byte_size( Rest ) of true -> _pipe@58 = Storage, _pipe@59 = gleam@list:reverse( _pipe@58 ), _pipe@60 = gleam@list:prepend( _pipe@59, {Key@1, Doc@3} ), _pipe@61 = gleam@list:reverse( _pipe@60 ), {ok, _pipe@61}; 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, begin _pipe@62 = Storage, _pipe@63 = gleam@list:reverse( _pipe@62 ), _pipe@64 = gleam@list:prepend( _pipe@63, {Key@1, Doc@3} ), gleam@list:reverse( _pipe@64 ) end ); {error, nil} -> {error, nil} end end end end end; _@9 -> {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) of 0 -> {error, nil}; _@1 -> <> = Data, case Ch of 0 -> {ok, Storage}; _@2 -> consume_till_zero( Rest, gleam@bit_string:append(Storage, <>) ) end end.