-module(packkit@seven_z). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/packkit/seven_z.gleam"). -export([format/0, new/0, lzma/0, copy/0, deflate/0, bzip2/0, encode_with_method/2, encode/1, encode_with_password_and_method/3, encode_with_password/2, encode_with_password_and_header_encryption_and_method/3, encode_with_password_and_header_encryption/2, decode/1, decode_with_limits/2, decode_with_password/2, decode_with_password_and_limits/3]). -export_type([method/0, encryption_spec/0, folder_encoding/0, parsed_header/0, parsed_folder/0, coder_spec/0, coder_id/0, header_parser/0, header_streams/0, header_files/0, streams_parser/0, sub_streams_acc/0, aes_properties/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( " 7z archive — minimal pure-Gleam reader.\n" "\n" " The reader handles the common case produced by `7z a` on a small\n" " payload: a single packed stream wrapped in a single folder that\n" " uses one coder. Recognised single-coder ids:\n" " - LZMA2 (`0x21`)\n" " - raw LZMA (`0x03 0x01 0x01`)\n" " - Copy (`0x00`) — identity passthrough\n" " - Deflate (`0x04 0x01 0x08`) — raw DEFLATE, delegated to packkit/deflate\n" " - BZip2 (`0x04 0x02 0x02`) — full BZh stream, delegated to packkit/bzip2\n" " Multiple files packed into that folder are supported when the\n" " archive carries a `SubStreamsInfo` block — the parser reads the\n" " per-substream sizes from `kSize` (0x09), derives the final size\n" " from the folder's total, and splits the decoded stream\n" " accordingly. Multi-coder folders (BCJ filters in front of LZMA2,\n" " AES decryption in front of LZMA2), AES-256-CBC encryption with\n" " p7zip's SHA-256-based key derivation (`06 F1 07 01`), and multiple\n" " folders are supported. Header encryption (`-mhe=on`, encrypts the\n" " next-header itself) is intentionally rejected with\n" " `ArchiveNotImplemented`. AES-encrypted archives require the\n" " `decode_with_password` / `decode_with_password_and_limits` entry\n" " points. The encoder is unaffected — it still emits a single\n" " LZMA-coded folder regardless of which coders the decoder accepts.\n" ). -opaque method() :: method_lzma | method_copy | method_deflate | method_bzip2. -type encryption_spec() :: {encryption_spec, binary(), bitstring(), bitstring(), integer()}. -type folder_encoding() :: {folder_encoding, bitstring(), bitstring()}. -type parsed_header() :: {parsed_header, integer(), list(integer()), list(parsed_folder()), list(list(integer())), list(integer()), list(binary()), list(boolean()), list(boolean()), list(gleam@option:option(integer()))}. -type parsed_folder() :: {parsed_folder, list(coder_spec()), list(integer())}. -type coder_spec() :: {coder_spec, coder_id(), bitstring(), integer(), integer()}. -type coder_id() :: lzma2 | lzma | copy | deflate | b_zip2 | delta | bcj_x86 | bcj_ppc | bcj_ia64 | bcj_arm | bcj_arm_t | bcj_sparc | aes256_sha256 | bcj2. -type header_parser() :: {header_parser, list(bitstring()), header_streams(), header_files()}. -type header_streams() :: header_streams_none | {header_streams_parsed, integer(), list(integer()), list(parsed_folder()), list(list(integer())), list(integer())}. -type header_files() :: header_files_none | {header_files_parsed, list(binary()), list(boolean()), list(boolean()), list(gleam@option:option(integer()))}. -type streams_parser() :: {streams_parser, integer(), list(integer()), list(parsed_folder()), list(list(integer())), list(integer()), boolean(), boolean()}. -type sub_streams_acc() :: {sub_streams_acc, list(integer()), list(integer())}. -type aes_properties() :: {aes_properties, integer(), bitstring(), bitstring()}. -file("src/packkit/seven_z.gleam", 215). ?DOC(" 7z archive format marker.\n"). -spec format() -> packkit@archive:archive_format(). format() -> packkit@archive:seven_z(). -file("src/packkit/seven_z.gleam", 220). ?DOC(" Create an empty 7z archive value.\n"). -spec new() -> packkit@archive:archive(). new() -> packkit@archive:new(format()). -file("src/packkit/seven_z.gleam", 240). ?DOC( " Default `Method`: raw LZMA1 with the historical `7z a` defaults\n" " (lc=3 / lp=0 / pb=2, 64 KiB dictionary). Equivalent to passing\n" " `seven_z.lzma()` to `encode_with_method`.\n" ). -spec lzma() -> method(). lzma() -> method_lzma. -file("src/packkit/seven_z.gleam", 247). ?DOC( " `Method` constructor: identity (no compression). Equivalent to\n" " `7z a -m0=Copy`. The packed bytes stored in the folder are the\n" " concatenated entry bodies verbatim.\n" ). -spec copy() -> method(). copy() -> method_copy. -file("src/packkit/seven_z.gleam", 254). ?DOC( " `Method` constructor: raw DEFLATE (no zlib / gzip wrapper). The\n" " concatenated entry bodies go through `packkit/deflate.encode`.\n" " Equivalent to `7z a -m0=Deflate`.\n" ). -spec deflate() -> method(). deflate() -> method_deflate. -file("src/packkit/seven_z.gleam", 261). ?DOC( " `Method` constructor: full bzip2 stream (with `BZh` magic and CRCs).\n" " The concatenated entry bodies go through `packkit/bzip2.encode`.\n" " Equivalent to `7z a -m0=BZip2`.\n" ). -spec bzip2() -> method(). bzip2() -> method_bzip2. -file("src/packkit/seven_z.gleam", 644). -spec validate_entries_for_encode(list(packkit@entry:entry())) -> {ok, nil} | {error, packkit@error:archive_error()}. validate_entries_for_encode(Entries) -> case Entries of [] -> {ok, nil}; [Head | Rest] -> case packkit@entry:kind(Head) of file -> validate_entries_for_encode(Rest); _ -> {error, {archive_entry_rejected, packkit@entry:to_string(packkit@entry:path(Head)), <<"7z encoder currently supports File entries only"/utf8>>}} end end. -file("src/packkit/seven_z.gleam", 901). -spec drop_last(list(MXD), list(MXD)) -> list(MXD). drop_last(Values, Acc) -> case Values of [] -> lists:reverse(Acc); [_] -> lists:reverse(Acc); [Head | Rest] -> drop_last(Rest, [Head | Acc]) end. -file("src/packkit/seven_z.gleam", 951). -spec pack_bool_bits_loop( list(boolean()), integer(), integer(), integer(), bitstring() ) -> bitstring(). pack_bool_bits_loop(Bits, Remaining, Bit_index, Current_byte, Acc) -> case Remaining of 0 -> case Bit_index of 0 -> Acc; _ -> gleam_stdlib:bit_array_concat([Acc, <>]) end; _ -> {Head, Tail} = case Bits of [B | Rest] -> {B, Rest}; [] -> {false, []} end, Bit_value = case Head of true -> 1; false -> 0 end, Updated_byte = erlang:'bor'( Current_byte, erlang:'bsl'(Bit_value, 7 - Bit_index) ), case Bit_index =:= 7 of true -> pack_bool_bits_loop( Tail, Remaining - 1, 0, 0, gleam_stdlib:bit_array_concat([Acc, <>]) ); false -> pack_bool_bits_loop( Tail, Remaining - 1, Bit_index + 1, Updated_byte, Acc ) end end. -file("src/packkit/seven_z.gleam", 947). -spec pack_bool_bits(list(boolean()), integer()) -> bitstring(). pack_bool_bits(Bits, Count) -> pack_bool_bits_loop(Bits, Count, 0, 0, <<>>). -file("src/packkit/seven_z.gleam", 1029). -spec encode_utf16_le_codepoints(list(integer()), bitstring(), binary()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_utf16_le_codepoints(Codepoints, Acc, Full_name) -> case Codepoints of [] -> {ok, Acc}; [Cp | Rest] -> Value = gleam_stdlib:identity(Cp), case Value < 16#10000 of true -> Low = erlang:'band'(Value, 16#FF), High = erlang:'bsr'(Value, 8), encode_utf16_le_codepoints( Rest, <>, Full_name ); false -> {error, {archive_entry_rejected, Full_name, <<"7z encoder requires BMP-only file names (no UTF-16 surrogate pairs yet)"/utf8>>}} end end. -file("src/packkit/seven_z.gleam", 1022). -spec encode_utf16_le_name(binary()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_utf16_le_name(Name) -> Codepoints = gleam@string:to_utf_codepoints(Name), gleam@result:'try'( encode_utf16_le_codepoints(Codepoints, <<>>, Name), fun(Body) -> {ok, <>} end ). -file("src/packkit/seven_z.gleam", 1009). -spec encode_names_loop(list(binary()), bitstring()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_names_loop(Names, Acc) -> case Names of [] -> {ok, Acc}; [Name | Rest] -> gleam@result:'try'( encode_utf16_le_name(Name), fun(Encoded) -> encode_names_loop( Rest, gleam_stdlib:bit_array_concat([Acc, Encoded]) ) end ) end. -file("src/packkit/seven_z.gleam", 1000). -spec encode_names_block(list(binary())) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_names_block(Names) -> gleam@result:'try'( encode_names_loop(Names, <<>>), fun(Bodies) -> {ok, <<16#00, Bodies/bitstring>>} end ). -file("src/packkit/seven_z.gleam", 1075). -spec encode_le_bytes(integer(), integer(), bitstring()) -> bitstring(). encode_le_bytes(Value, Count, Acc) -> case Count of 0 -> Acc; _ -> Byte = Value - ((Value div 256) * 256), Shifted = Value div 256, encode_le_bytes(Shifted, Count - 1, <>) end. -file("src/packkit/seven_z.gleam", 1086). -spec int_pow(integer(), integer()) -> integer(). int_pow(Base, Exp) -> case Exp of 0 -> 1; _ -> Base * int_pow(Base, Exp - 1) end. -file("src/packkit/seven_z.gleam", 1058). ?DOC( " 7z-style 1..5 byte varint. The first byte's leading 1-bits encode\n" " the total length; the trailing bytes carry the lower bytes of the\n" " value little-endian. Cap is 2^35 - 1 which comfortably covers\n" " every size field the encoder will produce in practice.\n" ). -spec write_varint(integer()) -> bitstring(). write_varint(Value) -> {Num_bytes, Header_top} = case Value of N when N < 16#80 -> {1, 16#00}; N@1 when N@1 < 16#4000 -> {2, 16#80}; N@2 when N@2 < 16#200000 -> {3, 16#C0}; N@3 when N@3 < 16#10000000 -> {4, 16#E0}; _ -> {5, 16#F0} end, Trailers = Num_bytes - 1, Divisor = int_pow(256, Trailers), High_value = case Divisor of 0 -> 0; Gleam@denominator -> Value div Gleam@denominator end, Low_value = Value - (High_value * Divisor), First_byte = erlang:'bor'(Header_top, High_value), Trailer_bytes = encode_le_bytes(Low_value, Trailers, <<>>), <>. -file("src/packkit/seven_z.gleam", 1237). -spec parse_signature_header(bitstring()) -> {ok, {integer(), integer(), integer()}} | {error, packkit@error:archive_error()}. parse_signature_header(Bytes) -> case Bytes of <<16#37, 16#7A, 16#BC, 16#AF, 16#27, 16#1C, _, _, _:4/binary, Next_offset_lo:32/little-unsigned, Next_offset_hi:32/little-unsigned, Next_size_lo:32/little-unsigned, Next_size_hi:32/little-unsigned, Next_crc:32/little-unsigned, _/binary>> -> Next_offset = begin _pipe = erlang:'bsl'(Next_offset_hi, 32), erlang:'bor'(_pipe, Next_offset_lo) end, Next_size = begin _pipe@1 = erlang:'bsl'(Next_size_hi, 32), erlang:'bor'(_pipe@1, Next_size_lo) end, {ok, {Next_offset, Next_size, Next_crc}}; _ -> {error, {archive_invalid, <<"invalid 7z signature header"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 1491). -spec finalize_parsed_header(header_parser()) -> {ok, parsed_header()} | {error, packkit@error:archive_error()}. finalize_parsed_header(Parser) -> case {erlang:element(3, Parser), erlang:element(4, Parser)} of {{header_streams_parsed, Pack_pos, Pack_sizes, Folders, Folder_unpack_sizes, Sub}, {header_files_parsed, Names, Empty_streams, Empty_files, Mtimes_unix}} -> {ok, {parsed_header, Pack_pos, Pack_sizes, Folders, Folder_unpack_sizes, Sub, Names, Empty_streams, Empty_files, Mtimes_unix}}; {{header_streams_parsed, Pack_pos@1, Pack_sizes@1, Folders@1, Folder_unpack_sizes@1, Sub@1}, header_files_none} -> {ok, {parsed_header, Pack_pos@1, Pack_sizes@1, Folders@1, Folder_unpack_sizes@1, Sub@1, [], [], [], []}}; {_, _} -> {error, {archive_invalid, <<"7z header missing MainStreamsInfo"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 1888). -spec get_additional_stream(list(bitstring()), integer()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. get_additional_stream(Streams, Index) -> case {Streams, Index} of {[Head | _], 0} -> {ok, Head}; {[_ | Rest], _} when Index > 0 -> get_additional_stream(Rest, Index - 1); {_, _} -> {error, {archive_invalid, <<<<<<<<"7z external DataIndex "/utf8, (erlang:integer_to_binary(Index))/binary>>/binary, " out of bounds (AdditionalStreamsInfo holds "/utf8>>/binary, (erlang:integer_to_binary(erlang:length(Streams)))/binary>>/binary, " stream(s))"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 1923). -spec split_unpack_sizes_by_folder( list(integer()), list(parsed_folder()), list(list(integer())) ) -> list(list(integer())). split_unpack_sizes_by_folder(Flat, Folders, Acc) -> case Folders of [] -> lists:reverse(Acc); [Folder | Rest] -> Count = erlang:length(erlang:element(2, Folder)), Group = gleam@list:take(Flat, Count), Leftover = gleam@list:drop(Flat, Count), split_unpack_sizes_by_folder(Leftover, Rest, [Group | Acc]) end. -file("src/packkit/seven_z.gleam", 2011). -spec sum_coder_in_streams(list(coder_spec()), integer()) -> integer(). sum_coder_in_streams(Coders, Acc) -> case Coders of [] -> Acc; [Head | Rest] -> sum_coder_in_streams(Rest, Acc + erlang:element(4, Head)) end. -file("src/packkit/seven_z.gleam", 2018). -spec sum_coder_out_streams(list(coder_spec()), integer()) -> integer(). sum_coder_out_streams(Coders, Acc) -> case Coders of [] -> Acc; [Head | Rest] -> sum_coder_out_streams(Rest, Acc + erlang:element(5, Head)) end. -file("src/packkit/seven_z.gleam", 2229). -spec describe_bit_array_hex(bitstring(), binary()) -> binary(). describe_bit_array_hex(Bytes, Acc) -> case Bytes of <> -> describe_bit_array_hex( Rest, <> ); _ -> Acc end. -file("src/packkit/seven_z.gleam", 2436). -spec count_true(list(boolean())) -> integer(). count_true(Bits) -> case Bits of [] -> 0; [true | Rest] -> 1 + count_true(Rest); [false | Rest@1] -> count_true(Rest@1) end. -file("src/packkit/seven_z.gleam", 2558). -spec build_dummy_names(integer(), integer(), list(binary())) -> list(binary()). build_dummy_names(Count, Index, Acc) -> case Index >= Count of true -> lists:reverse(Acc); false -> build_dummy_names( Count, Index + 1, [<<"file"/utf8, (erlang:integer_to_binary(Index))/binary>> | Acc] ) end. -file("src/packkit/seven_z.gleam", 2554). -spec dummy_names(integer()) -> list(binary()). dummy_names(Count) -> build_dummy_names(Count, 0, []). -file("src/packkit/seven_z.gleam", 2630). -spec encode_utf8_code(integer(), bitstring()) -> bitstring(). encode_utf8_code(Code, Acc) -> case Code of C when C < 16#80 -> <>; C@1 when C@1 < 16#800 -> B1 = 16#C0 + erlang:'bsr'(C@1, 6), B2 = 16#80 + erlang:'band'(C@1, 16#3F), <>; C@2 -> B1@1 = 16#E0 + erlang:'bsr'(C@2, 12), B2@1 = 16#80 + erlang:'band'(erlang:'bsr'(C@2, 6), 16#3F), B3 = 16#80 + erlang:'band'(C@2, 16#3F), <> end. -file("src/packkit/seven_z.gleam", 2623). -spec codepoints_to_bit_array(list(integer()), bitstring()) -> bitstring(). codepoints_to_bit_array(Codes, Acc) -> case Codes of [] -> Acc; [Code | Rest] -> codepoints_to_bit_array(Rest, encode_utf8_code(Code, Acc)) end. -file("src/packkit/seven_z.gleam", 2594). -spec decode_utf16_names( bitstring(), integer(), list(integer()), list(binary()) ) -> {ok, list(binary())} | {error, packkit@error:archive_error()}. decode_utf16_names(Bytes, Remaining, Current, Acc) -> case Remaining of 0 -> {ok, lists:reverse(Acc)}; _ -> case Bytes of <> -> Code = erlang:'bor'(erlang:'bsl'(Hi, 8), Lo), case Code of 0 -> Name@1 = case gleam@bit_array:to_string( codepoints_to_bit_array( lists:reverse(Current), <<>> ) ) of {ok, Name} -> Name; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/seven_z"/utf8>>, function => <<"decode_utf16_names"/utf8>>, line => 2608, value => _assert_fail, start => 83799, 'end' => 83947, pattern_start => 83810, pattern_end => 83818}) end, decode_utf16_names( Rest, Remaining - 1, [], [Name@1 | Acc] ); _ -> decode_utf16_names( Rest, Remaining, [Code | Current], Acc ) end; _ -> {error, {archive_invalid, <<"truncated 7z UTF-16 file name"/utf8>>}} end end. -file("src/packkit/seven_z.gleam", 2665). -spec unpack_bits(integer(), integer(), list(boolean())) -> list(boolean()). unpack_bits(Byte, Remaining, Acc) -> case Remaining of 0 -> lists:reverse(Acc); _ -> Bit = erlang:'band'(erlang:'bsr'(Byte, Remaining - 1), 1), unpack_bits(Byte, Remaining - 1, [Bit =:= 1 | Acc]) end. -file("src/packkit/seven_z.gleam", 2712). -spec drop_bytes(bitstring(), integer(), binary()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. drop_bytes(Bytes, Count, Label) -> case gleam_stdlib:bit_array_slice( Bytes, Count, erlang:byte_size(Bytes) - Count ) of {ok, Rest} -> {ok, Rest}; {error, _} -> {error, {archive_invalid, <<"truncated "/utf8, Label/binary>>}} end. -file("src/packkit/seven_z.gleam", 2690). -spec skip_crc_block(bitstring(), integer()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. skip_crc_block(Bytes, Count) -> case Bytes of <> -> case All_defined of 1 -> drop_bytes(Rest, Count * 4, <<"7z CRC table"/utf8>>); _ -> Byte_count = (Count + 7) div 8, gleam@result:'try'( drop_bytes( Rest, Byte_count, <<"7z CRC flag bits"/utf8>> ), fun(After_flags) -> drop_bytes( After_flags, Count * 4, <<"7z CRC values"/utf8>> ) end ) end; _ -> {error, {archive_invalid, <<"truncated 7z CRC block"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 2827). -spec repeat_one_per_folder(integer(), list(integer())) -> list(integer()). repeat_one_per_folder(N, Acc) -> case N of 0 -> Acc; _ -> repeat_one_per_folder(N - 1, [1 | Acc]) end. -file("src/packkit/seven_z.gleam", 2867). -spec list_take(list(NEE), integer(), list(NEE)) -> {list(NEE), list(NEE)}. list_take(Values, N, Acc) -> case {Values, N} of {_, 0} -> {lists:reverse(Acc), Values}; {[], _} -> {lists:reverse(Acc), []}; {[Head | Rest], _} -> list_take(Rest, N - 1, [Head | Acc]) end. -file("src/packkit/seven_z.gleam", 2875). -spec sum_list(list(integer()), integer()) -> integer(). sum_list(Values, Acc) -> case Values of [] -> Acc; [Head | Rest] -> sum_list(Rest, Acc + Head) end. -file("src/packkit/seven_z.gleam", 2834). -spec derive_substream_sizes( list(integer()), list(integer()), list(integer()), list(integer()) ) -> list(integer()). derive_substream_sizes(Per_folder, Folder_unpack_sizes, Remaining_explicit, Acc) -> case {Per_folder, Folder_unpack_sizes} of {[], _} -> lists:reverse(Acc); {_, []} -> lists:reverse(Acc); {[Count | Rest_counts], [Folder_total | Rest_folder_totals]} -> Explicit_for_folder = case Count of 0 -> 0; _ -> Count - 1 end, {Explicit, Remaining} = list_take( Remaining_explicit, Explicit_for_folder, [] ), Explicit_sum = sum_list(Explicit, 0), Derived = Folder_total - Explicit_sum, Folder_sizes = case Count of 0 -> []; _ -> lists:append(Explicit, [Derived]) end, derive_substream_sizes( Rest_counts, Rest_folder_totals, Remaining, lists:append(lists:reverse(Folder_sizes), Acc) ) end. -file("src/packkit/seven_z.gleam", 2988). -spec folder_packed_stream_count(parsed_folder()) -> integer(). folder_packed_stream_count(Folder) -> case erlang:element(3, Folder) of [] -> 1; List_value -> erlang:length(List_value) end. -file("src/packkit/seven_z.gleam", 3015). -spec enforce_max_output(list(integer()), packkit@limit:limits()) -> {ok, nil} | {error, packkit@error:archive_error()}. enforce_max_output(Unpack_sizes, Limits) -> Total = sum_list(Unpack_sizes, 0), case Total > packkit@limit:max_output_bytes(Limits) of true -> {error, {archive_limit_exceeded, <<"max_output_bytes"/utf8>>, Total}}; false -> {ok, nil} end. -file("src/packkit/seven_z.gleam", 3111). -spec bcj2_error_to_archive(packkit@internal@bcj2:bcj2_error()) -> packkit@error:archive_error(). bcj2_error_to_archive(Err) -> case Err of range_coder_header_invalid -> {archive_invalid, <<"7z BCJ2: range-coder header invalid (first 5 bytes)"/utf8>>}; {stream_exhausted, Name} -> {archive_invalid, <<<<"7z BCJ2: stream \""/utf8, Name/binary>>/binary, "\" exhausted mid-decode"/utf8>>}; {output_size_mismatch, Declared, Actual} -> {archive_invalid, <<<<<<"7z BCJ2: decoded "/utf8, (erlang:integer_to_binary(Actual))/binary>>/binary, " bytes, expected "/utf8>>/binary, (erlang:integer_to_binary(Declared))/binary>>} end. -file("src/packkit/seven_z.gleam", 3200). -spec string_inspect(any()) -> binary(). string_inspect(Value) -> gleam@string:inspect(Value). -file("src/packkit/seven_z.gleam", 3179). -spec maybe_wrap_aes_chain_error(packkit@error:archive_error(), coder_id()) -> packkit@error:archive_error(). maybe_wrap_aes_chain_error(Err, Head_id) -> case Head_id =:= aes256_sha256 of false -> Err; true -> Original = case Err of {archive_invalid, Message} -> Message; {archive_not_implemented, Feature} -> Feature; Other -> string_inspect(Other) end, {archive_invalid, <<<<"7z AES decrypt produced invalid plaintext for the "/utf8, "downstream coder (wrong password or corrupt archive): "/utf8>>/binary, Original/binary>>} end. -file("src/packkit/seven_z.gleam", 3285). -spec bit_array_to_byte_list_seven_z(bitstring(), list(integer())) -> list(integer()). bit_array_to_byte_list_seven_z(Bytes, Acc) -> case Bytes of <> -> bit_array_to_byte_list_seven_z(Rest, [B | Acc]); _ -> lists:reverse(Acc) end. -file("src/packkit/seven_z.gleam", 3292). -spec byte_list_to_bit_array_seven_z(list(integer()), bitstring()) -> bitstring(). byte_list_to_bit_array_seven_z(Bytes, Acc) -> case Bytes of [] -> Acc; [B | Rest] -> byte_list_to_bit_array_seven_z(Rest, <>) end. -file("src/packkit/seven_z.gleam", 3324). -spec nth_back(list(integer()), integer()) -> integer(). nth_back(Values, Steps) -> case {Values, Steps} of {[Head | _], 0} -> Head; {[_ | Tail], _} -> nth_back(Tail, Steps - 1); {[], _} -> 0 end. -file("src/packkit/seven_z.gleam", 3299). -spec delta_decode_seven_z_loop( list(integer()), integer(), list(integer()), integer() ) -> list(integer()). delta_decode_seven_z_loop(Input, Distance, Output, Index) -> case Input of [] -> lists:reverse(Output); [B | Rest] -> case Index < Distance of true -> delta_decode_seven_z_loop( Rest, Distance, [B | Output], Index + 1 ); false -> Predecessor = nth_back(Output, Distance - 1), Sum = erlang:'band'(B + Predecessor, 16#FF), delta_decode_seven_z_loop( Rest, Distance, [Sum | Output], Index + 1 ) end end. -file("src/packkit/seven_z.gleam", 3279). -spec delta_decode_seven_z(bitstring(), integer()) -> bitstring(). delta_decode_seven_z(Bytes, Distance) -> Byte_list = bit_array_to_byte_list_seven_z(Bytes, []), Decoded = delta_decode_seven_z_loop(Byte_list, Distance, [], 0), byte_list_to_bit_array_seven_z(Decoded, <<>>). -file("src/packkit/seven_z.gleam", 3344). -spec flag_to_int(boolean()) -> integer(). flag_to_int(Flag) -> case Flag of true -> 1; false -> 0 end. -file("src/packkit/seven_z.gleam", 3506). -spec aes_kdf_loop( packkit@checksum:sha256_state(), bitstring(), bitstring(), integer(), integer() ) -> packkit@checksum:sha256_state(). aes_kdf_loop(State, Salt, Password_utf16le, Counter, Rounds) -> case gleam@int:compare(Counter, Rounds) of lt -> Counter_bytes = <>, Next_state = begin _pipe = State, _pipe@1 = packkit@checksum:sha256_update(_pipe, Salt), _pipe@2 = packkit@checksum:sha256_update( _pipe@1, Password_utf16le ), packkit@checksum:sha256_update(_pipe@2, Counter_bytes) end, aes_kdf_loop( Next_state, Salt, Password_utf16le, Counter + 1, Rounds ); _ -> State end. -file("src/packkit/seven_z.gleam", 3484). -spec derive_aes_key_hashed(bitstring(), bitstring(), integer()) -> bitstring(). derive_aes_key_hashed(Salt, Password_utf16le, Num_cycles_power) -> Rounds = erlang:'bsl'(1, Num_cycles_power), Initial = packkit@checksum:sha256_init(), Final_state = aes_kdf_loop(Initial, Salt, Password_utf16le, 0, Rounds), packkit@checksum:sha256_finalize(Final_state). -file("src/packkit/seven_z.gleam", 3556). -spec utf16le_append_codepoint(integer(), bitstring()) -> bitstring(). utf16le_append_codepoint(Scalar, Acc) -> gleam@bool:guard( Scalar < 16#10000, <>, fun() -> Adjusted = Scalar - 16#10000, High = 16#D800 + erlang:'bsr'(Adjusted, 10), Low = 16#DC00 + erlang:'band'(Adjusted, 16#3FF), <> end ). -file("src/packkit/seven_z.gleam", 3549). -spec utf16le_append_grapheme(binary(), bitstring()) -> bitstring(). utf16le_append_grapheme(Grapheme, Acc) -> _pipe = gleam@string:to_utf_codepoints(Grapheme), gleam@list:fold( _pipe, Acc, fun(Running, Codepoint) -> utf16le_append_codepoint(gleam_stdlib:identity(Codepoint), Running) end ). -file("src/packkit/seven_z.gleam", 3538). -spec utf16le_encode(binary(), bitstring()) -> bitstring(). utf16le_encode(Source, Acc) -> case gleam_stdlib:string_pop_grapheme(Source) of {ok, {Grapheme, Rest}} -> utf16le_encode(Rest, utf16le_append_grapheme(Grapheme, Acc)); _ -> Acc end. -file("src/packkit/seven_z.gleam", 3642). -spec iv_or_zero(bitstring()) -> bitstring(). iv_or_zero(Iv) -> Iv_size = erlang:byte_size(Iv), case Iv_size of 16 -> Iv; Size when Size < 16 -> <>; _ -> _pipe = gleam_stdlib:bit_array_slice(Iv, 0, 16), gleam@result:unwrap(_pipe, <<0:128>>) end. -file("src/packkit/seven_z.gleam", 3683). -spec xor_bit_arrays_loop(bitstring(), bitstring(), bitstring()) -> bitstring(). xor_bit_arrays_loop(Left, Right, Acc) -> case {Left, Right} of {<>, <>} -> xor_bit_arrays_loop( Left_rest, Right_rest, <> ); {_, _} -> Acc end. -file("src/packkit/seven_z.gleam", 3679). -spec xor_bit_arrays(bitstring(), bitstring()) -> bitstring(). xor_bit_arrays(Left, Right) -> xor_bit_arrays_loop(Left, Right, <<>>). -file("src/packkit/seven_z.gleam", 3593). -spec aes_cbc_encrypt_loop( bitstring(), packkit@internal@aes:expanded_key(), bitstring(), bitstring() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. aes_cbc_encrypt_loop(Plaintext, Key, Prev_block, Acc) -> case Plaintext of <<>> -> {ok, Acc}; <> -> Xored = xor_bit_arrays(Block, Prev_block), gleam@result:'try'( begin _pipe = packkit@internal@aes:encrypt_block(Key, Xored), gleam@result:replace_error( _pipe, {archive_invalid, <<"7z AES encrypt_block rejected a 16-byte plaintext block"/utf8>>} ) end, fun(Ciphertext_block) -> aes_cbc_encrypt_loop( Rest, Key, Ciphertext_block, <> ) end ); _ -> {error, {archive_invalid, <<"7z AES plaintext tail shorter than 16 bytes after padding"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 3654). -spec aes_cbc_decrypt_loop( bitstring(), packkit@internal@aes:expanded_key(), bitstring(), bitstring() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. aes_cbc_decrypt_loop(Ciphertext, Key, Prev_block, Acc) -> case Ciphertext of <<>> -> {ok, Acc}; <> -> gleam@result:'try'( begin _pipe = packkit@internal@aes:decrypt_block(Key, Block), gleam@result:replace_error( _pipe, {archive_invalid, <<"7z AES decrypt_block rejected a 16-byte ciphertext block"/utf8>>} ) end, fun(Decrypted) -> Plaintext_block = xor_bit_arrays(Decrypted, Prev_block), aes_cbc_decrypt_loop( Rest, Key, Block, <> ) end ); _ -> {error, {archive_invalid, <<"7z AES ciphertext tail shorter than 16 bytes"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 3698). -spec folder_unpack_total(list(integer())) -> integer(). folder_unpack_total(Unpack_sizes) -> case Unpack_sizes of [Size | _] -> Size; [] -> 0 end. -file("src/packkit/seven_z.gleam", 3711). -spec decode_copy_coder(bitstring(), list(integer())) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_copy_coder(Packed, Unpack_sizes) -> Target = folder_unpack_total(Unpack_sizes), Packed_size = erlang:byte_size(Packed), case Packed_size >= Target of true -> case gleam_stdlib:bit_array_slice(Packed, 0, Target) of {ok, B} -> {ok, B}; {error, _} -> {error, {archive_invalid, <<"7z Copy coder slice failed"/utf8>>}} end; false -> {error, {archive_invalid, <<<<<<"7z Copy coder packed size "/utf8, (erlang:integer_to_binary(Packed_size))/binary>>/binary, " < declared unpack size "/utf8>>/binary, (erlang:integer_to_binary(Target))/binary>>}} end. -file("src/packkit/seven_z.gleam", 3770). -spec verify_unpack_size(bitstring(), integer(), binary()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. verify_unpack_size(Plain, Expected, Coder_name) -> Actual = erlang:byte_size(Plain), case Actual =:= Expected of true -> {ok, Plain}; false -> {error, {archive_invalid, <<<<<<<<<<"7z "/utf8, Coder_name/binary>>/binary, " unpacked "/utf8>>/binary, (erlang:integer_to_binary(Actual))/binary>>/binary, " bytes but folder declared "/utf8>>/binary, (erlang:integer_to_binary(Expected))/binary>>}} end. -file("src/packkit/seven_z.gleam", 3247). -spec decode_bcj_coder( bitstring(), list(integer()), fun((bitstring(), integer()) -> bitstring()), binary() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_bcj_coder(Packed, Unpack_sizes, Decoder, Arch_name) -> Target = folder_unpack_total(Unpack_sizes), Decoded = Decoder(Packed, 0), verify_unpack_size(Decoded, Target, <<"BCJ "/utf8, Arch_name/binary>>). -file("src/packkit/seven_z.gleam", 3265). -spec decode_delta_coder(bitstring(), bitstring(), list(integer())) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_delta_coder(Packed, Properties, Unpack_sizes) -> Target = folder_unpack_total(Unpack_sizes), Distance = case Properties of <> -> D + 1; _ -> 1 end, Decoded = delta_decode_seven_z(Packed, Distance), verify_unpack_size(Decoded, Target, <<"Delta"/utf8>>). -file("src/packkit/seven_z.gleam", 3948). -spec codec_to_archive(packkit@error:codec_error()) -> packkit@error:archive_error(). codec_to_archive(Err) -> case Err of {codec_not_implemented, Feature} -> {archive_not_implemented, Feature}; {codec_invalid_data, Message} -> {archive_invalid, Message}; {codec_limit_exceeded, Limit, Actual} -> {archive_limit_exceeded, Limit, Actual}; {codec_dictionary_required, Name} -> {archive_invalid, <<<<"codec "/utf8, Name/binary>>/binary, " requires a preset dictionary"/utf8>>}; {codec_dictionary_mismatch, Name@1} -> {archive_invalid, <<<<"codec "/utf8, Name@1/binary>>/binary, " preset dictionary DICT_ID mismatch"/utf8>>}; {codec_option_unsupported, Option, Codec_name} -> {archive_invalid, <<<<<<"codec "/utf8, Codec_name/binary>>/binary, " does not support the requested option: "/utf8>>/binary, Option/binary>>} end. -file("src/packkit/seven_z.gleam", 3739). -spec decode_deflate_coder(bitstring(), list(integer()), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_deflate_coder(Packed, Unpack_sizes, Limits) -> Target = folder_unpack_total(Unpack_sizes), case packkit@deflate:decode_with_limits(Packed, Limits) of {ok, Plain} -> verify_unpack_size(Plain, Target, <<"Deflate"/utf8>>); {error, Err} -> {error, codec_to_archive(Err)} end. -file("src/packkit/seven_z.gleam", 3753). -spec decode_bzip2_coder(bitstring(), list(integer()), packkit@limit:limits()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_bzip2_coder(Packed, Unpack_sizes, Limits) -> Target = folder_unpack_total(Unpack_sizes), case packkit@bzip2:decode_with_limits(Packed, Limits) of {ok, Plain} -> verify_unpack_size(Plain, Target, <<"BZip2"/utf8>>); {error, Err} -> {error, codec_to_archive(Err)} end. -file("src/packkit/seven_z.gleam", 3803). -spec decode_lzma2_stream(bitstring(), bitstring(), integer()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_lzma2_stream(Payload, Output, Target) -> case Payload of <<16#00, _/binary>> -> {ok, Output}; <> when (Control =:= 16#01) orelse (Control =:= 16#02) -> case Payload of <<_, Sh, Sl, Rest/binary>> -> Size = erlang:'bor'(erlang:'bsl'(Sh, 8), Sl) + 1, case gleam_stdlib:bit_array_slice(Rest, 0, Size) of {ok, Chunk} -> case gleam_stdlib:bit_array_slice( Rest, Size, erlang:byte_size(Rest) - Size ) of {ok, After} -> decode_lzma2_stream( After, gleam_stdlib:bit_array_concat( [Output, Chunk] ), Target ); {error, _} -> {error, {archive_invalid, <<"truncated 7z LZMA2 uncompressed chunk"/utf8>>}} end; {error, _} -> {error, {archive_invalid, <<"truncated 7z LZMA2 chunk body"/utf8>>}} end; _ -> {error, {archive_invalid, <<"truncated 7z LZMA2 chunk header"/utf8>>}} end; <> when Control@1 >= 16#80 -> _ = Target, Usize = erlang:'bor'( erlang:'bsl'(erlang:'band'(Control@1, 16#1F), 16), erlang:'bor'(erlang:'bsl'(Usize_high, 8), Usize_low) ) + 1, Csize = erlang:'bor'(erlang:'bsl'(Csize_high, 8), Csize_low) + 1, case Control@1 >= 16#C0 of true -> case Rest@1 of <> -> case packkit@internal@lzma:properties_of_byte( Props_byte ) of {ok, Parsed_props} -> case gleam_stdlib:bit_array_slice( Rest_after_props, 0, Csize ) of {ok, Lzma_data} -> case gleam_stdlib:bit_array_slice( Rest_after_props, Csize, erlang:byte_size( Rest_after_props ) - Csize ) of {ok, After_chunk} -> case packkit@internal@lzma:new( Lzma_data, Parsed_props, 32000000 ) of {ok, Dec} -> case packkit@internal@lzma:decode_into( Dec, Usize ) of {ok, {Decoded, _}} -> decode_lzma2_stream( After_chunk, gleam_stdlib:bit_array_concat( [Output, Decoded] ), Target ); {error, Err} -> {error, codec_to_archive( Err )} end; {error, Err@1} -> {error, codec_to_archive( Err@1 )} end; {error, _} -> {error, {archive_invalid, <<"truncated 7z LZMA chunk"/utf8>>}} end; {error, _} -> {error, {archive_invalid, <<"truncated 7z LZMA chunk body"/utf8>>}} end; {error, Err@2} -> {error, codec_to_archive(Err@2)} end; _ -> {error, {archive_invalid, <<"truncated 7z LZMA properties byte"/utf8>>}} end; false -> {error, {archive_not_implemented, <<"7z LZMA2 chunks without inline properties"/utf8>>}} end; _ -> {error, {archive_invalid, <<"invalid 7z LZMA2 control byte"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 3790). -spec decode_lzma2_payload(bitstring(), bitstring(), list(integer())) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_lzma2_payload(Packed, _, Unpack_sizes) -> Total = case Unpack_sizes of [Size | _] -> Size; [] -> 0 end, gleam@result:'try'( decode_lzma2_stream(Packed, <<>>, Total), fun(Bytes) -> {ok, Bytes} end ). -file("src/packkit/seven_z.gleam", 3912). -spec decode_raw_lzma(bitstring(), bitstring(), list(integer())) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_raw_lzma(Packed, Props, Unpack_sizes) -> Target = case Unpack_sizes of [Size | _] -> Size; [] -> 0 end, case Props of <> -> case packkit@internal@lzma:properties_of_byte(Props_byte) of {ok, Parsed_props} -> case packkit@internal@lzma:new( Packed, Parsed_props, 32000000 ) of {ok, Dec} -> case packkit@internal@lzma:decode_into(Dec, Target) of {ok, {Decoded, _}} -> {ok, Decoded}; {error, Err} -> {error, codec_to_archive(Err)} end; {error, Err@1} -> {error, codec_to_archive(Err@1)} end; {error, Err@2} -> {error, codec_to_archive(Err@2)} end; _ -> {error, {archive_invalid, <<"7z raw LZMA coder missing properties"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 4016). -spec last_of_list(list(integer())) -> integer(). last_of_list(Values) -> case Values of [Last] -> Last; [_ | Rest] -> last_of_list(Rest); [] -> 0 end. -file("src/packkit/seven_z.gleam", 4010). -spec derive_substream_sizes_from_folders(list(list(integer()))) -> list(integer()). derive_substream_sizes_from_folders(Folder_unpack_sizes) -> gleam@list:map(Folder_unpack_sizes, fun last_of_list/1). -file("src/packkit/seven_z.gleam", 4143). -spec apply_mtime(packkit@entry:entry(), gleam@option:option(integer())) -> packkit@entry:entry(). apply_mtime(E, Mtime) -> case Mtime of {some, Unix_seconds} when Unix_seconds > 0 -> packkit@entry:with_modified_at(E, Unix_seconds); _ -> E end. -file("src/packkit/seven_z.gleam", 4151). -spec add_file( binary(), bitstring(), gleam@option:option(integer()), list(packkit@entry:entry()), packkit@limit:limits() ) -> {ok, list(packkit@entry:entry())} | {error, packkit@error:archive_error()}. add_file(Name, Body, Mtime, Acc, Limits) -> case packkit@entry:file_checked(Name, Body) of {ok, E} -> Depth = packkit@entry:depth(packkit@entry:path(E)), case Depth > packkit@limit:max_entry_depth(Limits) of true -> {error, {archive_limit_exceeded, <<"max_entry_depth"/utf8>>, Depth}}; false -> {ok, [apply_mtime(E, Mtime) | Acc]} end; {error, _} -> {error, {archive_invalid, <<"7z file name failed path validation: "/utf8, Name/binary>>}} end. -file("src/packkit/seven_z.gleam", 4177). -spec add_directory( binary(), gleam@option:option(integer()), list(packkit@entry:entry()), packkit@limit:limits() ) -> {ok, list(packkit@entry:entry())} | {error, packkit@error:archive_error()}. add_directory(Name, Mtime, Acc, Limits) -> case packkit@entry:directory_checked(Name) of {ok, E} -> Depth = packkit@entry:depth(packkit@entry:path(E)), case Depth > packkit@limit:max_entry_depth(Limits) of true -> {error, {archive_limit_exceeded, <<"max_entry_depth"/utf8>>, Depth}}; false -> {ok, [apply_mtime(E, Mtime) | Acc]} end; {error, _} -> {error, {archive_invalid, <<"7z directory name failed path validation: "/utf8, Name/binary>>}} end. -file("src/packkit/seven_z.gleam", 4204). -spec slice_required(bitstring(), integer(), integer(), binary()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. slice_required(Bytes, Offset, Length, Label) -> case gleam_stdlib:bit_array_slice(Bytes, Offset, Length) of {ok, Value} -> {ok, Value}; {error, _} -> {error, {archive_invalid, <<"truncated "/utf8, Label/binary>>}} end. -file("src/packkit/seven_z.gleam", 2995). -spec slice_folder_streams( bitstring(), integer(), list(integer()), list(bitstring()) ) -> {ok, list(bitstring())} | {error, packkit@error:archive_error()}. slice_folder_streams(Packed, Cursor, Sizes, Acc) -> case Sizes of [] -> {ok, lists:reverse(Acc)}; [Size | Rest] -> gleam@result:'try'( slice_required( Packed, Cursor, Size, <<"7z per-folder packed stream"/utf8>> ), fun(Stream) -> slice_folder_streams( Packed, Cursor + Size, Rest, [Stream | Acc] ) end ) end. -file("src/packkit/seven_z.gleam", 4223). -spec read_number_body(integer(), bitstring(), integer(), integer(), integer()) -> {ok, {integer(), bitstring()}} | {error, packkit@error:archive_error()}. read_number_body(First, Rest, Mask, Index, Value) -> case Index >= 8 of true -> {ok, {Value, Rest}}; false -> case erlang:'band'(First, Mask) of 0 -> High_part = erlang:'band'(First, Mask - 1), Final_value = Value + erlang:'bsl'(High_part, Index * 8), {ok, {Final_value, Rest}}; _ -> case Rest of <> -> read_number_body( First, More, erlang:'bsr'(Mask, 1), Index + 1, Value + erlang:'bsl'(Byte, Index * 8) ); _ -> {error, {archive_invalid, <<"truncated 7z multi-byte varint"/utf8>>}} end end end. -file("src/packkit/seven_z.gleam", 4216). -spec read_number(bitstring()) -> {ok, {integer(), bitstring()}} | {error, packkit@error:archive_error()}. read_number(Bytes) -> case Bytes of <> -> read_number_body(First, Rest, 16#80, 0, 0); _ -> {error, {archive_invalid, <<"truncated 7z varint"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 2025). -spec read_bind_pairs(bitstring(), integer(), list({integer(), integer()})) -> {ok, {list({integer(), integer()}), bitstring()}} | {error, packkit@error:archive_error()}. read_bind_pairs(Bytes, Remaining, Acc) -> case Remaining of 0 -> {ok, {lists:reverse(Acc), Bytes}}; _ -> gleam@result:'try'( read_number(Bytes), fun(_use0) -> {In_idx, After_in} = _use0, gleam@result:'try'( read_number(After_in), fun(_use0@1) -> {Out_idx, After_out} = _use0@1, read_bind_pairs( After_out, Remaining - 1, [{In_idx, Out_idx} | Acc] ) end ) end ) end. -file("src/packkit/seven_z.gleam", 2040). -spec read_varint_list(bitstring(), integer(), list(integer())) -> {ok, {list(integer()), bitstring()}} | {error, packkit@error:archive_error()}. read_varint_list(Bytes, Remaining, Acc) -> case Remaining of 0 -> {ok, {lists:reverse(Acc), Bytes}}; _ -> gleam@result:'try'( read_number(Bytes), fun(_use0) -> {Value, After_value} = _use0, read_varint_list(After_value, Remaining - 1, [Value | Acc]) end ) end. -file("src/packkit/seven_z.gleam", 2054). -spec consume_linear_bind_pairs(bitstring(), integer(), integer()) -> {ok, {bitstring(), nil}} | {error, packkit@error:archive_error()}. consume_linear_bind_pairs(Bytes, Next_in_idx, Remaining) -> gleam@bool:guard( Remaining =:= 0, {ok, {Bytes, nil}}, fun() -> gleam@result:'try'( read_number(Bytes), fun(_use0) -> {In_idx, After_in} = _use0, gleam@result:'try'( read_number(After_in), fun(_use0@1) -> {Out_idx, After_out} = _use0@1, Expected_out_idx = Next_in_idx - 1, gleam@bool:guard( (In_idx /= Next_in_idx) orelse (Out_idx /= Expected_out_idx), {error, {archive_not_implemented, <<<<<<<<<<<<<<<<"7z non-linear coder topology (bind in="/utf8, (erlang:integer_to_binary( In_idx ))/binary>>/binary, " out="/utf8>>/binary, (erlang:integer_to_binary( Out_idx ))/binary>>/binary, ", expected linear in="/utf8>>/binary, (erlang:integer_to_binary( Next_in_idx ))/binary>>/binary, " out="/utf8>>/binary, (erlang:integer_to_binary( Expected_out_idx ))/binary>>/binary, ")"/utf8>>}}, fun() -> consume_linear_bind_pairs( After_out, Next_in_idx + 1, Remaining - 1 ) end ) end ) end ) end ). -file("src/packkit/seven_z.gleam", 2569). -spec parse_name_block(bitstring(), integer(), list(bitstring())) -> {ok, list(binary())} | {error, packkit@error:archive_error()}. parse_name_block(Payload, Num_files, Additional_streams) -> case Payload of <> -> case External of 0 -> decode_utf16_names(Rest, Num_files, [], []); _ -> gleam@result:'try'( read_number(Rest), fun(_use0) -> {Data_index, _} = _use0, gleam@result:'try'( get_additional_stream( Additional_streams, Data_index ), fun(External_bytes) -> decode_utf16_names( External_bytes, Num_files, [], [] ) end ) end ) end; _ -> {error, {archive_invalid, <<"truncated 7z file-name section"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 4265). -spec read_numbers_loop(bitstring(), integer(), list(integer())) -> {ok, {list(integer()), bitstring()}} | {error, packkit@error:archive_error()}. read_numbers_loop(Bytes, Remaining, Acc) -> case Remaining of 0 -> {ok, {lists:reverse(Acc), Bytes}}; _ -> gleam@result:'try'( read_number(Bytes), fun(_use0) -> {Value, Rest} = _use0, read_numbers_loop(Rest, Remaining - 1, [Value | Acc]) end ) end. -file("src/packkit/seven_z.gleam", 4258). -spec read_numbers(bitstring(), integer()) -> {ok, {list(integer()), bitstring()}} | {error, packkit@error:archive_error()}. read_numbers(Bytes, Count) -> read_numbers_loop(Bytes, Count, []). -file("src/packkit/seven_z.gleam", 667). -spec encode_via_method(bitstring(), method()) -> {ok, {bitstring(), bitstring()}} | {error, packkit@error:archive_error()}. encode_via_method(Bytes, Method) -> case Method of method_lzma -> Props = {properties, 3, 0, 2}, Compressed = packkit@internal@lzma:encode_with_lz77(Bytes, Props), Prop_byte = packkit@internal@lzma:properties_to_byte(Props), Dict_size_bytes = <<16#10000:32/little>>, Coder_def = <<16#23, 16#03, 16#01, 16#01, (write_varint(5))/bitstring, Prop_byte, Dict_size_bytes/bitstring>>, {ok, {Compressed, Coder_def}}; method_copy -> Coder_def@1 = <<16#01, 16#00>>, {ok, {Bytes, Coder_def@1}}; method_deflate -> gleam@result:'try'( begin _pipe = packkit@deflate:encode(Bytes), gleam@result:map_error(_pipe, fun codec_to_archive/1) end, fun(Compressed@1) -> Coder_def@2 = <<16#03, 16#04, 16#01, 16#08>>, {ok, {Compressed@1, Coder_def@2}} end ); method_bzip2 -> gleam@result:'try'( begin _pipe@1 = packkit@bzip2:encode(Bytes), gleam@result:map_error(_pipe@1, fun codec_to_archive/1) end, fun(Compressed@2) -> Coder_def@3 = <<16#03, 16#04, 16#02, 16#02>>, {ok, {Compressed@2, Coder_def@3}} end ) end. -file("src/packkit/seven_z.gleam", 2176). -spec classify_coder_id(bitstring()) -> {ok, coder_id()} | {error, packkit@error:archive_error()}. classify_coder_id(Id_bytes) -> case Id_bytes of <> when B =:= 16#00 -> {ok, copy}; <> when B@1 =:= 16#21 -> {ok, lzma2}; <> when B@2 =:= 16#03 -> {ok, delta}; <> when ((B1 =:= 16#03) andalso (B2 =:= 16#01)) andalso (B3 =:= 16#01) -> {ok, lzma}; <> when ((B1@1 =:= 16#04) andalso (B2@1 =:= 16#01)) andalso (B3@1 =:= 16#08) -> {ok, deflate}; <> when ((B1@2 =:= 16#04) andalso (B2@2 =:= 16#02)) andalso (B3@2 =:= 16#02) -> {ok, b_zip2}; <> when (((B1@3 =:= 16#06) andalso (B2@3 =:= 16#F1)) andalso (B3@3 =:= 16#07)) andalso (B4 =:= 16#01) -> {ok, aes256_sha256}; <> when (((B1@4 =:= 16#03) andalso (B2@4 =:= 16#03)) andalso (B3@4 =:= 16#01)) andalso (B4@1 =:= 16#1B) -> {ok, bcj2}; <> when (B1@5 =:= 16#03) andalso (B2@5 =:= 16#03) -> case {B3@5, B4@2} of {V3, V4} when (V3 =:= 16#01) andalso (V4 =:= 16#03) -> {ok, bcj_x86}; {V3@1, V4@1} when (V3@1 =:= 16#02) andalso (V4@1 =:= 16#05) -> {ok, bcj_ppc}; {V3@2, V4@2} when (V3@2 =:= 16#04) andalso (V4@2 =:= 16#01) -> {ok, bcj_ia64}; {V3@3, V4@3} when (V3@3 =:= 16#05) andalso (V4@3 =:= 16#01) -> {ok, bcj_arm}; {V3@4, V4@4} when (V3@4 =:= 16#07) andalso (V4@4 =:= 16#01) -> {ok, bcj_arm_t}; {V3@5, V4@5} when (V3@5 =:= 16#08) andalso (V4@5 =:= 16#05) -> {ok, bcj_sparc}; {_, _} -> {error, {archive_not_implemented, <<"7z coder id "/utf8, (describe_bit_array_hex(Id_bytes, <<""/utf8>>))/binary>>}} end; _ -> {error, {archive_not_implemented, <<"7z coder id "/utf8, (describe_bit_array_hex(Id_bytes, <<""/utf8>>))/binary>>}} end. -file("src/packkit/seven_z.gleam", 2094). -spec parse_one_coder(bitstring()) -> {ok, {coder_spec(), bitstring()}} | {error, packkit@error:archive_error()}. parse_one_coder(Bytes) -> case Bytes of <> -> Id_size = erlang:'band'(Flags, 16#0F), Is_complex = erlang:'band'(Flags, 16#10) /= 0, Has_attrs = erlang:'band'(Flags, 16#20) /= 0, gleam@result:'try'( slice_required(After_flags, 0, Id_size, <<"7z coder id"/utf8>>), fun(Coder_id_bytes) -> gleam@result:'try'( begin _pipe = gleam_stdlib:bit_array_slice( After_flags, Id_size, erlang:byte_size(After_flags) - Id_size ), gleam@result:replace_error( _pipe, {archive_invalid, <<"7z coder id slice failed"/utf8>>} ) end, fun(After_coder_id) -> gleam@result:'try'( classify_coder_id(Coder_id_bytes), fun(Coder_id) -> gleam@result:'try'(case Is_complex of false -> {ok, {1, 1, After_coder_id}}; true -> gleam@result:'try'( read_number(After_coder_id), fun(_use0) -> {Num_in_streams, Rest_a} = _use0, gleam@result:'try'( read_number(Rest_a), fun(_use0@1) -> {Num_out_streams, Rest_b} = _use0@1, {ok, {Num_in_streams, Num_out_streams, Rest_b}} end ) end ) end, fun(_use0@2) -> {Num_in, Num_out, After_streams} = _use0@2, case Has_attrs of false -> {ok, {{coder_spec, Coder_id, <<>>, Num_in, Num_out}, After_streams}}; true -> gleam@result:'try'( read_number( After_streams ), fun(_use0@3) -> {Attrs_size, After_attrs_size} = _use0@3, gleam@result:'try'( slice_required( After_attrs_size, 0, Attrs_size, <<"7z coder attributes"/utf8>> ), fun(Attrs) -> gleam@result:'try'( begin _pipe@1 = gleam_stdlib:bit_array_slice( After_attrs_size, Attrs_size, erlang:byte_size( After_attrs_size ) - Attrs_size ), gleam@result:replace_error( _pipe@1, {archive_invalid, <<"7z coder attrs slice failed"/utf8>>} ) end, fun( After_attrs ) -> {ok, {{coder_spec, Coder_id, Attrs, Num_in, Num_out}, After_attrs}} end ) end ) end ) end end) end ) end ) end ); _ -> {error, {archive_invalid, <<"truncated 7z coder definition"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 2080). -spec parse_coders_loop(bitstring(), integer(), list(coder_spec())) -> {ok, {list(coder_spec()), bitstring()}} | {error, packkit@error:archive_error()}. parse_coders_loop(Bytes, Remaining, Acc) -> case Remaining of 0 -> {ok, {lists:reverse(Acc), Bytes}}; _ -> gleam@result:'try'( parse_one_coder(Bytes), fun(_use0) -> {Coder, Rest} = _use0, parse_coders_loop(Rest, Remaining - 1, [Coder | Acc]) end ) end. -file("src/packkit/seven_z.gleam", 1954). -spec parse_one_folder(bitstring()) -> {ok, {parsed_folder(), bitstring()}} | {error, packkit@error:archive_error()}. parse_one_folder(Bytes) -> gleam@result:'try'( read_number(Bytes), fun(_use0) -> {Num_coders, Rest} = _use0, gleam@bool:guard( Num_coders < 1, {error, {archive_invalid, <<"7z folder declares zero coders"/utf8>>}}, fun() -> gleam@bool:guard( Num_coders > 3, {error, {archive_not_implemented, <<<<"7z folders with "/utf8, (erlang:integer_to_binary(Num_coders))/binary>>/binary, " coders"/utf8>>}}, fun() -> gleam@result:'try'( parse_coders_loop(Rest, Num_coders, []), fun(_use0@1) -> {Coders, Rest@1} = _use0@1, Total_in = sum_coder_in_streams(Coders, 0), Total_out = sum_coder_out_streams(Coders, 0), Num_bind_pairs = Total_out - 1, Num_packed_streams = Total_in - Num_bind_pairs, case {Num_coders, Total_in =:= Total_out} of {1, _} -> {ok, {{parsed_folder, Coders, []}, Rest@1}}; {_, true} -> gleam@result:'try'( consume_linear_bind_pairs( Rest@1, 1, Num_bind_pairs ), fun(_use0@2) -> {After_bind_pairs, _} = _use0@2, {ok, {{parsed_folder, Coders, []}, After_bind_pairs}} end ); {_, false} -> gleam@result:'try'( read_bind_pairs( Rest@1, Num_bind_pairs, [] ), fun(_use0@3) -> {_, After_bind_pairs@1} = _use0@3, gleam@result:'try'( case Num_packed_streams > 1 of true -> read_varint_list( After_bind_pairs@1, Num_packed_streams, [] ); false -> {ok, {[], After_bind_pairs@1}} end, fun(_use0@4) -> {Packed_indices, After_packed} = _use0@4, {ok, {{parsed_folder, Coders, Packed_indices}, After_packed}} end ) end ) end end ) end ) end ) end ). -file("src/packkit/seven_z.gleam", 1906). -spec parse_folders_loop(bitstring(), integer(), list(parsed_folder())) -> {ok, {list(parsed_folder()), bitstring()}} | {error, packkit@error:archive_error()}. parse_folders_loop(Bytes, Remaining, Acc) -> case Remaining of 0 -> {ok, {lists:reverse(Acc), Bytes}}; _ -> gleam@result:'try'( parse_one_folder(Bytes), fun(_use0) -> {Folder, Rest} = _use0, parse_folders_loop(Rest, Remaining - 1, [Folder | Acc]) end ) end. -file("src/packkit/seven_z.gleam", 1763). -spec parse_folders(bitstring(), list(bitstring())) -> {ok, {list(parsed_folder()), bitstring()}} | {error, packkit@error:archive_error()}. parse_folders(Bytes, Additional_streams) -> gleam@result:'try'( read_number(Bytes), fun(_use0) -> {Num_folders, Rest} = _use0, gleam@bool:guard( Num_folders < 1, {error, {archive_invalid, <<"7z UnPackInfo declares zero folders"/utf8>>}}, fun() -> case Rest of <> -> case External of 0 -> parse_folders_loop( After_external, Num_folders, [] ); _ -> gleam@result:'try'( read_number(After_external), fun(_use0@1) -> {Data_index, After_data_index} = _use0@1, gleam@result:'try'( get_additional_stream( Additional_streams, Data_index ), fun(External_bytes) -> gleam@result:'try'( parse_folders_loop( External_bytes, Num_folders, [] ), fun(_use0@2) -> {Parsed_folders, _} = _use0@2, {ok, {Parsed_folders, After_data_index}} end ) end ) end ) end; _ -> {error, {archive_invalid, <<"truncated 7z folder section"/utf8>>}} end end ) end ). -file("src/packkit/seven_z.gleam", 3574). -spec aes_cbc_encrypt( bitstring(), packkit@internal@aes:expanded_key(), bitstring() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. aes_cbc_encrypt(Plaintext, Key, Iv) -> Plaintext_size = erlang:byte_size(Plaintext), Remainder = erlang:'band'(Plaintext_size, 16 - 1), Padding_bytes = case Remainder of 0 -> 0; Used -> 16 - Used end, Padding = case Padding_bytes of 0 -> <<>>; _ -> <<0:(lists:max([((Padding_bytes * 8)), 0]))>> end, Padded = <>, aes_cbc_encrypt_loop(Padded, Key, iv_or_zero(Iv), <<>>). -file("src/packkit/seven_z.gleam", 3625). -spec aes_cbc_decrypt( bitstring(), packkit@internal@aes:expanded_key(), bitstring() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. aes_cbc_decrypt(Ciphertext, Key, Iv) -> Size = erlang:byte_size(Ciphertext), case erlang:'band'(Size, 16 - 1) of 0 -> aes_cbc_decrypt_loop(Ciphertext, Key, iv_or_zero(Iv), <<>>); _ -> {error, {archive_invalid, <<<<"7z AES ciphertext length "/utf8, (erlang:integer_to_binary(Size))/binary>>/binary, " is not a multiple of 16"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 807). -spec build_aes_props_tail(bitstring(), bitstring(), integer(), integer()) -> bitstring(). build_aes_props_tail(Salt, Iv, Salt_extra, Iv_extra) -> Second_byte = erlang:'bor'(erlang:'bsl'(Salt_extra, 4), Iv_extra), <<Second_byte, Salt/bitstring, Iv/bitstring>>. -file("src/packkit/seven_z.gleam", 821). -spec build_aes_coder_def(encryption_spec()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. build_aes_coder_def(Spec) -> Salt_size = erlang:byte_size(erlang:element(3, Spec)), Iv_size = erlang:byte_size(erlang:element(4, Spec)), gleam@bool:guard( (Salt_size > 16) orelse (Iv_size > 16), {error, {archive_invalid, <<"7z AES encoder: salt or iv exceeds 16 bytes"/utf8>>}}, fun() -> gleam@bool:guard( (erlang:element(5, Spec) < 0) orelse (erlang:element(5, Spec) >= 16#3F), {error, {archive_invalid, <<"7z AES encoder: numCyclesPower must be in 0..62 (0x3F is reserved)"/utf8>>}}, fun() -> Salt_flag = Salt_size > 0, Iv_flag = Iv_size > 0, First_byte = erlang:'bor'( erlang:element(5, Spec), erlang:'bor'( 16#80 * flag_to_int(Salt_flag), 16#40 * flag_to_int(Iv_flag) ) ), Props_after_first = case Salt_flag orelse Iv_flag of false -> <<>>; true -> build_aes_props_tail( erlang:element(3, Spec), erlang:element(4, Spec), Salt_size - flag_to_int(Salt_flag), Iv_size - flag_to_int(Iv_flag) ) end, Props = <<First_byte, Props_after_first/bitstring>>, Props_size = erlang:byte_size(Props), {ok, gleam_stdlib:bit_array_concat( [<<16#24>>, <<16#06, 16#F1, 16#07, 16#01>>, write_varint(Props_size), Props] )} end ) end ). -file("src/packkit/seven_z.gleam", 3414). -spec parse_aes_field_sizes(bitstring(), integer(), boolean(), boolean()) -> {ok, aes_properties()} | {error, packkit@error:archive_error()}. parse_aes_field_sizes(After_first_byte, Num_cycles_power, Salt_flag, Iv_flag) -> case After_first_byte of <<Second_byte, After_second/binary>> -> Salt_base = flag_to_int(Salt_flag), Iv_base = flag_to_int(Iv_flag), Salt_size = Salt_base + erlang:'bsr'(Second_byte, 4), Iv_size = Iv_base + erlang:'band'(Second_byte, 16#0F), gleam@bool:guard( (Salt_size > 16) orelse (Iv_size > 16), {error, {archive_invalid, <<"7z AES salt or iv size exceeds 16 bytes"/utf8>>}}, fun() -> gleam@result:'try'( begin _pipe = gleam_stdlib:bit_array_slice( After_second, 0, Salt_size ), gleam@result:replace_error( _pipe, {archive_invalid, <<"7z AES salt slice failed"/utf8>>} ) end, fun(Salt) -> gleam@result:'try'( begin _pipe@1 = gleam_stdlib:bit_array_slice( After_second, Salt_size, Iv_size ), gleam@result:replace_error( _pipe@1, {archive_invalid, <<"7z AES iv slice failed"/utf8>>} ) end, fun(Iv) -> {ok, {aes_properties, Num_cycles_power, Salt, Iv}} end ) end ) end ); _ -> {error, {archive_invalid, <<"7z AES coder properties truncated before salt/iv sizes"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 3393). -spec parse_aes_properties(bitstring()) -> {ok, aes_properties()} | {error, packkit@error:archive_error()}. parse_aes_properties(Properties) -> case Properties of <<First_byte, Rest/binary>> -> Num_cycles_power = erlang:'band'(First_byte, 16#3F), Iv_flag = erlang:'band'(First_byte, 16#40) /= 0, Salt_flag = erlang:'band'(First_byte, 16#80) /= 0, gleam@bool:guard( not Salt_flag andalso not Iv_flag, {ok, {aes_properties, Num_cycles_power, <<>>, <<>>}}, fun() -> parse_aes_field_sizes( Rest, Num_cycles_power, Salt_flag, Iv_flag ) end ); _ -> {error, {archive_invalid, <<"7z AES coder properties are empty or non-byte-aligned"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 381). -spec default_encryption_spec(binary()) -> encryption_spec(). default_encryption_spec(Password) -> {encryption_spec, Password, <<>>, <<0:128>>, 19}. -file("src/packkit/seven_z.gleam", 3495). -spec derive_aes_key_direct(bitstring(), bitstring()) -> bitstring(). derive_aes_key_direct(Salt, Password_utf16le) -> Combined = <<Salt/bitstring, Password_utf16le/bitstring, 0:(lists:max([((32 * 8)), 0]))>>, _pipe = gleam_stdlib:bit_array_slice(Combined, 0, 32), gleam@result:unwrap(_pipe, <<0:(lists:max([((32 * 8)), 0]))>>). -file("src/packkit/seven_z.gleam", 3465). -spec derive_aes_key(binary(), bitstring(), integer()) -> {ok, packkit@internal@aes:expanded_key()} | {error, packkit@error:archive_error()}. derive_aes_key(Password, Salt, Num_cycles_power) -> Password_utf16le = utf16le_encode(Password, <<>>), Digest = case Num_cycles_power =:= 16#3F of true -> derive_aes_key_direct(Salt, Password_utf16le); false -> derive_aes_key_hashed(Salt, Password_utf16le, Num_cycles_power) end, case packkit@internal@aes:expand_key(Digest) of {ok, Expanded} -> {ok, Expanded}; {error, nil} -> {error, {archive_invalid, <<"7z AES key expansion rejected the derived 32-byte digest"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 744). -spec maybe_wrap_with_aes( bitstring(), bitstring(), integer(), integer(), gleam@option:option(encryption_spec()) ) -> {ok, {bitstring(), folder_encoding()}} | {error, packkit@error:archive_error()}. maybe_wrap_with_aes( Inner_packed, Inner_coder_def, Inner_packed_size, Total_unpack, Encryption ) -> case Encryption of none -> {ok, {Inner_packed, {folder_encoding, gleam_stdlib:bit_array_concat( [write_varint(1), Inner_coder_def] ), write_varint(Total_unpack)}}}; {some, Spec} -> gleam@result:'try'( derive_aes_key( erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(5, Spec) ), fun(Key) -> gleam@result:'try'( aes_cbc_encrypt( Inner_packed, Key, erlang:element(4, Spec) ), fun(Ciphertext) -> gleam@result:'try'( build_aes_coder_def(Spec), fun(Aes_coder_def) -> Folder_coders_block = gleam_stdlib:bit_array_concat( [write_varint(2), Aes_coder_def, Inner_coder_def, write_varint(1), write_varint(0)] ), Coders_unpack_sizes_block = gleam_stdlib:bit_array_concat( [write_varint(Inner_packed_size), write_varint(Total_unpack)] ), {ok, {Ciphertext, {folder_encoding, Folder_coders_block, Coders_unpack_sizes_block}}} end ) end ) end ) end. -file("src/packkit/seven_z.gleam", 3351). -spec decode_aes_coder( bitstring(), bitstring(), list(integer()), gleam@option:option(binary()) ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_aes_coder(Packed, Properties, Unpack_sizes, Password) -> gleam@result:'try'(case Password of {some, Value} -> {ok, Value}; none -> {error, {archive_invalid, <<"7z AES folder requires a password — call decode_with_password"/utf8>>}} end, fun(Password_value) -> gleam@result:'try'( parse_aes_properties(Properties), fun(Props) -> gleam@result:'try'( derive_aes_key( Password_value, erlang:element(3, Props), erlang:element(2, Props) ), fun(Key) -> gleam@result:'try'( aes_cbc_decrypt( Packed, Key, erlang:element(4, Props) ), fun(Plaintext) -> Target = folder_unpack_total(Unpack_sizes), Plaintext_size = erlang:byte_size(Plaintext), gleam@bool:guard( Plaintext_size < Target, {error, {archive_invalid, <<<<<<"7z AES decrypted "/utf8, (erlang:integer_to_binary( Plaintext_size ))/binary>>/binary, " bytes < declared "/utf8>>/binary, (erlang:integer_to_binary( Target ))/binary>>}}, fun() -> _pipe = gleam_stdlib:bit_array_slice( Plaintext, 0, Target ), gleam@result:replace_error( _pipe, {archive_invalid, <<"7z AES decrypted slice failed"/utf8>>} ) end ) end ) end ) end ) end). -file("src/packkit/seven_z.gleam", 3204). -spec dispatch_coder( bitstring(), coder_spec(), list(integer()), gleam@option:option(binary()), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. dispatch_coder(Packed, Spec, Unpack_sizes, Password, Limits) -> case erlang:element(2, Spec) of lzma2 -> decode_lzma2_payload(Packed, erlang:element(3, Spec), Unpack_sizes); lzma -> decode_raw_lzma(Packed, erlang:element(3, Spec), Unpack_sizes); copy -> decode_copy_coder(Packed, Unpack_sizes); deflate -> decode_deflate_coder(Packed, Unpack_sizes, Limits); b_zip2 -> decode_bzip2_coder(Packed, Unpack_sizes, Limits); delta -> decode_delta_coder(Packed, erlang:element(3, Spec), Unpack_sizes); bcj_x86 -> decode_bcj_coder( Packed, Unpack_sizes, fun packkit@internal@bcj:x86_decode/2, <<"x86"/utf8>> ); bcj_ppc -> decode_bcj_coder( Packed, Unpack_sizes, fun packkit@internal@bcj:powerpc_decode/2, <<"PowerPC"/utf8>> ); bcj_ia64 -> decode_bcj_coder( Packed, Unpack_sizes, fun packkit@internal@bcj:ia64_decode/2, <<"IA-64"/utf8>> ); bcj_arm -> decode_bcj_coder( Packed, Unpack_sizes, fun packkit@internal@bcj:arm_decode/2, <<"ARM"/utf8>> ); bcj_arm_t -> decode_bcj_coder( Packed, Unpack_sizes, fun packkit@internal@bcj:armthumb_decode/2, <<"ARM-Thumb"/utf8>> ); bcj_sparc -> decode_bcj_coder( Packed, Unpack_sizes, fun packkit@internal@bcj:sparc_decode/2, <<"SPARC"/utf8>> ); aes256_sha256 -> decode_aes_coder( Packed, erlang:element(3, Spec), Unpack_sizes, Password ); bcj2 -> {error, {archive_not_implemented, <<"7z BCJ2 outside its canonical [simple, BCJ2(4,1)] folder layout"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 3076). -spec decode_bcj2_folder( bitstring(), bitstring(), bitstring(), bitstring(), coder_spec(), list(integer()), gleam@option:option(binary()), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_bcj2_folder( Main_packed, Call_packed, Jump_packed, Rc_packed, Inner_spec, Unpack_sizes, Password, Limits ) -> {Inner_unpack_size, Bcj2_output_size} = case Unpack_sizes of [First, Second | _] -> {First, Second}; [Only] -> {Only, Only}; [] -> {0, 0} end, gleam@result:'try'( dispatch_coder( Main_packed, Inner_spec, [Inner_unpack_size], Password, Limits ), fun(Main_stream) -> _pipe = packkit@internal@bcj2:decode( Main_stream, Call_packed, Jump_packed, Rc_packed, Bcj2_output_size ), gleam@result:map_error(_pipe, fun bcj2_error_to_archive/1) end ). -file("src/packkit/seven_z.gleam", 3131). -spec decode_linear_chain( bitstring(), list(coder_spec()), list(integer()), gleam@option:option(binary()), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_linear_chain(Packed, Coders, Unpack_sizes, Password, Limits) -> case {Coders, Unpack_sizes} of {[], _} -> {error, {archive_invalid, <<"7z folder has unsupported coder count"/utf8>>}}; {[Single], _} -> dispatch_coder(Packed, Single, Unpack_sizes, Password, Limits); {[Head | Rest_coders], [Head_size | Rest_sizes]} -> gleam@result:'try'( dispatch_coder(Packed, Head, [Head_size], Password, Limits), fun(Intermediate) -> _pipe = decode_linear_chain( Intermediate, Rest_coders, Rest_sizes, Password, Limits ), gleam@result:map_error( _pipe, fun(_capture) -> maybe_wrap_aes_chain_error( _capture, erlang:element(2, Head) ) end ) end ); {_, _} -> {error, {archive_invalid, <<"7z folder coder list longer than CodersUnPackSize block"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 3027). -spec decode_folder( list(bitstring()), parsed_folder(), list(integer()), gleam@option:option(binary()), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_folder(Packed_streams, Folder, Unpack_sizes, Password, Limits) -> case {Packed_streams, erlang:element(2, Folder)} of {[Single_packed], _} -> decode_linear_chain( Single_packed, erlang:element(2, Folder), Unpack_sizes, Password, Limits ); {[Main_packed, Call_packed, Jump_packed, Rc_packed], [Inner_spec, Bcj2_spec]} when (erlang:element(2, Bcj2_spec) =:= bcj2) andalso (erlang:element( 4, Bcj2_spec ) =:= 4) -> decode_bcj2_folder( Main_packed, Call_packed, Jump_packed, Rc_packed, Inner_spec, Unpack_sizes, Password, Limits ); {_, _} -> {error, {archive_not_implemented, <<<<<<<<"7z folder topology with "/utf8, (erlang:integer_to_binary( erlang:length(Packed_streams) ))/binary>>/binary, " packed streams and "/utf8>>/binary, (erlang:integer_to_binary( erlang:length(erlang:element(2, Folder)) ))/binary>>/binary, " coders"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 1845). -spec decode_additional_streams_loop( bitstring(), list(parsed_folder()), list(list(integer())), list(integer()), packkit@limit:limits(), integer(), list(bitstring()) ) -> {ok, list(bitstring())} | {error, packkit@error:archive_error()}. decode_additional_streams_loop( Packed, Folders, Folder_unpack_sizes, Pack_sizes, Limits, Pack_cursor, Acc ) -> case {Folders, Folder_unpack_sizes} of {[], []} -> {ok, lists:reverse(Acc)}; {[Folder | Rest_folders], [Unpack_sizes | Rest_unpack]} -> Stream_count = folder_packed_stream_count(Folder), Folder_pack_sizes = gleam@list:take(Pack_sizes, Stream_count), Rest_pack_sizes = gleam@list:drop(Pack_sizes, Stream_count), gleam@result:'try'( slice_folder_streams(Packed, Pack_cursor, Folder_pack_sizes, []), fun(Folder_streams) -> gleam@result:'try'( decode_folder( Folder_streams, Folder, Unpack_sizes, none, Limits ), fun(Folder_plain) -> Next_cursor = Pack_cursor + sum_list( Folder_pack_sizes, 0 ), decode_additional_streams_loop( Packed, Rest_folders, Rest_unpack, Rest_pack_sizes, Limits, Next_cursor, [Folder_plain | Acc] ) end ) end ); {_, _} -> {error, {archive_invalid, <<"7z AdditionalStreamsInfo folder/unpack-size lists misaligned"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 1813). -spec decode_additional_streams( header_streams(), bitstring(), packkit@limit:limits() ) -> {ok, list(bitstring())} | {error, packkit@error:archive_error()}. decode_additional_streams(Streams_info, Full_archive, Limits) -> case Streams_info of header_streams_none -> {error, {archive_invalid, <<"7z AdditionalStreamsInfo has no StreamsInfo body"/utf8>>}}; {header_streams_parsed, Pack_pos, Pack_sizes, Folders, Folder_unpack_sizes, _} -> Pack_offset = 32 + Pack_pos, Total_pack_size = sum_list(Pack_sizes, 0), gleam@result:'try'( slice_required( Full_archive, Pack_offset, Total_pack_size, <<"7z AdditionalStreamsInfo packed bytes"/utf8>> ), fun(Packed) -> decode_additional_streams_loop( Packed, Folders, Folder_unpack_sizes, Pack_sizes, Limits, 0, [] ) end ) end. -file("src/packkit/seven_z.gleam", 2940). -spec decode_all_folders( bitstring(), list(parsed_folder()), list(list(integer())), list(integer()), gleam@option:option(binary()), packkit@limit:limits(), integer(), list(bitstring()) ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_all_folders( Packed, Folders, Folder_unpack_sizes, Pack_sizes, Password, Limits, Pack_cursor, Acc ) -> case {Folders, Folder_unpack_sizes} of {[], []} -> {ok, gleam_stdlib:bit_array_concat(lists:reverse(Acc))}; {[Folder | Rest_folders], [Unpack_sizes | Rest_unpack]} -> Stream_count = folder_packed_stream_count(Folder), Folder_pack_sizes = gleam@list:take(Pack_sizes, Stream_count), Rest_pack_sizes = gleam@list:drop(Pack_sizes, Stream_count), gleam@result:'try'( slice_folder_streams(Packed, Pack_cursor, Folder_pack_sizes, []), fun(Folder_streams) -> gleam@result:'try'( decode_folder( Folder_streams, Folder, Unpack_sizes, Password, Limits ), fun(Folder_plain) -> Next_cursor = Pack_cursor + sum_list( Folder_pack_sizes, 0 ), decode_all_folders( Packed, Rest_folders, Rest_unpack, Rest_pack_sizes, Password, Limits, Next_cursor, [Folder_plain | Acc] ) end ) end ); {_, _} -> {error, {archive_invalid, <<"7z folder / unpack-size lists are misaligned"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 880). -spec build_sub_streams_info(list(integer())) -> bitstring(). build_sub_streams_info(Unpack_sizes) -> Explicit_sizes = drop_last(Unpack_sizes, []), Size_block = gleam@list:fold( Explicit_sizes, <<>>, fun(Acc, N) -> gleam_stdlib:bit_array_concat([Acc, write_varint(N)]) end ), Num_files = erlang:length(Unpack_sizes), gleam_stdlib:bit_array_concat( [<<16#08>>, <<16#0D>>, write_varint(Num_files), <<16#09>>, Size_block, <<16#00>>] ). -file("src/packkit/seven_z.gleam", 1656). -spec parse_pack_info_body(bitstring(), integer(), integer(), list(integer())) -> {ok, {integer(), list(integer()), bitstring()}} | {error, packkit@error:archive_error()}. parse_pack_info_body(Bytes, Pack_pos, Num_pack_streams, Sizes) -> case Bytes of <<Nid, Rest/binary>> -> case Nid of N when N =:= 16#00 -> {ok, {Pack_pos, Sizes, Rest}}; N@1 when N@1 =:= 16#09 -> gleam@result:'try'( read_numbers(Rest, Num_pack_streams), fun(_use0) -> {Read_sizes, Rest@1} = _use0, parse_pack_info_body( Rest@1, Pack_pos, Num_pack_streams, Read_sizes ) end ); N@2 when N@2 =:= 16#0A -> gleam@result:'try'( skip_crc_block(Rest, Num_pack_streams), fun(Rest@2) -> parse_pack_info_body( Rest@2, Pack_pos, Num_pack_streams, Sizes ) end ); _ -> {error, {archive_invalid, <<"unexpected 7z PackInfo NID "/utf8, (erlang:integer_to_binary(Nid))/binary>>}} end; _ -> {error, {archive_invalid, <<"truncated 7z PackInfo"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 1648). -spec parse_pack_info(bitstring()) -> {ok, {integer(), list(integer()), bitstring()}} | {error, packkit@error:archive_error()}. parse_pack_info(Bytes) -> gleam@result:'try'( read_number(Bytes), fun(_use0) -> {Pack_pos, Rest} = _use0, gleam@result:'try'( read_number(Rest), fun(_use0@1) -> {Num_pack_streams, Rest@1} = _use0@1, parse_pack_info_body(Rest@1, Pack_pos, Num_pack_streams, []) end ) end ). -file("src/packkit/seven_z.gleam", 2772). -spec sub_streams_loop_collect(bitstring(), integer(), sub_streams_acc()) -> {ok, {sub_streams_acc(), bitstring()}} | {error, packkit@error:archive_error()}. sub_streams_loop_collect(Bytes, Num_folders, Acc) -> case Bytes of <<Nid, Rest/binary>> -> case Nid of N when N =:= 16#00 -> {ok, {Acc, Rest}}; 16#0D -> gleam@result:'try'( read_numbers(Rest, Num_folders), fun(_use0) -> {Counts, Rest@1} = _use0, sub_streams_loop_collect( Rest@1, Num_folders, {sub_streams_acc, Counts, erlang:element(3, Acc)} ) end ); N@1 when N@1 =:= 16#09 -> Per_folder = case erlang:element(2, Acc) of [] -> repeat_one_per_folder(Num_folders, []); Values -> Values end, Explicit_count = sum_list(Per_folder, 0) - erlang:length( Per_folder ), Safe_count = case Explicit_count > 0 of true -> Explicit_count; false -> 0 end, gleam@result:'try'( read_numbers(Rest, Safe_count), fun(_use0@1) -> {Sizes, Rest@2} = _use0@1, sub_streams_loop_collect( Rest@2, Num_folders, {sub_streams_acc, erlang:element(2, Acc), Sizes} ) end ); N@2 when N@2 =:= 16#0A -> Total = case erlang:element(2, Acc) of [] -> Num_folders; Values@1 -> sum_list(Values@1, 0) end, gleam@result:'try'( skip_crc_block(Rest, Total), fun(Rest@3) -> sub_streams_loop_collect(Rest@3, Num_folders, Acc) end ); _ -> {error, {archive_invalid, <<"unexpected 7z SubStreamsInfo NID "/utf8, (erlang:integer_to_binary(Nid))/binary>>}} end; _ -> {error, {archive_invalid, <<"truncated 7z SubStreamsInfo"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 2736). -spec parse_sub_streams_info(bitstring(), integer(), list(integer())) -> {ok, {list(integer()), list(integer()), bitstring()}} | {error, packkit@error:archive_error()}. parse_sub_streams_info(Bytes, Num_folders, Folder_unpack_sizes) -> Initial = {sub_streams_acc, [], []}, gleam@result:'try'( sub_streams_loop_collect(Bytes, Num_folders, Initial), fun(_use0) -> {Acc, Rest} = _use0, Per_folder = case erlang:element(2, Acc) of [] -> repeat_one_per_folder(Num_folders, []); Values -> Values end, Total_substreams = sum_list(Per_folder, 0), Sizes = derive_substream_sizes( Per_folder, Folder_unpack_sizes, erlang:element(3, Acc), [] ), case erlang:length(Sizes) =:= Total_substreams of true -> {ok, {Per_folder, Sizes, Rest}}; false -> {error, {archive_invalid, <<"7z SubStreamsInfo: derived substream count mismatch"/utf8>>}} end end ). -file("src/packkit/seven_z.gleam", 1698). -spec parse_unpack_info_body( bitstring(), list(parsed_folder()), list(list(integer())), list(bitstring()) ) -> {ok, {list(parsed_folder()), list(list(integer())), bitstring()}} | {error, packkit@error:archive_error()}. parse_unpack_info_body(Bytes, Folders, Folder_unpack_sizes, Additional_streams) -> case Bytes of <<Nid, Rest/binary>> -> case Nid of N when N =:= 16#00 -> case Folders of [] -> {error, {archive_invalid, <<"7z UnPackInfo missing Folder section"/utf8>>}}; _ -> {ok, {Folders, Folder_unpack_sizes, Rest}} end; N@1 when N@1 =:= 16#0B -> gleam@result:'try'( parse_folders(Rest, Additional_streams), fun(_use0) -> {Parsed_folders, Rest@1} = _use0, parse_unpack_info_body( Rest@1, Parsed_folders, Folder_unpack_sizes, Additional_streams ) end ); N@2 when N@2 =:= 16#0C -> Total_size_count = gleam@list:fold( Folders, 0, fun(Acc, F) -> Acc + erlang:length(erlang:element(2, F)) end ), gleam@result:'try'( read_numbers(Rest, Total_size_count), fun(_use0@1) -> {Flat_sizes, Rest@2} = _use0@1, Grouped = split_unpack_sizes_by_folder( Flat_sizes, Folders, [] ), parse_unpack_info_body( Rest@2, Folders, Grouped, Additional_streams ) end ); N@3 when N@3 =:= 16#0A -> gleam@result:'try'( skip_crc_block(Rest, erlang:length(Folders)), fun(Rest@3) -> parse_unpack_info_body( Rest@3, Folders, Folder_unpack_sizes, Additional_streams ) end ); _ -> {error, {archive_invalid, <<"unexpected 7z UnPackInfo NID "/utf8, (erlang:integer_to_binary(Nid))/binary>>}} end; _ -> {error, {archive_invalid, <<"truncated 7z UnPackInfo"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 1688). -spec parse_unpack_info(bitstring(), list(bitstring())) -> {ok, {list(parsed_folder()), list(list(integer())), bitstring()}} | {error, packkit@error:archive_error()}. parse_unpack_info(Bytes, Additional_streams) -> parse_unpack_info_body(Bytes, [], [], Additional_streams). -file("src/packkit/seven_z.gleam", 1561). -spec parse_streams_loop(bitstring(), streams_parser(), list(bitstring())) -> {ok, {header_streams(), bitstring()}} | {error, packkit@error:archive_error()}. parse_streams_loop(Bytes, State, Additional_streams) -> case Bytes of <<Nid, Rest/binary>> -> case Nid of N when N =:= 16#00 -> case erlang:element(4, State) of [] -> {error, {archive_invalid, <<"7z MainStreamsInfo missing UnPackInfo"/utf8>>}}; _ -> {ok, {{header_streams_parsed, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State)}, Rest}} end; N@1 when N@1 =:= 16#06 -> gleam@result:'try'( parse_pack_info(Rest), fun(_use0) -> {Pack_pos, Pack_sizes, Rest@1} = _use0, parse_streams_loop( Rest@1, {streams_parser, Pack_pos, Pack_sizes, erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), true, erlang:element(8, State)}, Additional_streams ) end ); N@2 when N@2 =:= 16#07 -> gleam@result:'try'( parse_unpack_info(Rest, Additional_streams), fun(_use0@1) -> {Folders, Folder_unpack_sizes, Rest@2} = _use0@1, parse_streams_loop( Rest@2, {streams_parser, erlang:element(2, State), erlang:element(3, State), Folders, Folder_unpack_sizes, erlang:element(6, State), erlang:element(7, State), true}, Additional_streams ) end ); N@3 when N@3 =:= 16#08 -> Folder_totals = gleam@list:map( erlang:element(5, State), fun last_of_list/1 ), gleam@result:'try'( parse_sub_streams_info( Rest, erlang:length(erlang:element(4, State)), Folder_totals ), fun(_use0@2) -> {_, Substream_sizes, Rest@3} = _use0@2, parse_streams_loop( Rest@3, {streams_parser, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), Substream_sizes, erlang:element(7, State), erlang:element(8, State)}, Additional_streams ) end ); _ -> {error, {archive_invalid, <<"unexpected 7z MainStreamsInfo NID "/utf8, (erlang:integer_to_binary(Nid))/binary>>}} end; _ -> {error, {archive_invalid, <<"truncated 7z MainStreamsInfo"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 1532). -spec parse_main_streams_info(bitstring(), list(bitstring())) -> {ok, {header_streams(), bitstring()}} | {error, packkit@error:archive_error()}. parse_main_streams_info(Bytes, Additional_streams) -> State = {streams_parser, 0, [], [], [], [], false, false}, parse_streams_loop(Bytes, State, Additional_streams). -file("src/packkit/seven_z.gleam", 1175). -spec decode_encoded_header( bitstring(), bitstring(), gleam@option:option(binary()), packkit@limit:limits() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. decode_encoded_header(Bytes_after_nid, Full_archive, Password, Limits) -> gleam@result:'try'( parse_main_streams_info(Bytes_after_nid, []), fun(_use0) -> {Streams, _} = _use0, case Streams of header_streams_none -> {error, {archive_invalid, <<"7z encoded next header has no StreamsInfo"/utf8>>}}; {header_streams_parsed, Pack_pos, Pack_sizes, Folders, Folder_unpack_sizes, _} -> Pack_offset = 32 + Pack_pos, Pack_size = sum_list(Pack_sizes, 0), gleam@result:'try'( slice_required( Full_archive, Pack_offset, Pack_size, <<"7z encoded-header packed bytes"/utf8>> ), fun(Packed) -> decode_all_folders( Packed, Folders, Folder_unpack_sizes, Pack_sizes, Password, Limits, 0, [] ) end ) end end ). -file("src/packkit/seven_z.gleam", 603). -spec build_encoded_next_header_for_aes( integer(), integer(), bitstring(), integer() ) -> bitstring(). build_encoded_next_header_for_aes( Pack_pos, Pack_size, Aes_coder_def, Plain_header_size ) -> Pack_info = gleam_stdlib:bit_array_concat( [<<16#06>>, write_varint(Pack_pos), write_varint(1), <<16#09>>, write_varint(Pack_size), <<16#00>>] ), Folder_def = gleam_stdlib:bit_array_concat( [write_varint(1), <<16#00>>, write_varint(1), Aes_coder_def] ), Unpack_info = gleam_stdlib:bit_array_concat( [<<16#07>>, <<16#0B>>, Folder_def, <<16#0C>>, write_varint(Plain_header_size), <<16#00>>] ), gleam_stdlib:bit_array_concat( [<<16#17>>, Pack_info, Unpack_info, <<16#00>>] ). -file("src/packkit/seven_z.gleam", 566). -spec maybe_encrypt_next_header( bitstring(), integer(), gleam@option:option(encryption_spec()) ) -> {ok, {bitstring(), bitstring()}} | {error, packkit@error:archive_error()}. maybe_encrypt_next_header( Plain_next_header, Payload_pack_size, Header_encryption ) -> case Header_encryption of none -> {ok, {<<>>, Plain_next_header}}; {some, Spec} -> gleam@result:'try'( derive_aes_key( erlang:element(2, Spec), erlang:element(3, Spec), erlang:element(5, Spec) ), fun(Key) -> gleam@result:'try'( aes_cbc_encrypt( Plain_next_header, Key, erlang:element(4, Spec) ), fun(Encrypted_header) -> Plain_size = erlang:byte_size(Plain_next_header), Encrypted_size = erlang:byte_size(Encrypted_header), gleam@result:'try'( build_aes_coder_def(Spec), fun(Aes_coder_def) -> Encoded_next_header = build_encoded_next_header_for_aes( Payload_pack_size, Encrypted_size, Aes_coder_def, Plain_size ), {ok, {Encrypted_header, Encoded_next_header}} end ) end ) end ) end. -file("src/packkit/seven_z.gleam", 2461). -spec unix_to_filetime(integer()) -> integer(). unix_to_filetime(Unix_seconds) -> (Unix_seconds + 11644473600) * 10000000. -file("src/packkit/seven_z.gleam", 915). -spec build_mtime_block(list(integer())) -> bitstring(). build_mtime_block(Mtimes_unix) -> Defined_flags = gleam@list:map(Mtimes_unix, fun(M) -> M > 0 end), All_defined = gleam@list:all(Defined_flags, fun(B) -> B end), Num_files = erlang:length(Mtimes_unix), Filetime_payload = gleam@list:fold( Mtimes_unix, <<>>, fun(Acc, M@1) -> case M@1 > 0 of true -> Ft = unix_to_filetime(M@1), gleam_stdlib:bit_array_concat([Acc, <<Ft:64/little>>]); false -> Acc end end ), Body = case All_defined of true -> gleam_stdlib:bit_array_concat([<<16#01, 16#00>>, Filetime_payload]); false -> Bitmap = pack_bool_bits(Defined_flags, Num_files), gleam_stdlib:bit_array_concat( [<<16#00, 16#00>>, Bitmap, Filetime_payload] ) end, gleam_stdlib:bit_array_concat( [<<16#14>>, write_varint(erlang:byte_size(Body)), Body] ). -file("src/packkit/seven_z.gleam", 416). -spec encode_entries( list(packkit@entry:entry()), method(), gleam@option:option(encryption_spec()), gleam@option:option(encryption_spec()) ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_entries(Entries, Method, Encryption, Header_encryption) -> gleam@result:'try'( validate_entries_for_encode(Entries), fun(_) -> Bodies = gleam@list:map(Entries, fun packkit@entry:body/1), Names = gleam@list:map( Entries, fun(E) -> packkit@entry:to_string(packkit@entry:path(E)) end ), Unpack_sizes = gleam@list:map(Bodies, fun erlang:byte_size/1), Total_unpack = sum_list(Unpack_sizes, 0), Concatenated = gleam_stdlib:bit_array_concat(Bodies), gleam@result:'try'( encode_via_method(Concatenated, Method), fun(_use0) -> {Inner_packed, Inner_coder_def} = _use0, Inner_packed_size = erlang:byte_size(Inner_packed), gleam@result:'try'( maybe_wrap_with_aes( Inner_packed, Inner_coder_def, Inner_packed_size, Total_unpack, Encryption ), fun(_use0@1) -> {Packed, Folder_inner} = _use0@1, Pack_size = erlang:byte_size(Packed), Pack_info_body = gleam_stdlib:bit_array_concat( [write_varint(0), write_varint(1), <<16#09>>, write_varint(Pack_size), <<16#00>>] ), Pack_info = <<16#06, Pack_info_body/bitstring>>, Folder_def = gleam_stdlib:bit_array_concat( [write_varint(1), <<16#00>>, erlang:element(2, Folder_inner)] ), Unpack_info_body = gleam_stdlib:bit_array_concat( [<<16#0B>>, Folder_def, <<16#0C>>, erlang:element(3, Folder_inner), <<16#00>>] ), Unpack_info = <<16#07, Unpack_info_body/bitstring>>, Sub_streams_info = case Entries of [_] -> <<>>; _ -> build_sub_streams_info(Unpack_sizes) end, Main_streams = gleam_stdlib:bit_array_concat( [<<16#04>>, Pack_info, Unpack_info, Sub_streams_info, <<16#00>>] ), gleam@result:'try'( encode_names_block(Names), fun(Names_block) -> Num_files = erlang:length(Entries), Mtimes_unix = gleam@list:map( Entries, fun(E@1) -> packkit@entry:modified_at_unix( packkit@entry:metadata(E@1) ) end ), Any_mtime_set = gleam@list:any( Mtimes_unix, fun(M) -> M > 0 end ), Mtime_block = case Any_mtime_set of true -> build_mtime_block(Mtimes_unix); false -> <<>> end, Files_info = gleam_stdlib:bit_array_concat( [<<16#05>>, write_varint(Num_files), <<16#11>>, write_varint( erlang:byte_size(Names_block) ), Names_block, Mtime_block, <<16#00>>] ), Plain_next_header = gleam_stdlib:bit_array_concat( [<<16#01>>, Main_streams, Files_info, <<16#00>>] ), gleam@result:'try'( maybe_encrypt_next_header( Plain_next_header, Pack_size, Header_encryption ), fun(_use0@2) -> {Post_pack_bytes, Final_next_header} = _use0@2, Final_next_header_size = erlang:byte_size( Final_next_header ), Final_next_header_crc = packkit@checksum:crc32( Final_next_header ), Final_next_header_offset = Pack_size + erlang:byte_size(Post_pack_bytes), Post_signature_20 = <<Final_next_header_offset:64/little, Final_next_header_size:64/little, Final_next_header_crc:32/little>>, Start_crc = packkit@checksum:crc32( Post_signature_20 ), Signature_header = gleam_stdlib:bit_array_concat( [<<16#37, 16#7A, 16#BC, 16#AF, 16#27, 16#1C>>, <<16#00, 16#04>>, <<Start_crc:32/little>>, Post_signature_20] ), {ok, gleam_stdlib:bit_array_concat( [Signature_header, Packed, Post_pack_bytes, Final_next_header] )} end ) end ) end ) end ) end ). -file("src/packkit/seven_z.gleam", 399). -spec do_encode( packkit@archive:archive(), method(), gleam@option:option(encryption_spec()), gleam@option:option(encryption_spec()) ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. do_encode(Archive_value, Method, Encryption, Header_encryption) -> Entries = packkit@archive:entries(Archive_value), case Entries of [] -> {error, {archive_entry_rejected, <<"<archive>"/utf8>>, <<"7z encoder requires at least one entry"/utf8>>}}; _ -> encode_entries(Entries, Method, Encryption, Header_encryption) end. -file("src/packkit/seven_z.gleam", 292). ?DOC( " Same as `encode/1` but lets the caller pick the coder. All four\n" " methods produce a single-folder, single-coder archive — Copy is\n" " just the raw bytes; Deflate / BZip2 / LZMA dispatch to the\n" " corresponding packkit codec. Cross-method round-trips work\n" " because the decoder accepts each of these coder ids.\n" ). -spec encode_with_method(packkit@archive:archive(), method()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_with_method(Archive_value, Method) -> do_encode(Archive_value, Method, none, none). -file("src/packkit/seven_z.gleam", 281). ?DOC( " Encode a logical archive to a 7z byte stream.\n" "\n" " The encoder produces a single-folder, single-coder archive that\n" " uses a raw LZMA1 coder for the packed stream. All file bodies are\n" " concatenated into one logical substream which is then fed to\n" " `packkit/internal/lzma.encode_literal_only`; if the archive holds\n" " more than one entry, the per-substream sizes are emitted via\n" " `SubStreamsInfo` so the standard decoder can split the decompressed\n" " bytes back into individual entries.\n" "\n" " Restrictions: only `File` entries are accepted (no directories,\n" " symlinks, or hardlinks — these would require the `EmptyStream` /\n" " `Attribute` / `WinAttributes` blocks the reader does not yet\n" " validate). Empty archives are rejected because the 7z format\n" " requires `MainStreamsInfo` to be present once a `Header` block\n" " exists.\n" ). -spec encode(packkit@archive:archive()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode(Archive_value) -> encode_with_method(Archive_value, lzma()). -file("src/packkit/seven_z.gleam", 334). ?DOC( " Same as `encode_with_password` but lets the caller pick the inner\n" " coder (Copy / Deflate / BZip2 / LZMA). Salt + IV are still empty /\n" " all-zero — see `encode_with_password` for the determinism caveat.\n" ). -spec encode_with_password_and_method( packkit@archive:archive(), binary(), method() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_with_password_and_method(Archive_value, Password, Method) -> do_encode( Archive_value, Method, {some, default_encryption_spec(Password)}, none ). -file("src/packkit/seven_z.gleam", 320). ?DOC( " Encode a logical archive to a 7z byte stream with AES-256-CBC\n" " payload encryption (coder id `06 F1 07 01`). Plumbed into the\n" " folder as a 2-coder chain `[AES, <method>]` so the existing\n" " `decode_with_password` path reads it back verbatim.\n" "\n" " The encoder uses **empty salt** and **a 16-byte all-zero IV** for\n" " determinism — without an FFI into a platform CSPRNG there is no\n" " good source of randomness in pure Gleam. This is fine for\n" " archives that go to a trusted recipient over an authenticated\n" " channel, but it is NOT a substitute for randomised encryption —\n" " two archives encrypted with the same password produce identical\n" " ciphertext blocks for identical plaintext prefixes, which leaks\n" " information about the payload. If you need randomised\n" " encryption, encrypt the payload yourself before passing it in or\n" " pre-generate a 16-byte IV from a CSPRNG and feed it back through\n" " a future BYO-IV API.\n" "\n" " The inner coder defaults to LZMA — matching what `7z a -p<pw>`\n" " emits — and the key derivation runs the canonical 2^19 = 524288\n" " SHA-256 iterations, which on the JS target is slow (multiple\n" " seconds per archive).\n" ). -spec encode_with_password(packkit@archive:archive(), binary()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_with_password(Archive_value, Password) -> encode_with_password_and_method(Archive_value, Password, lzma()). -file("src/packkit/seven_z.gleam", 372). ?DOC( " Like `encode_with_password_and_header_encryption` but lets the\n" " caller pick the inner coder for the *payload*. The header is\n" " always wrapped in just AES (no inner method).\n" ). -spec encode_with_password_and_header_encryption_and_method( packkit@archive:archive(), binary(), method() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_with_password_and_header_encryption_and_method( Archive_value, Password, Method ) -> Spec = default_encryption_spec(Password), do_encode(Archive_value, Method, {some, Spec}, {some, Spec}). -file("src/packkit/seven_z.gleam", 358). ?DOC( " Encode an archive with both the payload AND the next-header bytes\n" " AES-encrypted — the on-disk equivalent of `7z a -p<pw> -mhe=on`.\n" " The signature header points at an \"encoded next header\" (NID 0x17)\n" " whose StreamsInfo block tells the decoder where the AES-encrypted\n" " next-header pack lives; the next header itself is plain bytes\n" " AES-CBC-encrypted with the user's password (no inner compression\n" " — the header is small enough that LZMA isn't worth the dispatch\n" " cost).\n" "\n" " The same determinism caveat as `encode_with_password` applies: salt\n" " is empty and IV is all zeros.\n" ). -spec encode_with_password_and_header_encryption( packkit@archive:archive(), binary() ) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_with_password_and_header_encryption(Archive_value, Password) -> encode_with_password_and_header_encryption_and_method( Archive_value, Password, lzma() ). -file("src/packkit/seven_z.gleam", 2465). -spec filetime_to_unix(integer()) -> integer(). filetime_to_unix(Filetime) -> (case 10000000 of 0 -> 0; Gleam@denominator -> Filetime div Gleam@denominator end) - 11644473600. -file("src/packkit/seven_z.gleam", 2528). -spec read_mtime_filetimes( bitstring(), list(boolean()), list(gleam@option:option(integer())) ) -> {ok, list(gleam@option:option(integer()))} | {error, packkit@error:archive_error()}. read_mtime_filetimes(Payload, Defined_flags, Acc) -> case Defined_flags of [] -> {ok, lists:reverse(Acc)}; [false | Rest] -> read_mtime_filetimes(Payload, Rest, [none | Acc]); [true | Rest@1] -> case Payload of <<Filetime:64/little, Tail/binary>> -> Unix_seconds = filetime_to_unix(Filetime), Safe = case Unix_seconds < 0 of true -> 0; false -> Unix_seconds end, read_mtime_filetimes(Tail, Rest@1, [{some, Safe} | Acc]); _ -> {error, {archive_invalid, <<"truncated 7z mtime FILETIME entry"/utf8>>}} end end. -file("src/packkit/seven_z.gleam", 4106). -spec consume_one_file_body( bitstring(), binary(), list(binary()), list(boolean()), list(boolean()), gleam@option:option(integer()), list(gleam@option:option(integer())), list(integer()), integer(), list(packkit@entry:entry()), packkit@limit:limits() ) -> {ok, list(packkit@entry:entry())} | {error, packkit@error:archive_error()}. consume_one_file_body( Plain, Name, Rest_names, Rest_empties, Empty_files, Entry_mtime, Rest_mtimes, Sizes, Consumed, Acc, Limits ) -> {This_size, Next_sizes} = case Sizes of [S | Rest] -> {S, Rest}; [] -> {erlang:byte_size(Plain) - Consumed, []} end, Body@1 = case gleam_stdlib:bit_array_slice(Plain, Consumed, This_size) of {ok, Body} -> Body; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <<?FILEPATH/utf8>>, module => <<"packkit/seven_z"/utf8>>, function => <<"consume_one_file_body"/utf8>>, line => 4126, value => _assert_fail, start => 133389, 'end' => 133454, pattern_start => 133400, pattern_end => 133408}) end, _pipe = add_file(Name, Body@1, Entry_mtime, Acc, Limits), gleam@result:'try'( _pipe, fun(New_acc) -> build_entries_loop( Plain, Rest_names, Rest_empties, Empty_files, Rest_mtimes, Next_sizes, Consumed + This_size, New_acc, Limits ) end ). -file("src/packkit/seven_z.gleam", 4024). -spec build_entries_loop( bitstring(), list(binary()), list(boolean()), list(boolean()), list(gleam@option:option(integer())), list(integer()), integer(), list(packkit@entry:entry()), packkit@limit:limits() ) -> {ok, list(packkit@entry:entry())} | {error, packkit@error:archive_error()}. build_entries_loop( Plain, Names, Empties, Empty_files, Mtimes, Sizes, Consumed, Acc, Limits ) -> {Entry_mtime, Rest_mtimes} = case Mtimes of [M | Rest] -> {M, Rest}; [] -> {none, []} end, case {Names, Empties} of {[], _} -> {ok, lists:reverse(Acc)}; {[Name | Rest_names], [Is_empty | Rest_empties]} -> case Is_empty of true -> {Is_file, Rest_empty_files} = case Empty_files of [Bit | Rest@1] -> {Bit, Rest@1}; [] -> {false, []} end, Adder = case Is_file of true -> add_file(Name, <<>>, Entry_mtime, Acc, Limits); false -> add_directory(Name, Entry_mtime, Acc, Limits) end, _pipe = Adder, gleam@result:'try'( _pipe, fun(New_acc) -> build_entries_loop( Plain, Rest_names, Rest_empties, Rest_empty_files, Rest_mtimes, Sizes, Consumed, New_acc, Limits ) end ); false -> consume_one_file_body( Plain, Name, Rest_names, Rest_empties, Empty_files, Entry_mtime, Rest_mtimes, Sizes, Consumed, Acc, Limits ) end; {[Name@1 | Rest_names@1], []} -> consume_one_file_body( Plain, Name@1, Rest_names@1, [], Empty_files, Entry_mtime, Rest_mtimes, Sizes, Consumed, Acc, Limits ) end. -file("src/packkit/seven_z.gleam", 3973). -spec build_archive_entries( bitstring(), parsed_header(), packkit@limit:limits() ) -> {ok, packkit@archive:archive()} | {error, packkit@error:archive_error()}. build_archive_entries(Plain, Parsed, Limits) -> Substream_sizes = case erlang:element(6, Parsed) of [] -> derive_substream_sizes_from_folders(erlang:element(5, Parsed)); Values -> Values end, _pipe = build_entries_loop( Plain, erlang:element(7, Parsed), erlang:element(8, Parsed), erlang:element(9, Parsed), erlang:element(10, Parsed), Substream_sizes, 0, [], Limits ), gleam@result:map( _pipe, fun(Entries) -> packkit@archive:from_entries(format(), Entries) end ). -file("src/packkit/seven_z.gleam", 2884). -spec decode_archive( bitstring(), parsed_header(), gleam@option:option(binary()), packkit@limit:limits() ) -> {ok, packkit@archive:archive()} | {error, packkit@error:archive_error()}. decode_archive(Packed, Parsed, Password, Limits) -> gleam@result:'try'( enforce_max_output(lists:append(erlang:element(5, Parsed)), Limits), fun(_) -> Declared_members = erlang:length(erlang:element(7, Parsed)), gleam@bool:guard( Declared_members > packkit@limit:max_members(Limits), {error, {archive_limit_exceeded, <<"max_members"/utf8>>, Declared_members}}, fun() -> gleam@result:'try'( decode_all_folders( Packed, erlang:element(4, Parsed), erlang:element(5, Parsed), erlang:element(3, Parsed), Password, Limits, erlang:element(2, Parsed), [] ), fun(Plain) -> build_archive_entries(Plain, Parsed, Limits) end ) end ) end ). -file("src/packkit/seven_z.gleam", 2675). -spec take_bools(list(boolean()), bitstring(), integer(), list(boolean())) -> list(boolean()). take_bools(Bits, Rest_bytes, Count, Acc) -> case {Bits, Count} of {_, 0} -> lists:reverse(Acc); {[], _} -> bit_array_to_bool_list(Rest_bytes, Count, Acc); {[Head | Tail], _} -> take_bools(Tail, Rest_bytes, Count - 1, [Head | Acc]) end. -file("src/packkit/seven_z.gleam", 2647). -spec bit_array_to_bool_list(bitstring(), integer(), list(boolean())) -> list(boolean()). bit_array_to_bool_list(Bytes, Count, Acc) -> case Count of 0 -> lists:reverse(Acc); _ -> case Bytes of <<B, Rest/binary>> -> Bits = unpack_bits(B, 8, []), take_bools(Bits, Rest, Count, Acc); _ -> lists:reverse(Acc) end end. -file("src/packkit/seven_z.gleam", 2514). -spec read_mtime_defined_flags(bitstring(), integer()) -> {ok, list(boolean())} | {error, packkit@error:archive_error()}. read_mtime_defined_flags(Payload, Num_files) -> Bitmap_size = (Num_files + 7) div 8, gleam@result:'try'( slice_required( Payload, 0, Bitmap_size, <<"7z mtime defined bitmap"/utf8>> ), fun(Bits) -> {ok, bit_array_to_bool_list(Bits, Num_files, [])} end ). -file("src/packkit/seven_z.gleam", 2469). -spec parse_mtime_block(bitstring(), integer(), list(bitstring())) -> {ok, list(gleam@option:option(integer()))} | {error, packkit@error:archive_error()}. parse_mtime_block(Payload, Num_files, Additional_streams) -> case Payload of <<All_defined, External, After_header/binary>> -> gleam@result:'try'(case External of 0 -> {ok, After_header}; _ -> gleam@result:'try'( read_number(After_header), fun(_use0) -> {Data_index, _} = _use0, get_additional_stream( Additional_streams, Data_index ) end ) end, fun(External_bytes) -> gleam@result:'try'(case All_defined of 1 -> {ok, gleam@list:repeat(true, Num_files)}; _ -> read_mtime_defined_flags( External_bytes, Num_files ) end, fun(Defined_flags) -> Body_after_flags = case All_defined of 1 -> External_bytes; _ -> Bitmap_size = (Num_files + 7) div 8, Rest@1 = case gleam_stdlib:bit_array_slice( External_bytes, Bitmap_size, erlang:byte_size(External_bytes) - Bitmap_size ) of {ok, Rest} -> Rest; _assert_fail -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <<?FILEPATH/utf8>>, module => <<"packkit/seven_z"/utf8>>, function => <<"parse_mtime_block"/utf8>>, line => 2499, value => _assert_fail, start => 80739, 'end' => 80925, pattern_start => 80750, pattern_end => 80758} ) end, Rest@1 end, read_mtime_filetimes( Body_after_flags, Defined_flags, [] ) end) end); _ -> {error, {archive_invalid, <<"truncated 7z mtime block header"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 2246). -spec parse_files_loop( bitstring(), integer(), list(binary()), list(boolean()), list(boolean()), list(gleam@option:option(integer())), list(bitstring()) ) -> {ok, {header_files(), bitstring()}} | {error, packkit@error:archive_error()}. parse_files_loop( Bytes, Num_files, Names, Empty_streams, Empty_files, Mtimes_unix, Additional_streams ) -> case Bytes of <<Nid, Rest/binary>> -> case Nid of N when N =:= 16#00 -> {ok, {{header_files_parsed, case Names of [] -> dummy_names(Num_files); Ns -> Ns end, case Empty_streams of [] -> gleam@list:repeat(false, Num_files); Es -> Es end, Empty_files, Mtimes_unix}, Rest}}; N@1 when N@1 =:= 16#11 -> gleam@result:'try'( read_number(Rest), fun(_use0) -> {Size, After_size} = _use0, gleam@result:'try'( slice_required( After_size, 0, Size, <<"7z file names payload"/utf8>> ), fun(Payload) -> After_payload@1 = case gleam_stdlib:bit_array_slice( After_size, Size, erlang:byte_size(After_size) - Size ) of {ok, After_payload} -> After_payload; _assert_fail -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <<?FILEPATH/utf8>>, module => <<"packkit/seven_z"/utf8>>, function => <<"parse_files_loop"/utf8>>, line => 2282, value => _assert_fail, start => 73382, 'end' => 73555, pattern_start => 73393, pattern_end => 73410} ) end, gleam@result:'try'( parse_name_block( Payload, Num_files, Additional_streams ), fun(Parsed_names) -> parse_files_loop( After_payload@1, Num_files, Parsed_names, Empty_streams, Empty_files, Mtimes_unix, Additional_streams ) end ) end ) end ); N@2 when N@2 =:= 16#0E -> gleam@result:'try'( read_number(Rest), fun(_use0@1) -> {Size@1, After_size@1} = _use0@1, gleam@result:'try'( slice_required( After_size@1, 0, Size@1, <<"7z empty-stream payload"/utf8>> ), fun(Payload@1) -> After_payload@3 = case gleam_stdlib:bit_array_slice( After_size@1, Size@1, erlang:byte_size(After_size@1) - Size@1 ) of {ok, After_payload@2} -> After_payload@2; _assert_fail@1 -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <<?FILEPATH/utf8>>, module => <<"packkit/seven_z"/utf8>>, function => <<"parse_files_loop"/utf8>>, line => 2311, value => _assert_fail@1, start => 74217, 'end' => 74390, pattern_start => 74228, pattern_end => 74245} ) end, Flags = bit_array_to_bool_list( Payload@1, Num_files, [] ), parse_files_loop( After_payload@3, Num_files, Names, Flags, Empty_files, Mtimes_unix, Additional_streams ) end ) end ); N@3 when N@3 =:= 16#0F -> gleam@result:'try'( read_number(Rest), fun(_use0@2) -> {Size@2, After_size@2} = _use0@2, gleam@result:'try'( slice_required( After_size@2, 0, Size@2, <<"7z empty-file payload"/utf8>> ), fun(Payload@2) -> After_payload@5 = case gleam_stdlib:bit_array_slice( After_size@2, Size@2, erlang:byte_size(After_size@2) - Size@2 ) of {ok, After_payload@4} -> After_payload@4; _assert_fail@2 -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <<?FILEPATH/utf8>>, module => <<"packkit/seven_z"/utf8>>, function => <<"parse_files_loop"/utf8>>, line => 2343, value => _assert_fail@2, start => 75398, 'end' => 75571, pattern_start => 75409, pattern_end => 75426} ) end, Empty_count = count_true(Empty_streams), Flags@1 = bit_array_to_bool_list( Payload@2, Empty_count, [] ), parse_files_loop( After_payload@5, Num_files, Names, Empty_streams, Flags@1, Mtimes_unix, Additional_streams ) end ) end ); N@4 when N@4 =:= 16#14 -> gleam@result:'try'( read_number(Rest), fun(_use0@3) -> {Size@3, After_size@3} = _use0@3, gleam@result:'try'( slice_required( After_size@3, 0, Size@3, <<"7z mtime block payload"/utf8>> ), fun(Payload@3) -> After_payload@7 = case gleam_stdlib:bit_array_slice( After_size@3, Size@3, erlang:byte_size(After_size@3) - Size@3 ) of {ok, After_payload@6} -> After_payload@6; _assert_fail@3 -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <<?FILEPATH/utf8>>, module => <<"packkit/seven_z"/utf8>>, function => <<"parse_files_loop"/utf8>>, line => 2380, value => _assert_fail@3, start => 76856, 'end' => 77029, pattern_start => 76867, pattern_end => 76884} ) end, gleam@result:'try'( parse_mtime_block( Payload@3, Num_files, Additional_streams ), fun(Parsed_mtimes) -> parse_files_loop( After_payload@7, Num_files, Names, Empty_streams, Empty_files, Parsed_mtimes, Additional_streams ) end ) end ) end ); N@5 when ((((((N@5 =:= 16#19) orelse (N@5 =:= 16#12)) orelse (N@5 =:= 16#13)) orelse (N@5 =:= 16#15)) orelse (N@5 =:= 16#10)) orelse (N@5 =:= 16#18)) orelse (N@5 =:= 16#16) -> gleam@result:'try'( read_number(Rest), fun(_use0@4) -> {Size@4, After_size@4} = _use0@4, After_payload@9 = case gleam_stdlib:bit_array_slice( After_size@4, Size@4, erlang:byte_size(After_size@4) - Size@4 ) of {ok, After_payload@8} -> After_payload@8; _assert_fail@4 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <<?FILEPATH/utf8>>, module => <<"packkit/seven_z"/utf8>>, function => <<"parse_files_loop"/utf8>>, line => 2411, value => _assert_fail@4, start => 77720, 'end' => 77893, pattern_start => 77731, pattern_end => 77748}) end, parse_files_loop( After_payload@9, Num_files, Names, Empty_streams, Empty_files, Mtimes_unix, Additional_streams ) end ); _ -> {error, {archive_invalid, <<"unexpected 7z FilesInfo NID "/utf8, (erlang:integer_to_binary(Nid))/binary>>}} end; _ -> {error, {archive_invalid, <<"truncated 7z FilesInfo"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 2238). -spec parse_files_info(bitstring(), list(bitstring())) -> {ok, {header_files(), bitstring()}} | {error, packkit@error:archive_error()}. parse_files_info(Bytes, Additional_streams) -> gleam@result:'try'( read_number(Bytes), fun(_use0) -> {Num_files, Rest} = _use0, parse_files_loop( Rest, Num_files, [], [], [], [], Additional_streams ) end ). -file("src/packkit/seven_z.gleam", 1415). -spec parse_header_body( bitstring(), header_parser(), bitstring(), packkit@limit:limits() ) -> {ok, header_parser()} | {error, packkit@error:archive_error()}. parse_header_body(Bytes, Parser, Full_archive, Limits) -> case Bytes of <<Nid, Rest/binary>> -> case Nid of N when N =:= 16#00 -> {ok, Parser}; N@1 when N@1 =:= 16#04 -> gleam@result:'try'( parse_main_streams_info(Rest, erlang:element(2, Parser)), fun(_use0) -> {Streams, Rest@1} = _use0, parse_header_body( Rest@1, {header_parser, erlang:element(2, Parser), Streams, erlang:element(4, Parser)}, Full_archive, Limits ) end ); N@2 when N@2 =:= 16#05 -> gleam@result:'try'( parse_files_info(Rest, erlang:element(2, Parser)), fun(_use0@1) -> {Files, Rest@2} = _use0@1, parse_header_body( Rest@2, {header_parser, erlang:element(2, Parser), erlang:element(3, Parser), Files}, Full_archive, Limits ) end ); N@3 when N@3 =:= 16#03 -> gleam@result:'try'( parse_main_streams_info(Rest, []), fun(_use0@2) -> {Streams_info, Rest@3} = _use0@2, gleam@result:'try'( decode_additional_streams( Streams_info, Full_archive, Limits ), fun(Decoded) -> parse_header_body( Rest@3, {header_parser, Decoded, erlang:element(3, Parser), erlang:element(4, Parser)}, Full_archive, Limits ) end ) end ); N@4 when N@4 =:= 16#02 -> {error, {archive_not_implemented, <<"7z ArchiveProperties (NID 0x02)"/utf8>>}}; _ -> {error, {archive_invalid, <<"unexpected 7z header NID "/utf8, (erlang:integer_to_binary(Nid))/binary>>}} end; _ -> {ok, Parser} end. -file("src/packkit/seven_z.gleam", 1352). -spec parse_header(bitstring(), bitstring(), packkit@limit:limits()) -> {ok, parsed_header()} | {error, packkit@error:archive_error()}. parse_header(Header, Full_archive, Limits) -> case Header of <<Head_nid, Rest/binary>> when Head_nid =:= 16#01 -> Parser = {header_parser, [], header_streams_none, header_files_none}, gleam@result:'try'( parse_header_body(Rest, Parser, Full_archive, Limits), fun(Parser@1) -> finalize_parsed_header(Parser@1) end ); _ -> {error, {archive_invalid, <<"7z header must start with the Header NID"/utf8>>}} end. -file("src/packkit/seven_z.gleam", 1136). -spec decode_internal( bitstring(), gleam@option:option(binary()), packkit@limit:limits() ) -> {ok, packkit@archive:archive()} | {error, packkit@error:archive_error()}. decode_internal(Bytes, Password, Limits) -> gleam@bool:guard( erlang:byte_size(Bytes) > packkit@limit:max_input_bytes(Limits), {error, {archive_limit_exceeded, <<"max_input_bytes"/utf8>>, erlang:byte_size(Bytes)}}, fun() -> gleam@result:'try'( parse_signature_header(Bytes), fun(_use0) -> {Next_offset, Next_size, _} = _use0, gleam@result:'try'( slice_required( Bytes, 32, Next_offset, <<"7z packed streams region"/utf8>> ), fun(Packed_streams) -> gleam@result:'try'( slice_required( Bytes, 32 + Next_offset, Next_size, <<"7z next header"/utf8>> ), fun(Next_header_bytes) -> gleam@result:'try'(case Next_header_bytes of <<N, Rest/binary>> when N =:= 16#17 -> decode_encoded_header( Rest, Bytes, Password, Limits ); _ -> {ok, Next_header_bytes} end, fun(Header) -> gleam@result:'try'( parse_header( Header, Bytes, Limits ), fun(Parsed) -> decode_archive( Packed_streams, Parsed, Password, Limits ) end ) end) end ) end ) end ) end ). -file("src/packkit/seven_z.gleam", 1094). ?DOC(" Decode a 7z byte stream using the default limits.\n"). -spec decode(bitstring()) -> {ok, packkit@archive:archive()} | {error, packkit@error:archive_error()}. decode(Bytes) -> decode_internal(Bytes, none, packkit@limit:default()). -file("src/packkit/seven_z.gleam", 1105). ?DOC( " Decode a 7z byte stream using explicit limits. Enforces\n" " `max_input_bytes` at entry, `max_output_bytes` against the\n" " declared unpack size before invoking the LZMA/LZMA2 decoder,\n" " and `max_members` / `max_entry_depth` while materialising the\n" " logical entry list.\n" ). -spec decode_with_limits(bitstring(), packkit@limit:limits()) -> {ok, packkit@archive:archive()} | {error, packkit@error:archive_error()}. decode_with_limits(Bytes, Limits) -> decode_internal(Bytes, none, Limits). -file("src/packkit/seven_z.gleam", 1120). ?DOC( " Decode a 7z byte stream that contains an AES-256 encrypted folder.\n" " `password` is applied to every AES-coded folder via the SHA-256\n" " key-derivation routine p7zip uses (`numCyclesPower` rounds of\n" " `sha256(salt || utf16le(password) || u64_le(counter))`); folders\n" " without an AES coder decode unchanged. A wrong password produces\n" " garbage plaintext that the downstream coder (typically LZMA2)\n" " rejects with the usual typed `ArchiveInvalid` error — there's no\n" " authentication tag on the AES layer.\n" ). -spec decode_with_password(bitstring(), binary()) -> {ok, packkit@archive:archive()} | {error, packkit@error:archive_error()}. decode_with_password(Bytes, Password) -> decode_internal(Bytes, {some, Password}, packkit@limit:default()). -file("src/packkit/seven_z.gleam", 1128). ?DOC(" Same as `decode_with_password` but with explicit limits.\n"). -spec decode_with_password_and_limits( bitstring(), binary(), packkit@limit:limits() ) -> {ok, packkit@archive:archive()} | {error, packkit@error:archive_error()}. decode_with_password_and_limits(Bytes, Password, Limits) -> decode_internal(Bytes, {some, Password}, Limits).