-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 -> <> = 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 -> <> = 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, 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; _@1 when Sub_code >= 16#80 -> case bson@custom:from_bit_string_with_code( Sub_code, Value ) of {error, _try@5} -> {error, _try@5}; {ok, Value@3} -> decode_body( Rest@2, gleam@list:append( Storage, [{Key@1, {binary, {custom, Value@3}}}] ) ) end; _@2 -> {error, nil} end; Kind@2 when Kind@2 =:= {kind, <<16#01>>} -> <> = Rest, decode_body( Rest@3, gleam@list:append( Storage, [{Key@1, {double, Value@4}}] ) ); Kind@3 when Kind@3 =:= {kind, <<16#07>>} -> <> = Rest, case bson@object_id:from_bit_string( Value@5 ) of {error, _try@6} -> {error, _try@6}; {ok, Oid} -> decode_body( Rest@4, gleam@list:append( Storage, [{Key@1, {object_id, Oid}}] ) ) end; Kind@4 when Kind@4 =:= {kind, <<16#08>>} -> <> = Rest, case Value@6 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>>} -> <> = Rest, decode_body( Rest@6, gleam@list:append( Storage, [{Key@1, {integer, Value@7}}] ) ); Kind@9 when Kind@9 =:= {kind, <<16#12>>} -> <> = Rest, decode_body( Rest@7, gleam@list:append( Storage, [{Key@1, {integer, Value@8}}] ) ); Kind@10 when Kind@10 =:= {kind, <<16#09>>} -> <> = Rest, decode_body( Rest@8, gleam@list:append( Storage, [{Key@1, {date_time, Value@9}}] ) ); Kind@11 when Kind@11 =:= {kind, <<16#11>>} -> <> = Rest, decode_body( Rest@9, gleam@list:append( Storage, [{Key@1, {timestamp, Value@10}}] ) ); Kind@12 when Kind@12 =:= {kind, <<16#02>>} -> <> = Rest, case consume_till_zero( Rest@10, <<>> ) of {error, _try@7} -> {error, _try@7}; {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@8} -> {error, _try@8}; {ok, Str@1} -> case gleam@bit_string:slice( Rest@10, Str_size + 1, (gleam@bit_string:byte_size( Rest@10 ) - Str_size) - 1 ) of {error, _try@9} -> {error, _try@9}; {ok, Rest@11} -> decode_body( Rest@11, gleam@list:append( Storage, [{Key@1, {str, Str@1}}] ) ) end end; false -> {error, nil} end end; Kind@13 when Kind@13 =:= {kind, <<16#0D>>} -> <> = Rest, case consume_till_zero( Rest@12, <<>> ) of {error, _try@10} -> {error, _try@10}; {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@11} -> {error, _try@11}; {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 {error, _try@12} -> {error, _try@12}; {ok, Rest@13} -> decode_body( Rest@13, gleam@list:append( Storage, [{Key@1, {js, Str@3}}] ) ) end end; false -> {error, nil} end end; Kind@14 when (Kind@14 =:= {kind, <<16#03>>}) orelse (Kind@14 =:= {kind, <<16#04>>}) -> <> = Rest, case gleam@bit_string:slice( Rest, 0, Doc_size ) of {error, _try@13} -> {error, _try@13}; {ok, Doc} -> case decode_document(Doc) of {error, _try@14} -> {error, _try@14}; {ok, {document, Doc@1}} -> case case Kind@14 of Kind@15 when Kind@15 =:= {kind, <<16#03>>} -> {ok, {document, Doc@1}}; Kind@16 when Kind@16 =:= {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@15} -> {error, _try@15}; {ok, First} -> {ok, {First, begin _pipe@3 = Item, gleam@pair:second( _pipe@3 ) end}} end end ) end of {error, _try@16} -> {error, _try@16}; {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; _@5 -> {error, nil} end of {error, _try@17} -> {error, _try@17}; {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@14} -> decode_body( Rest@14, gleam@list:append( Storage, [{Key@1, Doc@3}] ) ); {error, nil} -> {error, nil} end end end end end; _@6 -> {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 -> <> = Data, case Ch =:= 0 of true -> {ok, Storage}; false -> consume_till_zero( Rest, gleam@bit_string:append(Storage, <>) ) end; true -> {error, nil} end.