-module(eVPack). -include("eVPack.hrl"). -compile(inline). -compile({inline_size, 128}). -import(lists, [reverse/1]). -import(maps, [iterator/1, next/1, keys/1]). -export([ %% decode decodeAll/1 , decodeHeader/1 , decodePart/1 %% encode , encodeIol/1 , encodeBin/1 , encodeIol/3 , encodeBin/3 %% other API , encodeAtom/1 , encodeMap/3 , encodeList/3 , encodeFloat/1 , encodeString/1 , encodeInteger/1 , buildIndexTable_1/2 , buildIndexTable_2/2 , buildIndexTable_4/2 , buildIndexTable_8/2 ]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% encode %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec encodeIol(term()) -> vpack() | {error, any()}. encodeIol(Term) -> {VPack, _Size} = encoder(Term, ?VpArrDef, ?VpObjDef), VPack. -spec encodeBin(term()) -> vpack() | {error, any()}. encodeBin(Term) -> {VPack, _Size} = encoder(Term, ?VpArrDef, ?VpObjDef), iolist_to_binary(VPack). -spec encodeIol(term(), vpOpt(), vpOpt()) -> vpack() | {error, any()}. encodeIol(Term, ArrOpt, ObjOpt) -> {VPack, _Size} = encoder(Term, ArrOpt, ObjOpt), VPack. -spec encodeBin(term(), vpOpt(), vpOpt()) -> vpack() | {error, any()}. encodeBin(Term, ArrOpt, ObjOpt) -> {VPack, _Size} = encoder(Term, ArrOpt, ObjOpt), iolist_to_binary(VPack). encoder(Map, ArrOpt, ObjOpt) when erlang:is_map(Map) -> encodeMap(ObjOpt, Map, ArrOpt); encoder(Atom, _, _) when erlang:is_atom(Atom) -> encodeAtom(Atom); encoder(Binary, _, _) when erlang:is_binary(Binary) -> encodeString(Binary); encoder(Integer, _, _) when erlang:is_integer(Integer) -> encodeInteger(Integer); encoder(Float, _, _) when erlang:is_float(Float) -> encodeFloat(Float); encoder(List, ArrOpt, ObjOpt) when erlang:is_list(List) -> encodeList(ArrOpt, List, ObjOpt); encoder({?blob, Blob}, _, _) when erlang:is_binary(Blob) -> encodeBlob(Blob); encoder(_Value, _, _) -> erlang:throw({error, {invalid_type, dataType(_Value), _Value}}). dataType(Data) when is_list(Data) -> list; dataType(Data) when is_integer(Data) -> integer; dataType(Data) when is_binary(Data) -> binary; dataType(Data) when is_function(Data) -> function; dataType(Data) when is_tuple(Data) -> tuple; dataType(Data) when is_atom(Data) -> atom; dataType(Data) when is_bitstring(Data) -> bitstring; dataType(Data) when is_boolean(Data) -> boolean; dataType(Data) when is_float(Data) -> float; dataType(Data) when is_number(Data) -> number; dataType(Data) when is_pid(Data) -> pid; dataType(Data) when is_port(Data) -> port; dataType(_Data) -> not_know. encodeAtom(undefined) -> {<<24/integer>>, 1}; encodeAtom(false) -> {<<25/integer>>, 1}; encodeAtom(true) -> {<<26/integer>>, 1}; encodeAtom(minKey) -> {<<30/integer>>, 1}; encodeAtom(maxKey) -> {<<31/integer>>, 1}; encodeAtom(Atom) -> encodeString(erlang:atom_to_binary(Atom, utf8)). encodeInteger(0) -> {<<48/integer>>, 1}; encodeInteger(1) -> {<<49/integer>>, 1}; encodeInteger(2) -> {<<50/integer>>, 1}; encodeInteger(3) -> {<<51/integer>>, 1}; encodeInteger(4) -> {<<52/integer>>, 1}; encodeInteger(5) -> {<<53/integer>>, 1}; encodeInteger(6) -> {<<54/integer>>, 1}; encodeInteger(7) -> {<<55/integer>>, 1}; encodeInteger(8) -> {<<56/integer>>, 1}; encodeInteger(9) -> {<<57/integer>>, 1}; encodeInteger(-6) -> {<<58/integer>>, 1}; encodeInteger(-5) -> {<<59/integer>>, 1}; encodeInteger(-4) -> {<<60/integer>>, 1}; encodeInteger(-3) -> {<<61/integer>>, 1}; encodeInteger(-2) -> {<<62/integer>>, 1}; encodeInteger(-1) -> {<<63/integer>>, 1}; encodeInteger(Integer) -> if Integer < -9223372036854775808 -> erlang:throw({error, too_small_integer}); Integer < -36028797018963968 -> {<<39/integer, Integer:64/integer-little-signed>>, 9}; Integer < -140737488355328 -> {<<38/integer, Integer:56/integer-little-signed>>, 8}; Integer < -549755813888 -> {<<37/integer, Integer:48/integer-little-signed>>, 7}; Integer < -2147483648 -> {<<36/integer, Integer:40/integer-little-signed>>, 6}; Integer < -8388608 -> {<<35/integer, Integer:32/integer-little-signed>>, 5}; Integer < -32768 -> {<<34/integer, Integer:24/integer-little-signed>>, 4}; Integer < -128 -> {<<33/integer, Integer:16/integer-little-signed>>, 3}; Integer < 0 -> {<<32/integer, Integer:8/integer-little-unsigned>>, 2}; Integer < 256 -> {<<40/integer, Integer:8/integer-little-unsigned>>, 2}; Integer < 65536 -> {<<41/integer, Integer:16/integer-little-unsigned>>, 3}; Integer < 16777216 -> {<<42/integer, Integer:24/integer-little-unsigned>>, 4}; Integer < 4294967296 -> {<<43/integer, Integer:32/integer-little-unsigned>>, 5}; Integer < 1099511627776 -> {<<44/integer, Integer:40/integer-little-unsigned>>, 6}; Integer < 281474976710656 -> {<<45/integer, Integer:48/integer-little-unsigned>>, 7}; Integer < 72057594037927936 -> {<<46/integer, Integer:56/integer-little-unsigned>>, 8}; Integer < 18446744073709551616 -> {<<47/integer, Integer:64/integer-little-unsigned>>, 9}; true -> erlang:throw({error, too_big_integer}) end. encodeFloat(Float) -> {<<27/integer, Float:64/float-little>>, 9}. encodeString(BinStr) -> StrSize = erlang:byte_size(BinStr), if StrSize =< 126 -> {<<(StrSize + 64)/integer, BinStr/binary>>, StrSize + 1}; StrSize < 18446744073709551616 -> {<<191/integer, StrSize:64/integer-little-unsigned, BinStr/binary>>, StrSize + 9}; true -> erlang:throw({error, too_max_str}) end. encodeBlob(Blob) -> StrSize = erlang:byte_size(Blob), if StrSize < 256 -> {<<192/integer, StrSize:8/integer-little-unsigned, Blob/binary>>, StrSize + 2}; StrSize < 65536 -> {<<193/integer, StrSize:16/integer-little-unsigned, Blob/binary>>, StrSize + 3}; StrSize < 16777216 -> {<<194/integer, StrSize:24/integer-little-unsigned, Blob/binary>>, StrSize + 4}; StrSize < 4294967296 -> {<<195/integer, StrSize:32/integer-little-unsigned, Blob/binary>>, StrSize + 5}; StrSize < 1099511627776 -> {<<196/integer, StrSize:40/integer-little-unsigned, Blob/binary>>, StrSize + 6}; StrSize < 281474976710656 -> {<<197/integer, StrSize:48/integer-little-unsigned, Blob/binary>>, StrSize + 7}; StrSize < 72057594037927936 -> {<<198/integer, StrSize:56/integer-little-unsigned, Blob/binary>>, StrSize + 8}; StrSize < 18446744073709551616 -> {<<199/integer, StrSize:64/integer-little-unsigned, Blob/binary>>, StrSize + 9}; true -> erlang:throw({error, too_max_blob}) end. doEncodeMap(Iterator, ArrOpt, ObjOpt, AccList, SumSize) -> case maps:next(Iterator) of {Key, Value, NextIter} -> {KeyEn, KeySize} = encodeString(asKey(Key)), {ValueEn, ValueSize} = encoder(Value, ArrOpt, ObjOpt), doEncodeMap(NextIter, ArrOpt, ObjOpt, [ValueEn, KeyEn | AccList], SumSize + KeySize + ValueSize); none -> {AccList, SumSize} end. doEncodeMap(Iterator, ArrOpt, ObjOpt, AccList, Offsets, SumSize) -> case maps:next(Iterator) of {Key, Value, NextIter} -> {KeyEn, KeySize} = encodeString(asKey(Key)), {ValueEn, ValueSize} = encoder(Value, ArrOpt, ObjOpt), doEncodeMap(NextIter, ArrOpt, ObjOpt, [ValueEn, KeyEn | AccList], [SumSize | Offsets], SumSize + KeySize + ValueSize); none -> {AccList, Offsets, SumSize} end. doEncodeMap([], _Map, _ArrOpt, _ObjOpt, AccList, Offsets, SumSize) -> {AccList, Offsets, SumSize}; doEncodeMap([OneKeys | Left], Map, ArrOpt, ObjOpt, AccList, Offsets, SumSize) -> case Map of #{OneKeys := Value} -> {KeyEn, KeySize} = encodeString(OneKeys), {ValueEn, ValueSize} = encoder(Value, ArrOpt, ObjOpt), doEncodeMap(Left, Map, ArrOpt, ObjOpt, [ValueEn, KeyEn | AccList], [SumSize | Offsets], SumSize + KeySize + ValueSize); _ -> AtomKey = binary_to_atom(OneKeys, utf8), case Map of #{AtomKey := Value} -> {KeyEn, KeySize} = encodeString(OneKeys), {ValueEn, ValueSize} = encoder(Value, ArrOpt, ObjOpt), doEncodeMap(Left, Map, ArrOpt, ObjOpt, [ValueEn, KeyEn | AccList], [SumSize | Offsets], SumSize + KeySize + ValueSize); _ -> erlang:throw({error, {no_map_value, OneKeys}}) end end. encodeMap(?VpObjNcNs, Map, ArrOpt) -> MapSize = erlang:map_size(Map), case MapSize == 0 of true -> {<<10/integer>>, 1}; _ -> {AccList, Offsets, SumSize} = doEncodeMap(maps:iterator(Map), ArrOpt, ?VpObjNcNs, [], [], 0), IoData = lists:reverse(AccList), encodeUnSortMapIndexTable(IoData, MapSize, Offsets, SumSize) end; encodeMap(?VpObjYc, Map, ArrOpt) -> MapSize = erlang:map_size(Map), case MapSize == 0 of true -> {<<10/integer>>, 1}; _ -> {AccList, SumSize} = doEncodeMap(maps:iterator(Map), ArrOpt, ?VpObjYc, [], 0), IoData = lists:reverse(AccList), encodeCompactData(<<20/integer>>, IoData, SumSize, MapSize) end; encodeMap(?VpObjNcYs, Map, ArrOpt) -> MapSize = erlang:map_size(Map), case MapSize == 0 of true -> {<<10/integer>>, 1}; _ -> Keys = maps:keys(Map), StrKeys = [asKey(OneKey) || OneKey <- Keys], {AccList, Offsets, SumSize} = doEncodeMap(lists:sort(StrKeys), Map, ArrOpt, ?VpObjNcYs, [], [], 0), IoData = lists:reverse(AccList), encodeSortMapIndexTable(IoData, MapSize, Offsets, SumSize) end. encodeSortMapIndexTable(IoData, Count, Offsets, SumSize) -> TemSize = SumSize + Count, if TemSize < 253 -> AllSize = TemSize + 3, Header = <<11/integer, AllSize:8/integer-unsigned, Count:8/integer-unsigned>>, {[Header, IoData, buildIndexTable_1(Offsets, 3)], AllSize}; TemSize + Count < 65531 -> AllSize = TemSize + Count + 5, Header = <<12/integer, AllSize:16/integer-little-unsigned, Count:16/integer-little-unsigned>>, {[Header, IoData, buildIndexTable_2(Offsets, 5)], AllSize}; TemSize + Count * 3 < 4294967287 -> AllSize = TemSize + Count * 3 + 9, Header = <<13/integer, AllSize:32/integer-little-unsigned, Count:32/integer-little-unsigned>>, {[Header, IoData, buildIndexTable_4(Offsets, 9)], AllSize}; TemSize + Count * 7 < 18446744073709551599 -> AllSize = TemSize + Count * 7 + 17, Header = <<14/integer, AllSize:64/integer-little-unsigned>>, {[Header, IoData, buildIndexTable_8(Offsets, 9), <>], AllSize}; true -> erlang:throw({error, too_much_sort_map_size}) end. encodeUnSortMapIndexTable(IoData, Count, Offsets, SumSize) -> TemSize = SumSize + Count, if TemSize < 253 -> AllSize = TemSize + 3, Header = <<15/integer, AllSize:8/integer-unsigned, Count:8/integer-unsigned>>, {[Header, IoData, buildIndexTable_1(Offsets, 3)], AllSize}; TemSize + Count < 65531 -> AllSize = TemSize + Count + 5, Header = <<16/integer, AllSize:16/integer-little-unsigned, Count:16/integer-little-unsigned>>, {[Header, IoData, buildIndexTable_2(Offsets, 5)], AllSize}; TemSize + Count * 3 < 4294967287 -> AllSize = TemSize + Count * 3 + 9, Header = <<17/integer, AllSize:32/integer-little-unsigned, Count:32/integer-little-unsigned>>, {[Header, IoData, buildIndexTable_4(Offsets, 9)], AllSize}; TemSize + Count * 7 < 18446744073709551599 -> AllSize = TemSize + Count * 7 + 17, Header = <<18/integer, AllSize:64/integer-little-unsigned>>, {[Header, IoData, buildIndexTable_8(Offsets, 9), <>], AllSize}; true -> erlang:throw({error, too_much_unsort_map_size}) end. buildIndexTable_1(Offsets, StartSize) -> <<<<(OneOff + StartSize):1/integer-little-unsigned-unit:8>> || OneOff <- Offsets>>. buildIndexTable_2(Offsets, StartSize) -> <<<<(OneOff + StartSize):2/integer-little-unsigned-unit:8>> || OneOff <- Offsets>>. buildIndexTable_4(Offsets, StartSize) -> <<<<(OneOff + StartSize):4/integer-little-unsigned-unit:8>> || OneOff <- Offsets>>. buildIndexTable_8(Offsets, StartSize) -> <<<<(OneOff + StartSize):8/integer-little-unsigned-unit:8>> || OneOff <- Offsets>>. compactIntegerList(Integer, AccList) -> case Integer < 128 of true -> [<> | AccList]; _ -> TemInteger = Integer band 127 bor 128, NewInteger = Integer bsr 7, compactIntegerList(NewInteger, [<> | AccList]) end. compactInteger(Value, Reverse) -> CompactList = compactIntegerList(Value, []), case Reverse of false -> lists:reverse(CompactList); _ -> CompactList end. compactSize(AllSize) -> TemByte = erlang:ceil(AllSize / 128), FinalSize = AllSize + TemByte, LastSize = case TemByte == erlang:ceil(FinalSize / 128) of false -> FinalSize + 1; _ -> FinalSize end, {compactInteger(LastSize, false), LastSize}. encodeCompactData(Type, IoData, SumSize, Count) -> CompactList = compactInteger(Count, true), AllSize = SumSize + 1 + erlang:length(CompactList), {TotalSize, FinalSize} = compactSize(AllSize), {[Type, TotalSize, IoData | CompactList], FinalSize}. asKey(Value) when erlang:is_atom(Value) -> erlang:atom_to_binary(Value, utf8); asKey(Value) when erlang:is_binary(Value) -> Value; asKey(_Value) -> erlang:throw({error, invalid_key}). doEncodeList([], _ArrOpt, _ObjOpt, AccList, SumSize, Count) -> {AccList, SumSize, Count}; doEncodeList([One | Left], ArrOpt, ObjOpt, AccList, SumSize, Count) -> {ValueEn, ValueSize} = encoder(One, ArrOpt, ObjOpt), doEncodeList(Left, ArrOpt, ObjOpt, [ValueEn | AccList], SumSize + ValueSize, Count + 1). doEncodeList([], _ArrOpt, _ObjOpt, AccList, Offsets, SumSize, Count, SizeOrIsNot) -> {AccList, Offsets, SumSize, Count, SizeOrIsNot}; doEncodeList([One | Left], ArrOpt, ObjOpt, AccList, Offsets, SumSize, Count, SizeOrIsNot) -> {ValueEn, ValueSize} = encoder(One, ArrOpt, ObjOpt), case SizeOrIsNot of true -> doEncodeList(Left, ArrOpt, ObjOpt, [ValueEn | AccList], [SumSize | Offsets], ValueSize + SumSize, Count + 1, SizeOrIsNot); init -> doEncodeList(Left, ArrOpt, ObjOpt, [ValueEn | AccList], [SumSize | Offsets], ValueSize + SumSize, Count + 1, ValueSize); _ -> doEncodeList(Left, ArrOpt, ObjOpt, [ValueEn | AccList], [SumSize | Offsets], ValueSize + SumSize, Count + 1, ValueSize =/= SizeOrIsNot orelse SizeOrIsNot) end. encodeList(?VpArrNc, List, ObjOpt) -> case List of [] -> {<<1/integer>>, 1}; _ -> {AccList, Offsets, SumSize, Count, IsNotSameSize} = doEncodeList(List, ?VpArrNc, ObjOpt, [], [], 0, 0, init), IoData = lists:reverse(AccList), case IsNotSameSize of true -> encodeListWithIndexTable(IoData, Count, Offsets, SumSize); _ -> encodeListWithoutIndexTable(IoData, SumSize) end end; encodeList(?VpArrYc, List, ObjOpt) -> case List of [] -> {<<1/integer>>, 1}; _ -> {AccList, SumSize, Count} = doEncodeList(List, ?VpArrYc, ObjOpt, [], 0, 0), IoData = lists:reverse(AccList), encodeCompactData(<<19/integer>>, IoData, SumSize, Count) end. encodeListWithoutIndexTable(IoData, SumSize) -> if SumSize < 254 -> AllSize = SumSize + 2, Header = <<2/integer, AllSize:1/integer-little-unsigned-unit:8>>, {[Header, IoData], AllSize}; SumSize < 65533 -> AllSize = SumSize + 3, Header = <<3/integer, AllSize:2/integer-little-unsigned-unit:8>>, {[Header, IoData], AllSize}; SumSize < 4294967291 -> AllSize = SumSize + 5, Header = <<4/integer, AllSize:4/integer-little-unsigned-unit:8>>, {[Header, IoData], AllSize}; SumSize < 18446744073709551607 -> AllSize = SumSize + 9, Header = <<5/integer, AllSize:8/integer-little-unsigned-unit:8>>, {[Header, IoData], AllSize}; true -> erlang:throw({error, too_much_wo_list_size}) end. encodeListWithIndexTable(IoData, Count, Offsets, SumSize) -> TemSize = SumSize + Count, if TemSize < 253 -> AllSize = TemSize + 3, Header = <<6/integer, AllSize:8/integer-unsigned, Count:8/integer-unsigned>>, {[Header, IoData, buildIndexTable_1(Offsets, 3)], AllSize}; TemSize + Count < 65531 -> AllSize = TemSize + Count + 5, Header = <<7/integer, AllSize:16/integer-little-unsigned, Count:16/integer-little-unsigned>>, {[Header, IoData, buildIndexTable_2(Offsets, 5)], AllSize}; TemSize + Count * 3 < 4294967287 -> AllSize = TemSize + Count * 3 + 9, Header = <<8/integer, AllSize:32/integer-little-unsigned, Count:32/integer-little-unsigned>>, {[Header, IoData, buildIndexTable_4(Offsets, 9)], AllSize}; TemSize + Count * 7 < 18446744073709551599 -> AllSize = TemSize + Count * 7 + 17, Header = <<9/integer, AllSize:64/integer-little-unsigned>>, {[Header, IoData, buildIndexTable_8(Offsets, 9), <>], AllSize}; true -> erlang:throw({error, too_much_wi_list_size}) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% decode %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec decodeAll(vpack()) -> {term(), term()}. decodeAll(DataBin) -> {HeaderTerm, BodyBin} = decoder(DataBin), case BodyBin of <<>> -> {HeaderTerm, #{}}; _ -> {BodyTerm, _LeftBin} = decoder(BodyBin), {HeaderTerm, BodyTerm} end. -spec decodeHeader(vpack()) -> term(). decodeHeader(DataBin) -> {HeaderTerm, _BodyBin} = decoder(DataBin), HeaderTerm. -spec decodePart(vpack()) -> {term(), binary()}. decodePart(DataBin) -> decoder(DataBin). decoder(DataBin) -> case DataBin of <> -> decoder(Type, RestBin); _ -> erlang:throw({error, unexpected_end}) end. decoder(0, RestBin) -> erlang:throw({error, {unsupported_type, RestBin}}); decoder(1, RestBin) -> {[], RestBin}; decoder(2, RestBin) -> parseArrWithoutIndexTable(1, RestBin); decoder(3, RestBin) -> parseArrWithoutIndexTable(2, RestBin); decoder(4, RestBin) -> parseArrWithoutIndexTable(4, RestBin); decoder(5, RestBin) -> parseArrWithoutIndexTable(8, RestBin); decoder(6, RestBin) -> parseArrWithIndexTable(1, RestBin); decoder(7, RestBin) -> parseArrWithIndexTable(2, RestBin); decoder(8, RestBin) -> parseArrWithIndexTable(4, RestBin); decoder(9, RestBin) -> parseArrWithIndexTable(8, RestBin); decoder(10, RestBin) -> {#{}, RestBin}; decoder(11, RestBin) -> parseObject(1, RestBin); decoder(12, RestBin) -> parseObject(2, RestBin); decoder(13, RestBin) -> parseObject(4, RestBin); decoder(14, RestBin) -> parseObject(8, RestBin); decoder(15, RestBin) -> parseObject(1, RestBin); decoder(16, RestBin) -> parseObject(2, RestBin); decoder(17, RestBin) -> parseObject(4, RestBin); decoder(18, RestBin) -> parseObject(8, RestBin); decoder(19, RestBin) -> parseCompactArr(RestBin); decoder(20, RestBin) -> parseCompactObj(RestBin); decoder(21, _RestBin) -> erlang:throw({error, {unsupported_type, 21}}); decoder(22, _RestBin) -> erlang:throw({error, {unsupported_type, 22}}); decoder(23, RestBin) -> {illegal, RestBin}; decoder(24, RestBin) -> {undefined, RestBin}; decoder(25, RestBin) -> {false, RestBin}; decoder(26, RestBin) -> {true, RestBin}; decoder(27, RestBin) -> <> = RestBin, {Float, LeftBin}; decoder(28, RestBin) -> <> = RestBin, {TimeMs, LeftBin}; decoder(29, _RestBin) -> erlang:throw({error, {unsupported_type, 29}}); decoder(30, RestBin) -> {minKey, RestBin}; decoder(31, RestBin) -> {maxKey, RestBin}; decoder(32, RestBin) -> parseInt(1, RestBin); decoder(33, RestBin) -> parseInt(2, RestBin); decoder(34, RestBin) -> parseInt(3, RestBin); decoder(35, RestBin) -> parseInt(4, RestBin); decoder(36, RestBin) -> parseInt(5, RestBin); decoder(37, RestBin) -> parseInt(6, RestBin); decoder(38, RestBin) -> parseInt(7, RestBin); decoder(39, RestBin) -> parseInt(8, RestBin); decoder(40, RestBin) -> parseUint(1, RestBin); decoder(41, RestBin) -> parseUint(2, RestBin); decoder(42, RestBin) -> parseUint(3, RestBin); decoder(43, RestBin) -> parseUint(4, RestBin); decoder(44, RestBin) -> parseUint(5, RestBin); decoder(45, RestBin) -> parseUint(6, RestBin); decoder(46, RestBin) -> parseUint(7, RestBin); decoder(47, RestBin) -> parseUint(8, RestBin); decoder(48, RestBin) -> {0, RestBin}; decoder(49, RestBin) -> {1, RestBin}; decoder(50, RestBin) -> {2, RestBin}; decoder(51, RestBin) -> {3, RestBin}; decoder(52, RestBin) -> {4, RestBin}; decoder(53, RestBin) -> {5, RestBin}; decoder(54, RestBin) -> {6, RestBin}; decoder(55, RestBin) -> {7, RestBin}; decoder(56, RestBin) -> {8, RestBin}; decoder(57, RestBin) -> {9, RestBin}; decoder(58, RestBin) -> {-6, RestBin}; decoder(59, RestBin) -> {-5, RestBin}; decoder(60, RestBin) -> {-4, RestBin}; decoder(61, RestBin) -> {-3, RestBin}; decoder(62, RestBin) -> {-2, RestBin}; decoder(63, RestBin) -> {-1, RestBin}; decoder(64, RestBin) -> {<<>>, RestBin}; decoder(65, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(66, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(67, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(68, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(69, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(70, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(71, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(72, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(73, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(74, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(75, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(76, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(77, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(78, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(79, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(80, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(81, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(82, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(83, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(84, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(85, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(86, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(87, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(88, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(89, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(90, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(91, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(92, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(93, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(94, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(95, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(96, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(97, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(98, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(99, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(100, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(101, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(102, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(103, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(104, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(105, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(106, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(107, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(108, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(109, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(110, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(111, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(112, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(113, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(114, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(115, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(116, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(117, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(118, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(119, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(120, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(121, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(122, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(123, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(124, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(125, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(126, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(127, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(128, RestBin) -> <> = RestBin, {BinStr, LeftBin}; decoder(129, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 65 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(130, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 66 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(131, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 67 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(132, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 68 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(133, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 69 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(134, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 70 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(135, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 71 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(136, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 72 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(137, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 73 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(138, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 74 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(139, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 75 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(140, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 76 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(141, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 77 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(142, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 78 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(143, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 79 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(144, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 80 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(145, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 81 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(146, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 82 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(147, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 83 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(148, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 84 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(149, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 85 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(150, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 86 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(151, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 87 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(152, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 88 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(153, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 89 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(154, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 90 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(155, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 91 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(156, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 92 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(157, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 93 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(158, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 94 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(159, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 95 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(160, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 96 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(161, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 97 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(162, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 98 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(163, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 99 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(164, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 100 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(165, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 101 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(166, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 102 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(167, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 103 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(168, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 104 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(169, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 105 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(170, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 106 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(171, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 107 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(172, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 108 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(173, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 109 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(174, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 110 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(175, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 111 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(176, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 112 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(177, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 113 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(178, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 114 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(179, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 115 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(180, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 116 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(181, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 117 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(182, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 118 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(183, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 119 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(184, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 120 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(185, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 121 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(186, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 122 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(187, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 123 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(188, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 124 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(189, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 125 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(190, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / 126 > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(191, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / Length > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(192, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / Length > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(193, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / Length > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(194, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / Length > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(195, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / Length > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(196, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / Length > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(197, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / Length > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(198, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / Length > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(199, RestBin) -> <> = RestBin, RefSize = binary:referenced_byte_size(RestBin), case RefSize / Length > ?VpBinaryCopyRatio of true -> {binary:copy(BinStr), LeftBin}; _ -> {BinStr, LeftBin} end; decoder(_, _) -> erlang:throw({error, unexpected_end}). parseArrayElements(<<>>, AccList) -> lists:reverse(AccList); parseArrayElements(DataBin, AccList) -> {Elem, Rest} = decoder(DataBin), parseArrayElements(Rest, [Elem | AccList]). parseArrWithIndexTable(1, DataBin) -> <> = DataBin, DataSize = erlang:byte_size(RestBin), DataLeftBin = skipZeros(RestBin), ZerosSize = DataSize - erlang:byte_size(DataLeftBin), ArrSize = SumSize - 3 - ZerosSize - Count, <> = DataLeftBin, ArrList = parseArrayElements(ArrData, []), {ArrList, LeftBin}; parseArrWithIndexTable(2, DataBin) -> <> = DataBin, IndexSize = 2 * Count, DataSize = erlang:byte_size(RestBin), DataLeftBin = skipZeros(RestBin), ZerosSize = DataSize - erlang:byte_size(DataLeftBin), ArrSize = SumSize - 5 - ZerosSize - IndexSize, <> = DataLeftBin, ArrList = parseArrayElements(ArrData, []), {ArrList, LeftBin}; parseArrWithIndexTable(4, DataBin) -> <> = DataBin, IndexSize = 4 * Count, DataSize = erlang:byte_size(RestBin), DataLeftBin = skipZeros(RestBin), ZerosSize = DataSize - erlang:byte_size(DataLeftBin), ArrSize = SumSize - 9 - ZerosSize - IndexSize, <> = DataLeftBin, ArrList = parseArrayElements(ArrData, []), {ArrList, LeftBin}; parseArrWithIndexTable(8, DataBin) -> <> = DataBin, DataSize = SumSize - 17, <> = RestBin, IndexSize = Count * 8, DataSize = DataSize - IndexSize, <> = DataBin, ArrList = parseArrayElements(ArrData, []), {ArrList, LeftBin}. parseArrWithoutIndexTable(1, DataBin) -> <> = DataBin, DataSize = erlang:byte_size(RestBin), DataLeftBin = skipZeros(RestBin), ZerosSize = DataSize - erlang:byte_size(DataLeftBin), ArrSize = SumSize - 2 - ZerosSize, <> = DataLeftBin, ArrList = parseArrayElements(ArrData, []), {ArrList, LeftBin}; parseArrWithoutIndexTable(2, DataBin) -> <> = DataBin, DataSize = erlang:byte_size(RestBin), DataLeftBin = skipZeros(RestBin), ZerosSize = DataSize - erlang:byte_size(DataLeftBin), ArrSize = SumSize - 3 - ZerosSize, <> = DataLeftBin, ArrList = parseArrayElements(ArrData, []), {ArrList, LeftBin}; parseArrWithoutIndexTable(4, DataBin) -> <> = DataBin, DataSize = erlang:byte_size(RestBin), DataLeftBin = skipZeros(RestBin), ZerosSize = DataSize - erlang:byte_size(DataLeftBin), ArrSize = SumSize - 5 - ZerosSize, <> = DataLeftBin, ArrList = parseArrayElements(ArrData, []), {ArrList, LeftBin}; parseArrWithoutIndexTable(8, DataBin) -> <> = DataBin, DataSize = erlang:byte_size(RestBin), DataLeftBin = skipZeros(RestBin), ZerosSize = DataSize - erlang:byte_size(DataLeftBin), ArrSize = SumSize - 9 - ZerosSize, <> = DataLeftBin, ArrList = parseArrayElements(ArrData, []), {ArrList, LeftBin}. parseCompactArr(DataBin) -> {ArrData, _Length, RestBin} = parseCompactHeader(DataBin), ArrList = parseArrayElements(ArrData, []), {ArrList, RestBin}. parseCompactHeader(DataBin) -> {Size, RestBin} = parseLength(DataBin, 0, 0, false), DataSize = Size - (erlang:byte_size(DataBin) - erlang:byte_size(RestBin)) - 1, <> = RestBin, {Length, HeaderBin} = parseLength(ArrData, 0, 0, true), {HeaderBin, Length, LeftBin}. parseCompactObj(DataBin) -> {ObjData, Length, RestBin} = parseCompactHeader(DataBin), {Obj, <<>>} = parseObjMembers(Length, #{}, ObjData), {Obj, RestBin}. parseInt(IntegerSize, DataBin) -> <> = DataBin, {Integer, LeftBin}. parseUint(IntegerSize, DataBin) -> <> = DataBin, {Integer, LeftBin}. parseLength(DataBin, Len, Pt, Reverse) -> {LastV, LeftBin} = case Reverse of false -> <> = DataBin, {V, RestBin}; _ -> Size = erlang:byte_size(DataBin) - 1, <> = DataBin, {V, RestBin} end, NewLen = Len + (LastV band 127 bsl Pt), NewPt = Pt + 7, case LastV band 128 /= 0 of false -> {NewLen, LeftBin}; _ -> parseLength(LeftBin, NewLen, NewPt, Reverse) end. parseObject(1, DataBin) -> <> = DataBin, DataSize = SumSize - 3, <> = ObjBin, {Obj, <<_IndexTable:Count/binary>>} = parseObjMembers(Count, #{}, skipZeros(ZerosBin)), {Obj, LeftBin}; parseObject(2, DataBin) -> <> = DataBin, DataSize = SumSize - 5, <> = ObjBin, IndexTableSize = Count * 2, {Obj, <<_IndexTable:IndexTableSize/binary>>} = parseObjMembers(Count, #{}, skipZeros(ZerosBin)), {Obj, LeftBin}; parseObject(4, DataBin) -> <> = DataBin, DataSize = SumSize - 9, <> = ObjBin, IndexTableSize = Count * 4, {Obj, <<_IndexTable:IndexTableSize/binary>>} = parseObjMembers(Count, #{}, skipZeros(ZerosBin)), {Obj, LeftBin}; parseObject(8, DataBin) -> <> = DataBin, DataSize = SumSize - 17, <> = RestBin, IndexTableSize = Count * 8, {Obj, <<_IndexTable:IndexTableSize/binary>>} = parseObjMembers(Count, #{}, skipZeros(ObjBin)), {Obj, LeftBin}. parseObjMembers(0, Obj, DataBin) -> {Obj, DataBin}; parseObjMembers(Length, Obj, DataBin) -> {Key, ValueDataBin} = decoder(DataBin), {Value, LeftBin} = decoder(ValueDataBin), NewObj = Obj#{Key => Value}, parseObjMembers(Length - 1, NewObj, LeftBin). skipZeros(<<0/integer, LeftBin/binary>>) -> skipZeros(LeftBin); skipZeros(DataBin) -> DataBin.