-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} -> _pipe = Body@1, _pipe@1 = {document, _pipe}, {ok, _pipe@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} -> recurse_with_new_kv( Rest@2, Storage, Key@1, begin _pipe = Value@1, _pipe@1 = {generic, _pipe}, {binary, _pipe@1} 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} -> recurse_with_new_kv( Rest@2, Storage, Key@1, begin _pipe@2 = Value@2, _pipe@3 = {md5, _pipe@2}, {binary, _pipe@3} 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} -> recurse_with_new_kv( Rest@2, Storage, Key@1, begin _pipe@4 = Value@3, _pipe@5 = {uuid, _pipe@4}, {binary, _pipe@5} 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} -> recurse_with_new_kv( Rest@2, Storage, Key@1, begin _pipe@6 = Value@4, _pipe@7 = {custom, _pipe@6}, {binary, _pipe@7} end ) end; _@3 -> {error, nil} end; Kind@2 when Kind@2 =:= {kind, <<16#01>>} -> <> = Rest, recurse_with_new_kv( Rest@3, Storage, Key@1, {double, Value@5} ); 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} -> recurse_with_new_kv( Rest@4, Storage, Key@1, {object_id, Oid} ) end; Kind@4 when Kind@4 =:= {kind, <<16#08>>} -> <> = Rest, decode_boolean( Value@7, fun(Value@8) -> recurse_with_new_kv( Rest@5, Storage, Key@1, {boolean, Value@8} ) end ); Kind@5 when Kind@5 =:= {kind, <<16#0A>>} -> recurse_with_new_kv( Rest, Storage, Key@1, null ); Kind@6 when Kind@6 =:= {kind, <<16#FF>>} -> recurse_with_new_kv( Rest, Storage, Key@1, min ); Kind@7 when Kind@7 =:= {kind, <<16#7F>>} -> recurse_with_new_kv( Rest, Storage, Key@1, max ); Kind@8 when Kind@8 =:= {kind, <<16#10>>} -> <> = Rest, recurse_with_new_kv( Rest@6, Storage, Key@1, {integer, Value@9} ); Kind@9 when Kind@9 =:= {kind, <<16#12>>} -> <> = Rest, recurse_with_new_kv( Rest@7, Storage, Key@1, {integer, Value@10} ); Kind@10 when Kind@10 =:= {kind, <<16#09>>} -> <> = Rest, recurse_with_new_kv( Rest@8, Storage, Key@1, {date_time, Value@11} ); Kind@11 when Kind@11 =:= {kind, <<16#11>>} -> <> = Rest, recurse_with_new_kv( Rest@9, Storage, Key@1, {timestamp, Value@12} ); 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} -> recurse_with_new_kv( Rest@11, Storage, Key@1, {regex, {Pattern, Options}} ) 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} -> recurse_with_new_kv( Rest@13, Storage, Key@1, {str, Str@1} ) 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} -> recurse_with_new_kv( Rest@15, 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>>}) -> <> = 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>>} -> _pipe@8 = Doc@1, _pipe@9 = {document, _pipe@8}, {ok, _pipe@9}; Kind@17 when Kind@17 =:= {kind, <<16#04>>} -> case gleam@list:try_map( Doc@1, fun( Item ) -> case gleam@int:parse( erlang:element( 1, Item ) ) of {error, _try@20} -> {error, _try@20}; {ok, First} -> {ok, {First, erlang:element( 2, Item )}} end end ) of {error, _try@21} -> {error, _try@21}; {ok, Doc@2} -> _pipe@10 = Doc@2, _pipe@11 = gleam@list:sort( _pipe@10, fun( A, B ) -> gleam@int:compare( erlang:element( 1, A ), erlang:element( 1, B ) ) end ), _pipe@12 = gleam@list:map( _pipe@11, fun gleam@pair:second/1 ), _pipe@13 = {array, _pipe@12}, {ok, _pipe@13} end; _@7 -> {error, nil} end of {error, _try@22} -> {error, _try@22}; {ok, Doc@3} -> case gleam@bit_string:slice( Rest, Doc_size, gleam@bit_string:byte_size( Rest ) - Doc_size ) of {ok, Rest@16} -> recurse_with_new_kv( Rest@16, Storage, Key@1, Doc@3 ); {error, nil} -> {error, nil} 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) of 0 -> {error, nil}; _@1 -> <> = Data, case Ch of 0 -> {ok, Storage}; _@2 -> consume_till_zero( Rest, gleam@bit_string:append(Storage, <>) ) end end. -spec recurse_with_new_kv( bitstring(), list({binary(), bson@types:value()}), binary(), bson@types:value() ) -> {ok, list({binary(), bson@types:value()})} | {error, nil}. recurse_with_new_kv(Rest, Storage, Key, Value) -> decode_body(Rest, gleam@list:key_set(Storage, Key, Value)). -spec decode_boolean( integer(), fun((boolean()) -> {ok, list({binary(), bson@types:value()})} | {error, nil}) ) -> {ok, list({binary(), bson@types:value()})} | {error, nil}. decode_boolean(Value, Rest) -> case Value of 0 -> Rest(false); 1 -> Rest(true); _@1 -> {error, nil} end.