-module(packkit@lz4). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/packkit/lz4.gleam"). -export([codec/0, decode_with_limits/2, decode/1, encode/1, encode_with_content_size/1]). -export_type([legacy_blocks_step/0, blocks_step/0, block_step/0, copy_step/0]). -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( " LZ4 frame format codec.\n" "\n" " Decodes LZ4 frames (magic `0x184D2204`) as specified in the LZ4\n" " Frame Format Description. The encoder runs a greedy 4-byte hash-\n" " chain match-finder over each block and emits the LZ77 sequences\n" " in the canonical block layout (token byte + optional length\n" " extensions + literals + 16-bit little-endian offset + optional\n" " match-length extensions). Blocks that don't shrink are emitted\n" " in the uncompressed form to guarantee the frame never grows\n" " beyond `1 + ceil(input_size / block_max) * (4 + block_max)`.\n" ). -type legacy_blocks_step() :: {legacy_blocks_done, bitstring()} | {legacy_blocks_continue, bitstring(), bitstring()}. -type blocks_step() :: {blocks_done, bitstring()} | {blocks_continue, bitstring(), bitstring()}. -type block_step() :: {block_done, bitstring()} | {block_continue, bitstring(), bitstring()}. -type copy_step() :: {copy_done, bitstring()} | {copy_continue, bitstring(), integer()}. -file("src/packkit/lz4.gleam", 58). ?DOC(" LZ4 frame codec smart constructor.\n"). -spec codec() -> packkit@codec:codec(). codec() -> packkit@codec:lz4(). -file("src/packkit/lz4.gleam", 356). -spec build_byte_table( bitstring(), integer(), gleam@dict:dict(integer(), integer()) ) -> gleam@dict:dict(integer(), integer()). build_byte_table(Bytes, Index, Acc) -> case Bytes of <> -> build_byte_table(Rest, Index + 1, gleam@dict:insert(Acc, Index, B)); _ -> Acc end. -file("src/packkit/lz4.gleam", 368). -spec byte_at(gleam@dict:dict(integer(), integer()), integer()) -> integer(). byte_at(Table, Index) -> case gleam_stdlib:map_get(Table, Index) of {ok, B} -> B; _ -> 0 end. -file("src/packkit/lz4.gleam", 375). -spec hash4(integer(), integer(), integer(), integer()) -> integer(). hash4(B0, B1, B2, B3) -> Combined = erlang:'bor'( B0, erlang:'bor'( erlang:'bsl'(B1, 8), erlang:'bor'(erlang:'bsl'(B2, 16), erlang:'bsl'(B3, 24)) ) ), erlang:'band'(Combined * 2654435761, 16#FFFF). -file("src/packkit/lz4.gleam", 393). -spec bytes4_equal(gleam@dict:dict(integer(), integer()), integer(), integer()) -> boolean(). bytes4_equal(Table, P1, P2) -> (((byte_at(Table, P1) =:= byte_at(Table, P2)) andalso (byte_at( Table, P1 + 1 ) =:= byte_at(Table, P2 + 1))) andalso (byte_at(Table, P1 + 2) =:= byte_at(Table, P2 + 2))) andalso (byte_at(Table, P1 + 3) =:= byte_at(Table, P2 + 3)). -file("src/packkit/lz4.gleam", 400). -spec lz4_match_length( gleam@dict:dict(integer(), integer()), integer(), integer(), integer(), integer() ) -> integer(). lz4_match_length(Table, Base, Cursor, Limit_pos, Acc) -> case (Cursor + Acc) >= Limit_pos of true -> Acc; false -> case byte_at(Table, Base + Acc) =:= byte_at(Table, Cursor + Acc) of true -> lz4_match_length(Table, Base, Cursor, Limit_pos, Acc + 1); false -> Acc end end. -file("src/packkit/lz4.gleam", 498). -spec encode_length_extension(integer()) -> bitstring(). encode_length_extension(N) -> case N of N@1 when N@1 < 255 -> <>; _ -> gleam_stdlib:bit_array_concat( [<<16#FF>>, encode_length_extension(N - 255)] ) end. -file("src/packkit/lz4.gleam", 505). -spec collect_bytes( gleam@dict:dict(integer(), integer()), integer(), integer(), bitstring() ) -> bitstring(). collect_bytes(Table, Start, Count, Acc) -> case Count of 0 -> Acc; _ -> collect_bytes( Table, Start + 1, Count - 1, <> ) end. -file("src/packkit/lz4.gleam", 480). -spec emit_literal_only_chunk( gleam@dict:dict(integer(), integer()), integer(), integer() ) -> bitstring(). emit_literal_only_chunk(Table, Start, Lit_len) -> Lit_high = case Lit_len >= 15 of true -> 15; false -> Lit_len end, Token = erlang:'bsl'(Lit_high, 4), Lit_ext = case Lit_len >= 15 of true -> encode_length_extension(Lit_len - 15); false -> <<>> end, Literals = collect_bytes(Table, Start, Lit_len, <<>>), gleam_stdlib:bit_array_concat([<>, Lit_ext, Literals]). -file("src/packkit/lz4.gleam", 475). -spec emit_literal_only_block(bitstring(), integer(), integer()) -> bitstring(). emit_literal_only_block(Bytes, Start, Size) -> Table = build_byte_table(Bytes, 0, maps:new()), emit_literal_only_chunk(Table, Start, Size). -file("src/packkit/lz4.gleam", 703). -spec finalize(bitstring(), bitstring(), boolean()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. finalize(After_end, Output, Content_checksum) -> case Content_checksum of false -> {ok, Output}; true -> case erlang:byte_size(After_end) >= 4 of true -> {ok, Output}; false -> {error, {codec_invalid_data, <<"lz4: content checksum missing"/utf8>>}} end end. -file("src/packkit/lz4.gleam", 834). -spec read_extension(bitstring(), integer()) -> {ok, {integer(), bitstring()}} | {error, packkit@error:codec_error()}. read_extension(Bytes, Acc) -> case Bytes of <> -> case B of 16#FF -> read_extension(Rest, Acc + 16#FF); _ -> {ok, {Acc + B, Rest}} end; _ -> {error, {codec_invalid_data, <<"lz4: length extension truncated"/utf8>>}} end. -file("src/packkit/lz4.gleam", 911). -spec append_with_limit(bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. append_with_limit(Output, Chunk, Limits) -> Projected = erlang:byte_size(Output) + erlang:byte_size(Chunk), case Projected > packkit@limit:max_output_bytes(Limits) of true -> {error, {codec_limit_exceeded, <<"max_output_bytes"/utf8>>, Projected}}; false -> {ok, gleam_stdlib:bit_array_concat([Output, Chunk])} end. -file("src/packkit/lz4.gleam", 894). -spec copy_match_byte_step( bitstring(), integer(), integer(), packkit@limit:limits() ) -> {ok, copy_step()} | {error, packkit@error:codec_error()}. copy_match_byte_step(Output, Offset, Length, Limits) -> case Length of 0 -> {ok, {copy_done, Output}}; _ -> Size = erlang:byte_size(Output), Byte_slice@1 = case gleam_stdlib:bit_array_slice( Output, Size - Offset, 1 ) of {ok, Byte_slice} -> Byte_slice; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"copy_match_byte_step"/utf8>>, line => 904, value => _assert_fail, start => 26798, 'end' => 26867, pattern_start => 26809, pattern_end => 26823}) end, gleam@result:'try'( append_with_limit(Output, Byte_slice@1, Limits), fun(New_output) -> {ok, {copy_continue, New_output, Length - 1}} end ) end. -file("src/packkit/lz4.gleam", 875). -spec copy_match_byte_by_byte( bitstring(), integer(), integer(), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. copy_match_byte_by_byte(Output, Offset, Length, Limits) -> case copy_match_byte_step(Output, Offset, Length, Limits) of {error, Err} -> {error, Err}; {ok, {copy_done, Out}} -> {ok, Out}; {ok, {copy_continue, New_output, New_length}} -> copy_match_byte_by_byte(New_output, Offset, New_length, Limits) end. -file("src/packkit/lz4.gleam", 849). -spec copy_match(bitstring(), integer(), integer(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. copy_match(Output, Offset, Length, Limits) -> case Length of 0 -> {ok, Output}; _ -> Size = erlang:byte_size(Output), case Offset >= Length of true -> Chunk@1 = case gleam_stdlib:bit_array_slice( Output, Size - Offset, Length ) of {ok, Chunk} -> Chunk; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"copy_match"/utf8>>, line => 861, value => _assert_fail, start => 25518, 'end' => 25587, pattern_start => 25529, pattern_end => 25538}) end, append_with_limit(Output, Chunk@1, Limits); false -> copy_match_byte_by_byte(Output, Offset, Length, Limits) end end. -file("src/packkit/lz4.gleam", 756). -spec decode_block_step(bitstring(), bitstring(), packkit@limit:limits()) -> {ok, block_step()} | {error, packkit@error:codec_error()}. decode_block_step(Block, Output, Limits) -> case Block of <> -> Lit_len_base = erlang:'bsr'(Token, 4), Match_len_base = erlang:'band'(Token, 16#0F), gleam@result:'try'(case Lit_len_base of 15 -> read_extension(Rest, 15); _ -> {ok, {Lit_len_base, Rest}} end, fun(_use0) -> {Lit_len, Rest@1} = _use0, case erlang:byte_size(Rest@1) < Lit_len of true -> {error, {codec_invalid_data, <<"lz4: literal length exceeds block payload"/utf8>>}}; false -> Literals@1 = case gleam_stdlib:bit_array_slice( Rest@1, 0, Lit_len ) of {ok, Literals} -> Literals; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"decode_block_step"/utf8>>, line => 777, value => _assert_fail, start => 22993, 'end' => 23052, pattern_start => 23004, pattern_end => 23016}) end, After_literals@1 = case gleam_stdlib:bit_array_slice( Rest@1, Lit_len, erlang:byte_size(Rest@1) - Lit_len ) of {ok, After_literals} -> After_literals; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"decode_block_step"/utf8>>, line => 778, value => _assert_fail@1, start => 23063, 'end' => 23174, pattern_start => 23074, pattern_end => 23092}) end, gleam@result:'try'( append_with_limit(Output, Literals@1, Limits), fun(Output@1) -> case erlang:byte_size(After_literals@1) of 0 -> {ok, {block_done, Output@1}}; _ -> case After_literals@1 of <> -> gleam@bool:guard( Offset =:= 0, {error, {codec_invalid_data, <<"lz4: zero match offset"/utf8>>}}, fun() -> gleam@result:'try'( case Match_len_base of 15 -> read_extension( After_offset, 15 ); _ -> {ok, {Match_len_base, After_offset}} end, fun(_use0@1) -> {Match_len_extra, After_offset@1} = _use0@1, Match_len = Match_len_extra + 4, gleam@bool:guard( Offset > erlang:byte_size( Output@1 ), {error, {codec_invalid_data, <<"lz4: match offset exceeds output"/utf8>>}}, fun() -> gleam@result:'try'( copy_match( Output@1, Offset, Match_len, Limits ), fun( Output@2 ) -> {ok, {block_continue, After_offset@1, Output@2}} end ) end ) end ) end ); _ -> {error, {codec_invalid_data, <<"lz4: match offset truncated"/utf8>>}} end end end ) end end); <<>> -> {ok, {block_done, Output}}; _ -> {error, {codec_invalid_data, <<"lz4: malformed block"/utf8>>}} end. -file("src/packkit/lz4.gleam", 738). -spec decode_block_loop(bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode_block_loop(Block, Output, Limits) -> case decode_block_step(Block, Output, Limits) of {error, Err} -> {error, Err}; {ok, {block_done, Out}} -> {ok, Out}; {ok, {block_continue, Next_block, Next_output}} -> decode_block_loop(Next_block, Next_output, Limits) end. -file("src/packkit/lz4.gleam", 719). -spec decode_block(bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode_block(Block, Output, Limits) -> case erlang:byte_size(Block) of 0 -> {ok, Output}; _ -> decode_block_loop(Block, Output, Limits) end. -file("src/packkit/lz4.gleam", 927). -spec maybe_skip(bitstring(), boolean(), integer(), binary()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. maybe_skip(Bytes, Active, Count, Message) -> case Active of false -> {ok, Bytes}; true -> case erlang:byte_size(Bytes) < Count of true -> {error, {codec_invalid_data, Message}}; false -> After@1 = case gleam_stdlib:bit_array_slice( Bytes, Count, erlang:byte_size(Bytes) - Count ) of {ok, After} -> After; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"maybe_skip"/utf8>>, line => 939, value => _assert_fail, start => 27760, 'end' => 27860, pattern_start => 27771, pattern_end => 27780}) end, {ok, After@1} end end. -file("src/packkit/lz4.gleam", 947). -spec block_max_bytes(integer()) -> integer(). block_max_bytes(Index) -> case Index of 4 -> 64000; 5 -> 256000; 6 -> 1000000; 7 -> 4000000; _ -> 4000000 end. -file("src/packkit/lz4.gleam", 542). -spec decode_legacy_blocks_step( bitstring(), bitstring(), packkit@limit:limits() ) -> {ok, legacy_blocks_step()} | {error, packkit@error:codec_error()}. decode_legacy_blocks_step(Bytes, Output, Limits) -> case Bytes of <<>> -> {ok, {legacy_blocks_done, Output}}; <> when Block_size =:= 0 -> {ok, {legacy_blocks_done, Output}}; <> when Block_size@1 > 8388608 -> {ok, {legacy_blocks_done, Output}}; <> -> case erlang:byte_size(Rest) < Block_size@2 of true -> {error, {codec_invalid_data, <<"lz4 legacy: block payload truncated"/utf8>>}}; false -> Block@1 = case gleam_stdlib:bit_array_slice( Rest, 0, Block_size@2 ) of {ok, Block} -> Block; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"decode_legacy_blocks_step"/utf8>>, line => 569, value => _assert_fail, start => 16860, 'end' => 16919, pattern_start => 16871, pattern_end => 16880}) end, After_block@1 = case gleam_stdlib:bit_array_slice( Rest, Block_size@2, erlang:byte_size(Rest) - Block_size@2 ) of {ok, After_block} -> After_block; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"decode_legacy_blocks_step"/utf8>>, line => 570, value => _assert_fail@1, start => 16930, 'end' => 17101, pattern_start => 16941, pattern_end => 16956}) end, gleam@result:'try'( decode_block(Block@1, Output, Limits), fun(New_output) -> {ok, {legacy_blocks_continue, After_block@1, New_output}} end ) end; _ -> {error, {codec_invalid_data, <<"lz4 legacy: block header truncated"/utf8>>}} end. -file("src/packkit/lz4.gleam", 524). -spec decode_legacy_blocks(bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode_legacy_blocks(Bytes, Output, Limits) -> case decode_legacy_blocks_step(Bytes, Output, Limits) of {error, Err} -> {error, Err}; {ok, {legacy_blocks_done, Out}} -> {ok, Out}; {ok, {legacy_blocks_continue, Next_bytes, Next_output}} -> decode_legacy_blocks(Next_bytes, Next_output, Limits) end. -file("src/packkit/lz4.gleam", 630). -spec decode_blocks_step( bitstring(), bitstring(), boolean(), boolean(), integer(), packkit@limit:limits() ) -> {ok, blocks_step()} | {error, packkit@error:codec_error()}. decode_blocks_step( Bytes, Output, Block_checksum, Content_checksum, Block_max, Limits ) -> case Bytes of <<0:32/little, Rest/binary>> -> case finalize(Rest, Output, Content_checksum) of {ok, Out} -> {ok, {blocks_done, Out}}; {error, Err} -> {error, Err} end; <> -> Uncompressed = erlang:'band'(Header, 16#80000000) /= 0, Block_size = erlang:'band'( Header, erlang:'bxor'(16#FFFFFFFF, 16#80000000) ), gleam@bool:guard( Block_size > Block_max, {error, {codec_invalid_data, <<"lz4: block size exceeds frame max block size"/utf8>>}}, fun() -> case erlang:byte_size(Rest@1) < Block_size of true -> {error, {codec_invalid_data, <<"lz4: block payload truncated"/utf8>>}}; false -> Block@1 = case gleam_stdlib:bit_array_slice( Rest@1, 0, Block_size ) of {ok, Block} -> Block; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"decode_blocks_step"/utf8>>, line => 662, value => _assert_fail, start => 19471, 'end' => 19530, pattern_start => 19482, pattern_end => 19491}) end, After_block@1 = case gleam_stdlib:bit_array_slice( Rest@1, Block_size, erlang:byte_size(Rest@1) - Block_size ) of {ok, After_block} -> After_block; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"decode_blocks_step"/utf8>>, line => 663, value => _assert_fail@1, start => 19541, 'end' => 19712, pattern_start => 19552, pattern_end => 19567}) end, gleam@result:'try'(case Block_checksum of true -> case erlang:byte_size(After_block@1) < 4 of true -> {error, {codec_invalid_data, <<"lz4: block checksum missing"/utf8>>}}; false -> After@1 = case gleam_stdlib:bit_array_slice( After_block@1, 4, erlang:byte_size( After_block@1 ) - 4 ) of {ok, After} -> After; _assert_fail@2 -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"decode_blocks_step"/utf8>>, line => 678, value => _assert_fail@2, start => 20052, 'end' => 20253, pattern_start => 20063, pattern_end => 20072} ) end, {ok, After@1} end; false -> {ok, After_block@1} end, fun(After_block@2) -> gleam@result:'try'(case Uncompressed of true -> append_with_limit( Output, Block@1, Limits ); false -> decode_block( Block@1, Output, Limits ) end, fun(New_output) -> {ok, {blocks_continue, After_block@2, New_output}} end) end) end end ); _ -> {error, {codec_invalid_data, <<"lz4: block header truncated"/utf8>>}} end. -file("src/packkit/lz4.gleam", 593). -spec decode_blocks( bitstring(), bitstring(), boolean(), boolean(), integer(), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode_blocks( Bytes, Output, Block_checksum, Content_checksum, Block_max, Limits ) -> case decode_blocks_step( Bytes, Output, Block_checksum, Content_checksum, Block_max, Limits ) of {error, Err} -> {error, Err}; {ok, {blocks_done, Out}} -> {ok, Out}; {ok, {blocks_continue, Next_bytes, Next_output}} -> decode_blocks( Next_bytes, Next_output, Block_checksum, Content_checksum, Block_max, Limits ) end. -file("src/packkit/lz4.gleam", 112). ?DOC(" Decode an LZ4 frame using explicit resource limits.\n"). -spec decode_with_limits(bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode_with_limits(Bytes, Limits) -> gleam@bool:guard( erlang:byte_size(Bytes) > packkit@limit:max_input_bytes(Limits), {error, {codec_limit_exceeded, <<"max_input_bytes"/utf8>>, erlang:byte_size(Bytes)}}, fun() -> case Bytes of <> when M =:= 16#184C2102 -> After_magic@1 = case gleam_stdlib:bit_array_slice( Bytes, 4, erlang:byte_size(Bytes) - 4 ) of {ok, After_magic} -> After_magic; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"decode_with_limits"/utf8>>, line => 126, value => _assert_fail, start => 4235, 'end' => 4329, pattern_start => 4246, pattern_end => 4261}) end, decode_legacy_blocks(After_magic@1, <<>>, Limits); <> -> gleam@bool:guard( M@1 /= 16#184D2204, {error, {codec_invalid_data, <<"lz4: bad frame magic"/utf8>>}}, fun() -> gleam@bool:guard( erlang:'band'(Flg, 16#C0) /= 16#40, {error, {codec_invalid_data, <<"lz4: unsupported frame version"/utf8>>}}, fun() -> Block_checksum = erlang:'band'(Flg, 16#10) /= 0, Content_size_present = erlang:'band'( Flg, 16#08 ) /= 0, Content_checksum = erlang:'band'(Flg, 16#04) /= 0, Dict_id_present = erlang:'band'(Flg, 16#01) /= 0, Bd_block_max_idx = erlang:'band'( erlang:'bsr'(Bd, 4), 7 ), Block_max = block_max_bytes( Bd_block_max_idx ), gleam@result:'try'( maybe_skip( Rest, Content_size_present, 8, <<"lz4: content size truncated"/utf8>> ), fun(Rest@1) -> gleam@result:'try'( maybe_skip( Rest@1, Dict_id_present, 4, <<"lz4: dictionary id truncated"/utf8>> ), fun(Rest@2) -> gleam@result:'try'( maybe_skip( Rest@2, true, 1, <<"lz4: header checksum missing"/utf8>> ), fun(Rest@3) -> decode_blocks( Rest@3, <<>>, Block_checksum, Content_checksum, Block_max, Limits ) end ) end ) end ) end ) end ); _ -> {error, {codec_invalid_data, <<"lz4: frame header truncated"/utf8>>}} end end ). -file("src/packkit/lz4.gleam", 107). ?DOC(" Decode an LZ4 frame using the default resource limits.\n"). -spec decode(bitstring()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode(Bytes) -> decode_with_limits(Bytes, packkit@limit:default()). -file("src/packkit/lz4.gleam", 417). -spec lz4_insert_hashes( gleam@dict:dict(integer(), integer()), gleam@dict:dict(integer(), integer()), integer(), integer(), integer() ) -> gleam@dict:dict(integer(), integer()). lz4_insert_hashes(Table, Hashes, From, To, Size) -> case (From > To) orelse ((From + 4) > Size) of true -> Hashes; false -> Key = hash4( byte_at(Table, From), byte_at(Table, From + 1), byte_at(Table, From + 2), byte_at(Table, From + 3) ), lz4_insert_hashes( Table, gleam@dict:insert(Hashes, Key, From), From + 1, To, Size ) end. -file("src/packkit/lz4.gleam", 445). -spec emit_sequence( gleam@dict:dict(integer(), integer()), integer(), integer(), integer(), integer() ) -> bitstring(). emit_sequence(Table, Lit_start, Lit_len, Distance, Match_len) -> Ml_stored = Match_len - 4, Lit_high = case Lit_len >= 15 of true -> 15; false -> Lit_len end, Ml_high = case Ml_stored >= 15 of true -> 15; false -> Ml_stored end, Token = erlang:'bor'(erlang:'bsl'(Lit_high, 4), Ml_high), Lit_ext = case Lit_len >= 15 of true -> encode_length_extension(Lit_len - 15); false -> <<>> end, Literals = collect_bytes(Table, Lit_start, Lit_len, <<>>), Offset = <>, Ml_ext = case Ml_stored >= 15 of true -> encode_length_extension(Ml_stored - 15); false -> <<>> end, gleam_stdlib:bit_array_concat( [<>, Lit_ext, Literals, Offset, Ml_ext] ). -file("src/packkit/lz4.gleam", 268). -spec step_compress( gleam@dict:dict(integer(), integer()), integer(), integer(), integer(), gleam@dict:dict(integer(), integer()), list(bitstring()) ) -> bitstring(). step_compress(Table, Size, Pos, Last_lit_start, Hashes, Acc) -> Key = hash4( byte_at(Table, Pos), byte_at(Table, Pos + 1), byte_at(Table, Pos + 2), byte_at(Table, Pos + 3) ), case gleam_stdlib:map_get(Hashes, Key) of {ok, Prev} -> Distance = Pos - Prev, Valid = ((Distance >= 1) andalso (Distance =< 65535)) andalso bytes4_equal( Table, Prev, Pos ), case Valid of false -> compress_loop( Table, Size, Pos + 1, Last_lit_start, gleam@dict:insert(Hashes, Key, Pos), Acc ); true -> Search_end = Size - 5, Match_len = lz4_match_length( Table, Prev, Pos, Search_end, 0 ), case Match_len < 4 of true -> compress_loop( Table, Size, Pos + 1, Last_lit_start, gleam@dict:insert(Hashes, Key, Pos), Acc ); false -> Lit_len = Pos - Last_lit_start, Seq = emit_sequence( Table, Last_lit_start, Lit_len, Distance, Match_len ), Next_pos = Pos + Match_len, New_hashes = lz4_insert_hashes( Table, gleam@dict:insert(Hashes, Key, Pos), Pos + 1, Next_pos - 1, Size ), compress_loop( Table, Size, Next_pos, Next_pos, New_hashes, [Seq | Acc] ) end end; _ -> compress_loop( Table, Size, Pos + 1, Last_lit_start, gleam@dict:insert(Hashes, Key, Pos), Acc ) end. -file("src/packkit/lz4.gleam", 248). -spec compress_loop( gleam@dict:dict(integer(), integer()), integer(), integer(), integer(), gleam@dict:dict(integer(), integer()), list(bitstring()) ) -> bitstring(). compress_loop(Table, Size, Pos, Last_lit_start, Hashes, Acc) -> Last_search = Size - 12, case Pos > Last_search of true -> Lit_len = Size - Last_lit_start, Tail = emit_literal_only_chunk(Table, Last_lit_start, Lit_len), gleam_stdlib:bit_array_concat(lists:reverse([Tail | Acc])); false -> step_compress(Table, Size, Pos, Last_lit_start, Hashes, Acc) end. -file("src/packkit/lz4.gleam", 238). -spec compress_block(bitstring(), integer()) -> bitstring(). compress_block(Bytes, Size) -> case Size =< 12 of true -> emit_literal_only_block(Bytes, 0, Size); false -> Table = build_byte_table(Bytes, 0, maps:new()), compress_loop(Table, Size, 0, 0, maps:new(), []) end. -file("src/packkit/lz4.gleam", 183). -spec encode_blocks(bitstring(), list(bitstring())) -> bitstring(). encode_blocks(Remaining, Acc) -> Total = erlang:byte_size(Remaining), case Total of 0 -> gleam_stdlib:bit_array_concat(lists:reverse(Acc)); _ -> Chunk_size = case Total > 4194304 of true -> 4194304; false -> Total end, Chunk@1 = case gleam_stdlib:bit_array_slice( Remaining, 0, Chunk_size ) of {ok, Chunk} -> Chunk; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"encode_blocks"/utf8>>, line => 192, value => _assert_fail, start => 6195, 'end' => 6259, pattern_start => 6206, pattern_end => 6215}) end, After@1 = case gleam_stdlib:bit_array_slice( Remaining, Chunk_size, Total - Chunk_size ) of {ok, After} -> After; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/lz4"/utf8>>, function => <<"encode_blocks"/utf8>>, line => 193, value => _assert_fail@1, start => 6266, 'end' => 6355, pattern_start => 6277, pattern_end => 6286}) end, Compressed = compress_block(Chunk@1, Chunk_size), Compressed_size = erlang:byte_size(Compressed), Framed = case Compressed_size < Chunk_size of true -> <>; false -> <<(erlang:'bor'(16#80000000, Chunk_size)):32/little, Chunk@1/bitstring>> end, encode_blocks(After@1, [Framed | Acc]) end. -file("src/packkit/lz4.gleam", 82). -spec encode_internal(bitstring(), boolean()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. encode_internal(Bytes, Content_size_present) -> Flg = case Content_size_present of true -> 16#60 + 16#08; false -> 16#60 end, Bd = 16#70, Descriptor = case Content_size_present of true -> <>; false -> <> end, Hc = erlang:'band'( erlang:'bsr'(packkit@internal@xxh32:digest(Descriptor, 0), 8), 16#FF ), Header = gleam_stdlib:bit_array_concat( [<<16#184D2204:32/little>>, Descriptor, <>] ), Blocks = encode_blocks(Bytes, []), End_mark = <<0:32/little>>, {ok, gleam_stdlib:bit_array_concat([Header, Blocks, End_mark])}. -file("src/packkit/lz4.gleam", 66). ?DOC( " Encode `bytes` as an LZ4 frame. The frame descriptor uses\n" " independent blocks, the v1 frame version, and a 4 MiB block\n" " maximum; no content size, block checksum, content checksum, or\n" " dictionary id is written.\n" ). -spec encode(bitstring()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. encode(Bytes) -> encode_internal(Bytes, false). -file("src/packkit/lz4.gleam", 76). ?DOC( " Encode `bytes` as an LZ4 frame and store the uncompressed\n" " content size in the frame descriptor. Strict LZ4 decoders use\n" " the value to pre-allocate the output buffer and reject any\n" " frame whose payload disagrees with the declared length; our own\n" " decoder simply skips the field today, so encoding it does not\n" " change `encode -> decode` round trips.\n" ). -spec encode_with_content_size(bitstring()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. encode_with_content_size(Bytes) -> encode_internal(Bytes, true).