Current section
Files
Jump to
Current section
Files
src/glepack@decode.erl
-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
<<Bin_data:Bin_len/binary, Remaining/binary>> ->
{ok, {{binary, Bin_data}, Remaining}};
_ ->
{error, incomplete_data}
end;
<<16#c5, Bin_len@1:16/big, Rest@4/binary>> ->
case Rest@4 of
<<Bin_data@1:Bin_len@1/binary, Remaining@1/binary>> ->
{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
<<Bin_data@2:Bin_len@2/binary, Remaining@2/binary>> ->
{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
<<Str_bytes:Str_len/binary, Remaining@3/binary>> ->
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
<<Str_bytes@1:Str_len@1/binary, Remaining@4/binary>> ->
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
<<Str_bytes@2:Str_len@2/binary, Remaining@5/binary>> ->
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
<<Ext_data:Ext_len/binary, Remaining@6/binary>> ->
{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
<<Ext_data@1:Ext_len@1/binary, Remaining@7/binary>> ->
{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
<<Ext_data@2:Ext_len@2/binary, Remaining@8/binary>> ->
{ok, {{extension, Type_id@7, Ext_data@2}, Remaining@8}};
_ ->
{error, incomplete_data}
end;
<<Format:8, Rest@31/binary>> when (Format >= 0) andalso (Format =< 16#7f) ->
{ok, {{integer, Format}, Rest@31}};
<<Format@1:8, Rest@32/binary>> 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());
<<Format@2:8, Rest@33/binary>> when (Format@2 >= 16#90) andalso (Format@2 =< 16#9f) ->
Array_len@2 = Format@2 - 16#90,
decode_array(Array_len@2, Rest@33, []);
<<Format@3:8, Rest@34/binary>> when (Format@3 >= 16#a0) andalso (Format@3 =< 16#bf) ->
Str_len@3 = Format@3 - 16#a0,
case Rest@34 of
<<Str_bytes@3:Str_len@3/binary, Remaining@9/binary>> ->
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;
<<Value@8:8, Rest@35/binary>> 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.