-module(glepack@decode). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([value/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(" This module provides functions to decode MessagePack data\n"). -file("src/glepack/decode.gleam", 268). -spec decode_array(integer(), bitstring(), list(glepack@data:value())) -> {ok, {glepack@data:value(), bitstring()}} | {error, glepack@error:decode_error()}. decode_array(Count, Input, Acc) -> case Count of 0 -> {ok, {{array, lists:reverse(Acc)}, Input}}; _ -> case value(Input) of {error, E} -> {error, E}; {ok, {Item_value, Rest}} -> decode_array(Count - 1, Rest, [Item_value | Acc]) end end. -file("src/glepack/decode.gleam", 22). ?DOC( " Decodes a MessagePack value from a BitArray\n" " Returns a tuple with the decoded value and the remaining BitArray\n" "\n" " ## Errors\n" "\n" " This function can return the following errors:\n" " - `InvalidFormat`: When the input data is not valid MessagePack\n" " - `IncompleteData`: When the input data is incomplete and more bytes are needed\n" " - `IntegerTooLarge`: When the input contains an integer that is too large for Gleam's Int type\n" " - `InvalidUtf8`: When the input contains a string that is not valid UTF-8\n" " - `ReservedFormat`: When the input contains a reserved format (0xc1)\n" " - `UnknownFormat`: When an unknown format was encountered\n" " - `UnsupportedExtension`: When the input contains an extension type that is not supported\n" ). -spec value(bitstring()) -> {ok, {glepack@data:value(), bitstring()}} | {error, glepack@error:decode_error()}. value(Input) -> case Input of <<16#c0, Rest/binary>> -> {ok, {nil, Rest}}; <<16#c1, _/binary>> -> {error, reserved_format}; <<16#c2, Rest@1/binary>> -> {ok, {{boolean, false}, Rest@1}}; <<16#c3, Rest@2/binary>> -> {ok, {{boolean, true}, Rest@2}}; <<16#c4, Bin_len:8, Rest@3/binary>> -> case Rest@3 of <> -> {ok, {{binary, Bin_data}, Remaining}}; _ -> {error, incomplete_data} end; <<16#c5, Bin_len@1:16/big, Rest@4/binary>> -> case Rest@4 of <> -> {ok, {{binary, Bin_data@1}, Remaining@1}}; _ -> {error, incomplete_data} end; <<16#c6, Bin_len@2:32/big, Rest@5/binary>> -> case Rest@5 of <> -> {ok, {{binary, Bin_data@2}, Remaining@2}}; _ -> {error, incomplete_data} end; <<16#ca, Bits:32/float-big, Rest@6/binary>> -> {ok, {{float, Bits}, Rest@6}}; <<16#ca, _/binary>> -> {error, incomplete_data}; <<16#cb, Bits@1:64/float-big, Rest@7/binary>> -> {ok, {{float, Bits@1}, Rest@7}}; <<16#cb, _/binary>> -> {error, incomplete_data}; <<16#cc, Value:8, Rest@8/binary>> -> {ok, {{integer, Value}, Rest@8}}; <<16#cc>> -> {error, incomplete_data}; <<16#cd, Value@1:16/big, Rest@9/binary>> -> {ok, {{integer, Value@1}, Rest@9}}; <<16#cd, _/binary>> -> {error, incomplete_data}; <<16#cd>> -> {error, incomplete_data}; <<16#ce, Value@2:32/big, Rest@10/binary>> -> {ok, {{integer, Value@2}, Rest@10}}; <<16#ce, _/binary>> -> {error, incomplete_data}; <<16#ce>> -> {error, incomplete_data}; <<16#cf, Value@3:64/big, Rest@11/binary>> -> case Value@3 >= 9223372036854775808 of true -> {error, integer_too_large}; false -> {ok, {{integer, Value@3}, Rest@11}} end; <<16#d0, Value@4:8/signed-big, Rest@12/binary>> -> {ok, {{integer, Value@4}, Rest@12}}; <<16#d1, Value@5:16/signed-big, Rest@13/binary>> -> {ok, {{integer, Value@5}, Rest@13}}; <<16#d2, Value@6:32/signed-big, Rest@14/binary>> -> {ok, {{integer, Value@6}, Rest@14}}; <<16#d3, Value@7:64/signed-big, Rest@15/binary>> -> {ok, {{integer, Value@7}, Rest@15}}; <<16#d4, Type_id:8, Data:1/binary, Rest@16/binary>> -> {ok, {{extension, Type_id, Data}, Rest@16}}; <<16#d5, Type_id@1:8, Data@1:2/binary, Rest@17/binary>> -> {ok, {{extension, Type_id@1, Data@1}, Rest@17}}; <<16#d6, Type_id@2:8, Data@2:4/binary, Rest@18/binary>> -> {ok, {{extension, Type_id@2, Data@2}, Rest@18}}; <<16#d7, Type_id@3:8, Data@3:8/binary, Rest@19/binary>> -> {ok, {{extension, Type_id@3, Data@3}, Rest@19}}; <<16#d8, Type_id@4:8, Data@4:16/binary, Rest@20/binary>> -> {ok, {{extension, Type_id@4, Data@4}, Rest@20}}; <<16#d9, Str_len:8, Rest@21/binary>> -> case Rest@21 of <> -> case gleam@bit_array:to_string(Str_bytes) of {ok, Str} -> {ok, {{string, Str}, Remaining@3}}; {error, _} -> {error, invalid_utf8} end; _ -> {error, incomplete_data} end; <<16#da, Str_len@1:16/big, Rest@22/binary>> -> case Rest@22 of <> -> case gleam@bit_array:to_string(Str_bytes@1) of {ok, Str@1} -> {ok, {{string, Str@1}, Remaining@4}}; {error, _} -> {error, invalid_utf8} end; _ -> {error, incomplete_data} end; <<16#db, Str_len@2:32/big, Rest@23/binary>> -> case Rest@23 of <> -> case gleam@bit_array:to_string(Str_bytes@2) of {ok, Str@2} -> {ok, {{string, Str@2}, Remaining@5}}; {error, _} -> {error, invalid_utf8} end; _ -> {error, incomplete_data} end; <<16#dc, Array_len:16/big, Rest@24/binary>> -> decode_array(Array_len, Rest@24, []); <<16#dd, Array_len@1:32/big, Rest@25/binary>> -> decode_array(Array_len@1, Rest@25, []); <<16#de, Map_len:16/big, Rest@26/binary>> -> decode_map(Map_len, Rest@26, maps:new()); <<16#df, Map_len@1:32/big, Rest@27/binary>> -> decode_map(Map_len@1, Rest@27, maps:new()); <<16#c7, Ext_len:8, Type_id@5:8, Rest@28/binary>> -> case Rest@28 of <> -> {ok, {{extension, Type_id@5, Ext_data}, Remaining@6}}; _ -> {error, incomplete_data} end; <<16#c8, Ext_len@1:16/big, Type_id@6:8, Rest@29/binary>> -> case Rest@29 of <> -> {ok, {{extension, Type_id@6, Ext_data@1}, Remaining@7}}; _ -> {error, incomplete_data} end; <<16#c9, Ext_len@2:32/big, Type_id@7:8, Rest@30/binary>> -> case Rest@30 of <> -> {ok, {{extension, Type_id@7, Ext_data@2}, Remaining@8}}; _ -> {error, incomplete_data} end; <> when (Format >= 0) andalso (Format =< 16#7f) -> {ok, {{integer, Format}, Rest@31}}; <> when (Format@1 >= 16#80) andalso (Format@1 =< 16#8f) -> Map_len@2 = Format@1 - 16#80, decode_map(Map_len@2, Rest@32, maps:new()); <> when (Format@2 >= 16#90) andalso (Format@2 =< 16#9f) -> Array_len@2 = Format@2 - 16#90, decode_array(Array_len@2, Rest@33, []); <> when (Format@3 >= 16#a0) andalso (Format@3 =< 16#bf) -> Str_len@3 = Format@3 - 16#a0, case Rest@34 of <> -> case gleam@bit_array:to_string(Str_bytes@3) of {ok, Str@3} -> {ok, {{string, Str@3}, Remaining@9}}; {error, _} -> {error, invalid_utf8} end; _ -> {error, incomplete_data} end; <> when (Value@8 >= 16#e0) andalso (Value@8 =< 16#ff) -> Int_value = Value@8 - 256, {ok, {{integer, Int_value}, Rest@35}}; _ -> {error, unknown_format} end. -file("src/glepack/decode.gleam", 287). -spec decode_map( integer(), bitstring(), gleam@dict:dict(glepack@data:value(), glepack@data:value()) ) -> {ok, {glepack@data:value(), bitstring()}} | {error, glepack@error:decode_error()}. decode_map(Count, Input, Acc) -> case Count of 0 -> {ok, {{map, Acc}, Input}}; _ -> case value(Input) of {error, E} -> {error, E}; {ok, {Key, Rest1}} -> case value(Rest1) of {error, E@1} -> {error, E@1}; {ok, {Val, Rest2}} -> New_acc = gleam@dict:insert(Acc, Key, Val), decode_map(Count - 1, Rest2, New_acc) end end end.