-module(packkit@snappy). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/packkit/snappy.gleam"). -export([codec/0, raw_decode_with_limits/2, raw_decode/1, decode_with_limits/2, decode/1, raw_encode/1, encode/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( " Snappy raw-block and framed codec.\n" "\n" " `snappy.raw_decode` and `snappy.raw_encode` operate on the original\n" " Snappy block format documented in `snappy-format-description`.\n" " `snappy.decode` and `snappy.encode` operate on the streaming\n" " framed form (`sNaPpY` stream identifier and chunked layout). The\n" " raw encoder runs a greedy 4-byte hash-chain match-finder and\n" " emits literal + copy-1 / copy-2 / copy-4 sequences in the\n" " canonical block layout; the framed encoder dispatches each chunk\n" " through the raw encoder and picks the smaller of the compressed\n" " (`0x00`) and uncompressed (`0x01`) chunk types.\n" ). -file("src/packkit/snappy.gleam", 39). ?DOC(" Snappy framed codec smart constructor.\n"). -spec codec() -> packkit@codec:codec(). codec() -> packkit@codec:snappy(). -file("src/packkit/snappy.gleam", 258). -spec read_varint(bitstring(), integer(), integer()) -> {ok, {integer(), bitstring()}} | {error, packkit@error:codec_error()}. read_varint(Bytes, Acc, Shift) -> case Bytes of <> -> Part = erlang:'band'(B, 16#7F), Acc@1 = erlang:'bor'(Acc, erlang:'bsl'(Part, Shift)), case erlang:'band'(B, 16#80) of 0 -> {ok, {Acc@1, Rest}}; _ -> case Shift > 28 of true -> {error, {codec_invalid_data, <<"snappy: oversize varint"/utf8>>}}; false -> read_varint(Rest, Acc@1, Shift + 7) end end; _ -> {error, {codec_invalid_data, <<"snappy: truncated varint length"/utf8>>}} end. -file("src/packkit/snappy.gleam", 286). -spec write_varint_loop(integer(), bitstring()) -> bitstring(). write_varint_loop(Value, Acc) -> case Value < 16#80 of true -> gleam_stdlib:bit_array_concat([Acc, <>]); false -> Low = erlang:'band'(Value, 16#7F), High = erlang:'bsr'(Value, 7), Byte_value = erlang:'bor'(Low, 16#80), write_varint_loop( High, gleam_stdlib:bit_array_concat([Acc, <>]) ) end. -file("src/packkit/snappy.gleam", 282). -spec write_varint(integer()) -> bitstring(). write_varint(Value) -> write_varint_loop(Value, <<>>). -file("src/packkit/snappy.gleam", 369). -spec read_le(bitstring(), integer()) -> integer(). read_le(Bytes, Width) -> case {Width, Bytes} of {1, <>} -> B; {2, <>} -> B1 + (B2 * 256); {3, <>} -> (B1@1 + (B2@1 * 256)) + (B3 * 65536); {4, <>} -> ((B1@2 + (B2@2 * 256)) + (B3@1 * 65536)) + (B4 * 16777216); {_, _} -> 0 end. -file("src/packkit/snappy.gleam", 350). -spec read_literal_extra(bitstring(), integer()) -> {ok, {integer(), bitstring()}} | {error, packkit@error:codec_error()}. read_literal_extra(Rest, Width) -> case erlang:byte_size(Rest) < Width of true -> {error, {codec_invalid_data, <<"snappy: literal length extension truncated"/utf8>>}}; false -> Prefix@1 = case gleam_stdlib:bit_array_slice(Rest, 0, Width) of {ok, Prefix} -> Prefix; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/snappy"/utf8>>, function => <<"read_literal_extra"/utf8>>, line => 360, value => _assert_fail, start => 11132, 'end' => 11187, pattern_start => 11143, pattern_end => 11153}) end, After@1 = case gleam_stdlib:bit_array_slice( Rest, Width, erlang:byte_size(Rest) - Width ) 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/snappy"/utf8>>, function => <<"read_literal_extra"/utf8>>, line => 361, value => _assert_fail@1, start => 11194, 'end' => 11288, pattern_start => 11205, pattern_end => 11214}) end, Value = read_le(Prefix@1, Width), {ok, {Value + 1, After@1}} end. -file("src/packkit/snappy.gleam", 606). -spec build_snappy_byte_table( bitstring(), integer(), gleam@dict:dict(integer(), integer()) ) -> gleam@dict:dict(integer(), integer()). build_snappy_byte_table(Bytes, Index, Acc) -> case Bytes of <> -> build_snappy_byte_table( Rest, Index + 1, gleam@dict:insert(Acc, Index, B) ); _ -> Acc end. -file("src/packkit/snappy.gleam", 618). -spec snappy_byte_at(gleam@dict:dict(integer(), integer()), integer()) -> integer(). snappy_byte_at(Table, Index) -> case gleam_stdlib:map_get(Table, Index) of {ok, B} -> B; _ -> 0 end. -file("src/packkit/snappy.gleam", 625). -spec snappy_hash4(integer(), integer(), integer(), integer()) -> integer(). snappy_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/snappy.gleam", 640). -spec snappy_bytes4_equal( gleam@dict:dict(integer(), integer()), integer(), integer() ) -> boolean(). snappy_bytes4_equal(Table, P1, P2) -> (((snappy_byte_at(Table, P1) =:= snappy_byte_at(Table, P2)) andalso (snappy_byte_at( Table, P1 + 1 ) =:= snappy_byte_at(Table, P2 + 1))) andalso (snappy_byte_at(Table, P1 + 2) =:= snappy_byte_at(Table, P2 + 2))) andalso (snappy_byte_at(Table, P1 + 3) =:= snappy_byte_at(Table, P2 + 3)). -file("src/packkit/snappy.gleam", 647). -spec snappy_match_length( gleam@dict:dict(integer(), integer()), integer(), integer(), integer(), integer() ) -> integer(). snappy_match_length(Table, Base, Cursor, Limit_pos, Acc) -> case (Cursor + Acc) >= Limit_pos of true -> Acc; false -> case snappy_byte_at(Table, Base + Acc) =:= snappy_byte_at( Table, Cursor + Acc ) of true -> snappy_match_length(Table, Base, Cursor, Limit_pos, Acc + 1); false -> Acc end end. -file("src/packkit/snappy.gleam", 694). -spec snappy_slice( gleam@dict:dict(integer(), integer()), integer(), integer(), bitstring() ) -> bitstring(). snappy_slice(Table, Start, Count, Acc) -> case Count of 0 -> Acc; _ -> snappy_slice( Table, Start + 1, Count - 1, <> ) end. -file("src/packkit/snappy.gleam", 714). ?DOC( " Emit one or more copy records that together cover a single LZ77\n" " match. The Snappy 1-byte offset form caps match length at 11; the\n" " 2- and 4-byte forms cap at 64. Matches longer than 64 are split\n" " into multiple back-to-back copies sharing the same offset.\n" ). -spec emit_copy_for(integer(), integer(), bitstring()) -> bitstring(). emit_copy_for(Offset, Length, Acc) -> case Length of 0 -> Acc; _ -> case ((Offset < 2048) andalso (Length >= 4)) andalso (Length =< 11) of true -> Tag = erlang:'bor'( erlang:'bsl'(Length - 4, 2), erlang:'bor'( erlang:'bsl'(erlang:'bsr'(Offset, 8), 5), 1 ) ), <>; false -> Chunk = case Length > 64 of true -> 64; false -> Length end, Piece = case Offset < 65536 of true -> Tag@1 = erlang:'bor'(erlang:'bsl'(Chunk - 1, 2), 2), <>; false -> Tag@2 = erlang:'bor'(erlang:'bsl'(Chunk - 1, 2), 3), <> end, emit_copy_for( Offset, Length - Chunk, <> ) end end. -file("src/packkit/snappy.gleam", 772). -spec literal_extension(integer()) -> {bitstring(), integer()}. literal_extension(Encoded_len) -> case Encoded_len < 16#100 of true -> {<>, 1}; false -> case Encoded_len < 16#10000 of true -> {<>, 2}; false -> case Encoded_len < 16#1000000 of true -> {<>, 3}; false -> {<>, 4} end end end. -file("src/packkit/snappy.gleam", 751). -spec emit_literal(bitstring()) -> bitstring(). emit_literal(Bytes) -> Length = erlang:byte_size(Bytes), case Length of 0 -> <<>>; _ -> Encoded_len = Length - 1, Header = case Encoded_len < 60 of true -> <<(erlang:'bsl'(Encoded_len, 2))>>; false -> {Extra, Width} = literal_extension(Encoded_len), gleam_stdlib:bit_array_concat( [<<(erlang:'bsl'((60 + Width) - 1, 2))>>, Extra] ) end, gleam_stdlib:bit_array_concat([Header, Bytes]) end. -file("src/packkit/snappy.gleam", 787). -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/snappy.gleam", 223). -spec decode_uncompressed_chunk( bitstring(), bitstring(), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode_uncompressed_chunk(Body, Output, Limits) -> case Body of <<_:32/little, Data/binary>> -> append_with_limit(Output, Data, Limits); _ -> {error, {codec_invalid_data, <<"snappy: uncompressed chunk too short"/utf8>>}} end. -file("src/packkit/snappy.gleam", 455). -spec copy_byte_by_byte( bitstring(), integer(), integer(), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. copy_byte_by_byte(Output, Offset, Length, Limits) -> case Length of 0 -> {ok, 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/snappy"/utf8>>, function => <<"copy_byte_by_byte"/utf8>>, line => 465, value => _assert_fail, start => 13981, 'end' => 14050, pattern_start => 13992, pattern_end => 14006}) end, gleam@result:'try'( append_with_limit(Output, Byte_slice@1, Limits), fun(New_output) -> copy_byte_by_byte(New_output, Offset, Length - 1, Limits) end ) end. -file("src/packkit/snappy.gleam", 666). -spec snappy_insert_hashes( gleam@dict:dict(integer(), integer()), gleam@dict:dict(integer(), integer()), integer(), integer(), integer() ) -> gleam@dict:dict(integer(), integer()). snappy_insert_hashes(Table, Hashes, From, To, Size) -> case (From > To) orelse ((From + 4) > Size) of true -> Hashes; false -> Key = snappy_hash4( snappy_byte_at(Table, From), snappy_byte_at(Table, From + 1), snappy_byte_at(Table, From + 2), snappy_byte_at(Table, From + 3) ), snappy_insert_hashes( Table, gleam@dict:insert(Hashes, Key, From), From + 1, To, Size ) end. -file("src/packkit/snappy.gleam", 318). -spec handle_literal( integer(), bitstring(), bitstring(), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. handle_literal(Tag, Rest, Output, Limits) -> Header = erlang:'bsr'(Tag, 2), gleam@result:'try'(case Header of H when H < 60 -> {ok, {H + 1, Rest}}; 60 -> read_literal_extra(Rest, 1); 61 -> read_literal_extra(Rest, 2); 62 -> read_literal_extra(Rest, 3); _ -> read_literal_extra(Rest, 4) end, fun(_use0) -> {Length, After_extra} = _use0, case erlang:byte_size(After_extra) < Length of true -> {error, {codec_invalid_data, <<"snappy: literal run truncated"/utf8>>}}; false -> Chunk@1 = case gleam_stdlib:bit_array_slice( After_extra, 0, 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/snappy"/utf8>>, function => <<"handle_literal"/utf8>>, line => 337, value => _assert_fail, start => 10491, 'end' => 10553, pattern_start => 10502, pattern_end => 10511}) end, After@1 = case gleam_stdlib:bit_array_slice( After_extra, Length, erlang:byte_size(After_extra) - Length ) 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/snappy"/utf8>>, function => <<"handle_literal"/utf8>>, line => 338, value => _assert_fail@1, start => 10560, 'end' => 10711, pattern_start => 10571, pattern_end => 10580}) end, gleam@result:'try'( append_with_limit(Output, Chunk@1, Limits), fun(Output@1) -> decode_raw_loop(After@1, Output@1, Limits) end ) end end). -file("src/packkit/snappy.gleam", 298). -spec decode_raw_loop(bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode_raw_loop(Bytes, Output, Limits) -> case Bytes of <<>> -> {ok, Output}; <> -> Kind = erlang:'band'(Tag, 16#03), case Kind of 0 -> handle_literal(Tag, Rest, Output, Limits); 1 -> handle_copy_1(Tag, Rest, Output, Limits); 2 -> handle_copy_2(Tag, Rest, Output, Limits); _ -> handle_copy_4(Tag, Rest, Output, Limits) end; _ -> {error, {codec_invalid_data, <<"snappy: malformed raw block"/utf8>>}} end. -file("src/packkit/snappy.gleam", 82). ?DOC(" Decode a Snappy raw block using explicit resource limits.\n"). -spec raw_decode_with_limits(bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. raw_decode_with_limits(Bytes, Limits) -> gleam@result:'try'( read_varint(Bytes, 0, 0), fun(_use0) -> {Uncompressed_length, After_varint} = _use0, gleam@bool:guard( Uncompressed_length > packkit@limit:max_output_bytes(Limits), {error, {codec_limit_exceeded, <<"max_output_bytes"/utf8>>, Uncompressed_length}}, fun() -> gleam@result:'try'( decode_raw_loop(After_varint, <<>>, Limits), fun(Output) -> case erlang:byte_size(Output) =:= Uncompressed_length of true -> {ok, Output}; false -> {error, {codec_invalid_data, <<"snappy: raw output length disagrees with declared length"/utf8>>}} end end ) end ) end ). -file("src/packkit/snappy.gleam", 77). ?DOC(" Decode a single Snappy raw block.\n"). -spec raw_decode(bitstring()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. raw_decode(Bytes) -> raw_decode_with_limits(Bytes, packkit@limit:default()). -file("src/packkit/snappy.gleam", 238). -spec decode_compressed_chunk(bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode_compressed_chunk(Body, Output, Limits) -> case Body of <<_:32/little, Payload/binary>> -> gleam@result:'try'( raw_decode_with_limits(Payload, Limits), fun(Decoded) -> append_with_limit(Output, Decoded, Limits) end ); _ -> {error, {codec_invalid_data, <<"snappy: compressed chunk too short"/utf8>>}} end. -file("src/packkit/snappy.gleam", 175). -spec decode_chunks(bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. decode_chunks(Bytes, Output, Limits) -> case Bytes of <<>> -> {ok, Output}; <> -> case erlang:byte_size(Rest) < Length of true -> {error, {codec_invalid_data, <<"snappy: chunk payload truncated"/utf8>>}}; false -> Body@1 = case gleam_stdlib:bit_array_slice(Rest, 0, Length) of {ok, Body} -> Body; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/snappy"/utf8>>, function => <<"decode_chunks"/utf8>>, line => 189, value => _assert_fail, start => 6189, 'end' => 6243, pattern_start => 6200, pattern_end => 6208}) end, After@1 = case gleam_stdlib:bit_array_slice( Rest, Length, erlang:byte_size(Rest) - Length ) 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/snappy"/utf8>>, function => <<"decode_chunks"/utf8>>, line => 190, value => _assert_fail@1, start => 6254, 'end' => 6354, pattern_start => 6265, pattern_end => 6274}) end, gleam@result:'try'(case Chunk_type of T when T =:= 16#01 -> decode_uncompressed_chunk( Body@1, Output, Limits ); T@1 when T@1 =:= 16#00 -> decode_compressed_chunk(Body@1, Output, Limits); T@2 when T@2 =:= 16#FE -> {ok, Output}; T@3 when T@3 =:= 16#FF -> case Body@1 =:= <<16#73, 16#4E, 16#61, 16#50, 16#70, 16#59>> of true -> {ok, Output}; false -> {error, {codec_invalid_data, <<"snappy: repeated stream identifier mismatched"/utf8>>}} end; T@4 when T@4 >= 16#80 -> {ok, Output}; _ -> {error, {codec_invalid_data, <<"snappy: unsupported reserved chunk type"/utf8>>}} end, fun(New_output) -> decode_chunks(After@1, New_output, Limits) end) end; _ -> {error, {codec_invalid_data, <<"snappy: chunk header truncated"/utf8>>}} end. -file("src/packkit/snappy.gleam", 56). ?DOC(" Decode a framed Snappy stream 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 <<16#FF, 16#06, 16#00, 16#00, 16#73, 16#4E, 16#61, 16#50, 16#70, 16#59, Rest/binary>> -> decode_chunks(Rest, <<>>, Limits); _ -> {error, {codec_invalid_data, <<"snappy: missing stream identifier"/utf8>>}} end end ). -file("src/packkit/snappy.gleam", 51). ?DOC(" Decode a framed Snappy stream 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/snappy.gleam", 430). -spec apply_copy( bitstring(), bitstring(), packkit@limit:limits(), integer(), integer() ) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. apply_copy(Rest, Output, Limits, Offset, Length) -> Size = erlang:byte_size(Output), gleam@bool:guard( (Offset =< 0) orelse (Offset > Size), {error, {codec_invalid_data, <<"snappy: copy offset out of bounds"/utf8>>}}, fun() -> gleam@result:'try'(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/snappy"/utf8>>, function => <<"apply_copy"/utf8>>, line => 447, value => _assert_fail, start => 13507, 'end' => 13576, pattern_start => 13518, pattern_end => 13527}) end, append_with_limit(Output, Chunk@1, Limits); false -> copy_byte_by_byte(Output, Offset, Length, Limits) end, fun(New_output) -> decode_raw_loop(Rest, New_output, Limits) end) end ). -file("src/packkit/snappy.gleam", 379). -spec handle_copy_1(integer(), bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. handle_copy_1(Tag, Rest, Output, Limits) -> case Rest of <> -> Length = erlang:'band'(erlang:'bsr'(Tag, 2), 16#07) + 4, Offset_high = erlang:'band'(erlang:'bsr'(Tag, 5), 16#07), Offset = erlang:'bor'(erlang:'bsl'(Offset_high, 8), Offset_low), apply_copy(After_offset, Output, Limits, Offset, Length); _ -> {error, {codec_invalid_data, <<"snappy: copy-1 offset truncated"/utf8>>}} end. -file("src/packkit/snappy.gleam", 398). -spec handle_copy_2(integer(), bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. handle_copy_2(Tag, Rest, Output, Limits) -> case Rest of <> -> Length = erlang:'bsr'(Tag, 2) + 1, apply_copy(After, Output, Limits, Offset, Length); _ -> {error, {codec_invalid_data, <<"snappy: copy-2 offset truncated"/utf8>>}} end. -file("src/packkit/snappy.gleam", 414). -spec handle_copy_4(integer(), bitstring(), bitstring(), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. handle_copy_4(Tag, Rest, Output, Limits) -> case Rest of <> -> Length = erlang:'bsr'(Tag, 2) + 1, apply_copy(After, Output, Limits, Offset, Length); _ -> {error, {codec_invalid_data, <<"snappy: copy-4 offset truncated"/utf8>>}} end. -file("src/packkit/snappy.gleam", 517). -spec snappy_step( gleam@dict:dict(integer(), integer()), integer(), integer(), integer(), gleam@dict:dict(integer(), integer()), list(bitstring()) ) -> bitstring(). snappy_step(Table, Size, Pos, Last_lit_start, Hashes, Acc) -> Key = snappy_hash4( snappy_byte_at(Table, Pos), snappy_byte_at(Table, Pos + 1), snappy_byte_at(Table, Pos + 2), snappy_byte_at(Table, Pos + 3) ), case gleam_stdlib:map_get(Hashes, Key) of {ok, Prev} -> Offset = Pos - Prev, Valid = ((Offset >= 1) andalso (Offset =< 65535)) andalso snappy_bytes4_equal( Table, Prev, Pos ), case Valid of false -> snappy_compress_loop( Table, Size, Pos + 1, Last_lit_start, gleam@dict:insert(Hashes, Key, Pos), Acc ); true -> Match_len = snappy_match_length(Table, Prev, Pos, Size, 0), case Match_len < 4 of true -> snappy_compress_loop( Table, Size, Pos + 1, Last_lit_start, gleam@dict:insert(Hashes, Key, Pos), Acc ); false -> Literals = case Pos > Last_lit_start of true -> emit_literal( snappy_slice( Table, Last_lit_start, Pos - Last_lit_start, <<>> ) ); false -> <<>> end, Copy = emit_copy_for(Offset, Match_len, <<>>), Next_pos = Pos + Match_len, New_hashes = snappy_insert_hashes( Table, gleam@dict:insert(Hashes, Key, Pos), Pos + 1, Next_pos - 1, Size ), snappy_compress_loop( Table, Size, Next_pos, Next_pos, New_hashes, [Copy, Literals | Acc] ) end end; _ -> snappy_compress_loop( Table, Size, Pos + 1, Last_lit_start, gleam@dict:insert(Hashes, Key, Pos), Acc ) end. -file("src/packkit/snappy.gleam", 496). -spec snappy_compress_loop( gleam@dict:dict(integer(), integer()), integer(), integer(), integer(), gleam@dict:dict(integer(), integer()), list(bitstring()) ) -> bitstring(). snappy_compress_loop(Table, Size, Pos, Last_lit_start, Hashes, Acc) -> case (Pos + 4) > Size of true -> Lit_len = Size - Last_lit_start, Tail = case Lit_len of 0 -> <<>>; _ -> emit_literal( snappy_slice(Table, Last_lit_start, Lit_len, <<>>) ) end, gleam_stdlib:bit_array_concat(lists:reverse([Tail | Acc])); false -> snappy_step(Table, Size, Pos, Last_lit_start, Hashes, Acc) end. -file("src/packkit/snappy.gleam", 486). -spec compress_raw_body(bitstring(), integer()) -> bitstring(). compress_raw_body(Bytes, Size) -> case Size < 4 of true -> emit_literal(Bytes); false -> Table = build_snappy_byte_table(Bytes, 0, maps:new()), snappy_compress_loop(Table, Size, 0, 0, maps:new(), []) end. -file("src/packkit/snappy.gleam", 114). ?DOC( " Encode `bytes` as a Snappy raw block. Runs a greedy LZ77 match-\n" " finder (4-byte hash table, 16-bit hash) and emits literal +\n" " copy-1 / copy-2 / copy-4 sequences in the canonical block layout.\n" " Inputs of fewer than 4 bytes — where no copy can fit the 4-byte\n" " minimum match — degenerate to a single literal run.\n" ). -spec raw_encode(bitstring()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. raw_encode(Bytes) -> Length = erlang:byte_size(Bytes), Length_varint = write_varint(Length), Body = compress_raw_body(Bytes, Length), {ok, gleam_stdlib:bit_array_concat([Length_varint, Body])}. -file("src/packkit/snappy.gleam", 169). -spec encode_raw_block(bitstring(), integer()) -> bitstring(). encode_raw_block(Bytes, Size) -> Varint = write_varint(Size), Body = compress_raw_body(Bytes, Size), gleam_stdlib:bit_array_concat([Varint, Body]). -file("src/packkit/snappy.gleam", 121). -spec encode_uncompressed_chunks(bitstring(), list(bitstring())) -> bitstring(). encode_uncompressed_chunks(Remaining, Acc) -> Total = erlang:byte_size(Remaining), case Total of 0 -> gleam_stdlib:bit_array_concat(lists:reverse(Acc)); _ -> Chunk_size = case Total > 65536 of true -> 65536; 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/snappy"/utf8>>, function => <<"encode_uncompressed_chunks"/utf8>>, line => 133, value => _assert_fail, start => 4316, 'end' => 4380, pattern_start => 4327, pattern_end => 4336}) 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/snappy"/utf8>>, function => <<"encode_uncompressed_chunks"/utf8>>, line => 134, value => _assert_fail@1, start => 4387, 'end' => 4476, pattern_start => 4398, pattern_end => 4407}) end, Crc = packkit@checksum:snappy_mask(packkit@checksum:crc32c(Chunk@1)), Raw_body = encode_raw_block(Chunk@1, Chunk_size), Raw_body_size = erlang:byte_size(Raw_body), Framed = case Raw_body_size < Chunk_size of true -> Payload_size = Raw_body_size + 4, Header = <<16#00, Payload_size:24/little, Crc:32/little>>, gleam_stdlib:bit_array_concat([Header, Raw_body]); false -> Payload_size@1 = Chunk_size + 4, Header@1 = <<16#01, Payload_size@1:24/little, Crc:32/little>>, gleam_stdlib:bit_array_concat([Header@1, Chunk@1]) end, encode_uncompressed_chunks(After@1, [Framed | Acc]) end. -file("src/packkit/snappy.gleam", 45). ?DOC( " Encode `bytes` as a framed Snappy stream that stores every chunk\n" " in the uncompressed form.\n" ). -spec encode(bitstring()) -> {ok, bitstring()} | {error, packkit@error:codec_error()}. encode(Bytes) -> Chunks = encode_uncompressed_chunks(Bytes, []), {ok, gleam_stdlib:bit_array_concat( [<<16#FF, 16#06, 16#00, 16#00, 16#73, 16#4E, 16#61, 16#50, 16#70, 16#59>>, Chunks] )}.