Skip to main content

src/packkit@seven_z.erl

-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, <<Current_byte>>])
            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, <<Updated_byte>>])
                    );

                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,
                        <<Acc/bitstring, Low, High>>,
                        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, <<Body/bitstring, 0, 0>>} 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, <<Acc/bitstring, Byte>>)
    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, <<>>),
    <<First_byte, Trailer_bytes/bitstring>>.

-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
        <<B, Rest/binary>> ->
            describe_bit_array_hex(
                Rest,
                <<Acc/binary, (gleam@int:to_base16(B))/binary>>
            );

        _ ->
            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 ->
            <<Acc/bitstring, C>>;

        C@1 when C@1 < 16#800 ->
            B1 = 16#C0 + erlang:'bsr'(C@1, 6),
            B2 = 16#80 + erlang:'band'(C@1, 16#3F),
            <<Acc/bitstring, B1, B2>>;

        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),
            <<Acc/bitstring, B1@1, B2@1, B3>>
    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
                <<Lo, Hi, Rest/binary>> ->
                    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 => <<?FILEPATH/utf8>>,
                                                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
        <<All_defined, Rest/binary>> ->
            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
        <<B, Rest/binary>> ->
            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, <<Acc/bitstring, B>>)
    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 = <<Counter:64/little>>,
            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,
        <<Acc/bitstring, Scalar:16/little>>,
        fun() ->
            Adjusted = Scalar - 16#10000,
            High = 16#D800 + erlang:'bsr'(Adjusted, 10),
            Low = 16#DC00 + erlang:'band'(Adjusted, 16#3FF),
            <<Acc/bitstring, High:16/little, Low:16/little>>
        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 ->
            <<Iv/bitstring, 0:(lists:max([(((16 - Size) * 8)), 0]))>>;

        _ ->
            _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
        {<<Left_byte, Left_rest/binary>>, <<Right_byte, Right_rest/binary>>} ->
            xor_bit_arrays_loop(
                Left_rest,
                Right_rest,
                <<Acc/bitstring, (erlang:'bxor'(Left_byte, Right_byte))>>
            );

        {_, _} ->
            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};

        <<Block:16/binary, Rest/binary>> ->
            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,
                        <<Acc/bitstring, Ciphertext_block/bitstring>>
                    )
                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};

        <<Block:16/binary, Rest/binary>> ->
            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,
                        <<Acc/bitstring, Plaintext_block/bitstring>>
                    )
                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>> ->
            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};

        <<Control, _/binary>> 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;

        <<Control@1,
            Usize_high,
            Usize_low,
            Csize_high,
            Csize_low,
            Rest@1/binary>> 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
                        <<Props_byte, Rest_after_props/binary>> ->
                            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
        <<Props_byte, _/binary>> ->
            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
                        <<Byte, More/binary>> ->
                            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
        <<First, Rest/binary>> ->
            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
        <<External, Rest/binary>> ->
            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
        <<B>> when B =:= 16#00 ->
            {ok, copy};

        <<B@1>> when B@1 =:= 16#21 ->
            {ok, lzma2};

        <<B@2>> when B@2 =:= 16#03 ->
            {ok, delta};

        <<B1, B2, B3>> when ((B1 =:= 16#03) andalso (B2 =:= 16#01)) andalso (B3 =:= 16#01) ->
            {ok, lzma};

        <<B1@1, B2@1, B3@1>> when ((B1@1 =:= 16#04) andalso (B2@1 =:= 16#01)) andalso (B3@1 =:= 16#08) ->
            {ok, deflate};

        <<B1@2, B2@2, B3@2>> when ((B1@2 =:= 16#04) andalso (B2@2 =:= 16#02)) andalso (B3@2 =:= 16#02) ->
            {ok, b_zip2};

        <<B1@3, B2@3, B3@3, B4>> when (((B1@3 =:= 16#06) andalso (B2@3 =:= 16#F1)) andalso (B3@3 =:= 16#07)) andalso (B4 =:= 16#01) ->
            {ok, aes256_sha256};

        <<B1@4, B2@4, B3@4, B4@1>> when (((B1@4 =:= 16#03) andalso (B2@4 =:= 16#03)) andalso (B3@4 =:= 16#01)) andalso (B4@1 =:= 16#1B) ->
            {ok, bcj2};

        <<B1@5, B2@5, B3@5, B4@2>> 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
        <<Flags, After_flags/binary>> ->
            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
                        <<External, After_external/binary>> ->
                            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 = <<Plaintext/bitstring, Padding/bitstring>>,
    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).