-module(packkit@ar). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/packkit/ar.gleam"). -export([format/0, new/0, decode_with_limits/2, decode/1, encode/1]). -export_type([special_kind/0, parsed_record/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( " Unix `ar` archive encoder and decoder.\n" "\n" " The encoder emits the BSD long-name variant (`#1/N`) so it can\n" " carry archive entries whose paths exceed 16 bytes or contain\n" " spaces. The decoder additionally accepts the GNU long-name\n" " variant (a leading `//` string-table member plus `/`\n" " references in entry headers), which is the form produced by\n" " `binutils` ar and present in nearly every `.deb` / `.a` on\n" " Linux. GNU symbol-table members (named `/`) are skipped\n" " transparently so they do not show up as user-visible entries.\n" "\n" " Only regular file entries are supported - `ar` does not represent\n" " directories or symbolic links.\n" ). -type special_kind() :: regular_entry | symbol_table | string_table. -type parsed_record() :: {parsed_record, binary(), integer(), gleam@option:option(integer()), special_kind(), integer(), integer(), integer(), integer(), integer()}. -file("src/packkit/ar.gleam", 38). ?DOC(" AR archive format marker.\n"). -spec format() -> packkit@archive:archive_format(). format() -> packkit@archive:ar(). -file("src/packkit/ar.gleam", 43). ?DOC(" Create an empty AR archive value.\n"). -spec new() -> packkit@archive:archive(). new() -> packkit@archive:new(format()). -file("src/packkit/ar.gleam", 61). -spec reject_comment(packkit@archive:archive()) -> {ok, nil} | {error, packkit@error:archive_error()}. reject_comment(Archive_value) -> case packkit@archive:comment(Archive_value) of none -> {ok, nil}; {some, _} -> {error, {archive_comment_unsupported, <<"ar"/utf8>>}} end. -file("src/packkit/ar.gleam", 260). -spec find_gnu_terminator(bitstring(), integer(), integer()) -> integer(). find_gnu_terminator(Bytes, Pos, Len) -> case Pos >= Len of true -> Len; false -> case gleam_stdlib:bit_array_slice(Bytes, Pos, 1) of {ok, <<16#2F>>} -> Pos; {ok, <<16#00>>} -> Pos; {ok, <<16#0A>>} -> Pos; _ -> find_gnu_terminator(Bytes, Pos + 1, Len) end end. -file("src/packkit/ar.gleam", 274). -spec check_member_limit(integer(), packkit@limit:limits()) -> {ok, nil} | {error, packkit@error:archive_error()}. check_member_limit(Count, Limits) -> case Count > packkit@limit:max_members(Limits) of true -> {error, {archive_limit_exceeded, <<"max_members"/utf8>>, Count}}; false -> {ok, nil} end. -file("src/packkit/ar.gleam", 535). -spec pow_int_loop(integer(), integer(), integer()) -> integer(). pow_int_loop(Base, Exponent, Acc) -> case Exponent of 0 -> Acc; _ -> pow_int_loop(Base, Exponent - 1, Acc * Base) end. -file("src/packkit/ar.gleam", 531). -spec pow_int(integer(), integer()) -> integer(). pow_int(Base, Exponent) -> pow_int_loop(Base, Exponent, 1). -file("src/packkit/ar.gleam", 563). -spec byte_repeat_loop(integer(), integer(), bitstring()) -> bitstring(). byte_repeat_loop(Byte, Count, Acc) -> case Count of 0 -> Acc; _ -> byte_repeat_loop(Byte, Count - 1, <>) end. -file("src/packkit/ar.gleam", 559). -spec byte_repeat(integer(), integer()) -> bitstring(). byte_repeat(Byte, Count) -> byte_repeat_loop(Byte, Count, <<>>). -file("src/packkit/ar.gleam", 548). -spec right_pad(bitstring(), integer(), integer()) -> bitstring(). right_pad(Value, Width, Fill) -> Size = erlang:byte_size(Value), case Size >= Width of true -> Slice@1 = case gleam_stdlib:bit_array_slice(Value, 0, Width) of {ok, Slice} -> Slice; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/ar"/utf8>>, function => <<"right_pad"/utf8>>, line => 552, value => _assert_fail, start => 16047, 'end' => 16102, pattern_start => 16058, pattern_end => 16067}) end, Slice@1; false -> gleam_stdlib:bit_array_concat( [Value, byte_repeat(Fill, Width - Size)] ) end. -file("src/packkit/ar.gleam", 480). -spec text_field(binary(), integer()) -> bitstring(). text_field(Value, Width) -> Bytes = gleam_stdlib:identity(Value), right_pad(Bytes, Width, 16#20). -file("src/packkit/ar.gleam", 485). -spec decimal_field(integer(), integer()) -> bitstring(). decimal_field(Value, Width) -> Raw = erlang:integer_to_binary(Value), Raw_bits = gleam_stdlib:identity(Raw), right_pad(Raw_bits, Width, 16#20). -file("src/packkit/ar.gleam", 491). -spec checked_decimal_field(integer(), integer(), binary()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. checked_decimal_field(Value, Width, Field) -> Raw = erlang:integer_to_binary(Value), Raw_size = erlang:byte_size(Raw), case (Value < 0) orelse (Raw_size > Width) of true -> Max_value = pow_int(10, Width) - 1, {error, {archive_field_overflow, <<"ar "/utf8, Field/binary>>, Value, Max_value}}; false -> {ok, decimal_field(Value, Width)} end. -file("src/packkit/ar.gleam", 542). -spec octal_field(integer(), integer()) -> bitstring(). octal_field(Value, Width) -> Raw = gleam@int:to_base8(Value), Raw_bits = gleam_stdlib:identity(Raw), right_pad(Raw_bits, Width, 16#20). -file("src/packkit/ar.gleam", 511). -spec checked_octal_field(integer(), integer(), binary()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. checked_octal_field(Value, Width, Field) -> Raw = gleam@int:to_base8(Value), Raw_size = erlang:byte_size(Raw), case (Value < 0) orelse (Raw_size > Width) of true -> Max_value = pow_int(8, Width) - 1, {error, {archive_field_overflow, <<"ar "/utf8, Field/binary>>, Value, Max_value}}; false -> {ok, octal_field(Value, Width)} end. -file("src/packkit/ar.gleam", 608). -spec slice_or_error(bitstring(), integer(), integer()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. slice_or_error(Block, Offset, Width) -> case gleam_stdlib:bit_array_slice(Block, Offset, Width) of {ok, Value} -> {ok, Value}; {error, _} -> {error, {archive_invalid, <<"ar header field out of bounds"/utf8>>}} end. -file("src/packkit/ar.gleam", 620). -spec bytes_to_string(bitstring()) -> {ok, binary()} | {error, packkit@error:archive_error()}. bytes_to_string(Bytes) -> case gleam@bit_array:to_string(Bytes) of {ok, Value} -> {ok, Value}; {error, _} -> {error, {archive_invalid, <<"non-UTF-8 ar header string"/utf8>>}} end. -file("src/packkit/ar.gleam", 241). -spec gnu_string_at(bitstring(), integer()) -> {ok, binary()} | {error, packkit@error:archive_error()}. gnu_string_at(Table, Offset) -> Size = erlang:byte_size(Table), case (Offset < 0) orelse (Offset >= Size) of true -> {error, {archive_invalid, <<"ar GNU string table offset out of range"/utf8>>}}; false -> Tail@1 = case gleam_stdlib:bit_array_slice( Table, Offset, Size - Offset ) of {ok, Tail} -> Tail; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/ar"/utf8>>, function => <<"gnu_string_at"/utf8>>, line => 252, value => _assert_fail, start => 7860, 'end' => 7927, pattern_start => 7871, pattern_end => 7879}) end, End_index = find_gnu_terminator(Tail@1, 0, Size - Offset), Name_bits@1 = case gleam_stdlib:bit_array_slice( Tail@1, 0, End_index ) of {ok, Name_bits} -> Name_bits; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/ar"/utf8>>, function => <<"gnu_string_at"/utf8>>, line => 254, value => _assert_fail@1, start => 8000, 'end' => 8062, pattern_start => 8011, pattern_end => 8024}) end, bytes_to_string(Name_bits@1) end. -file("src/packkit/ar.gleam", 570). -spec read_decimal_field(bitstring(), integer(), integer()) -> {ok, integer()} | {error, packkit@error:archive_error()}. read_decimal_field(Block, Offset, Width) -> gleam@result:'try'( slice_or_error(Block, Offset, Width), fun(Slice) -> gleam@result:'try'( bytes_to_string(Slice), fun(Raw) -> Trimmed = gleam@string:trim(Raw), case Trimmed of <<""/utf8>> -> {ok, 0}; _ -> case gleam_stdlib:parse_int(Trimmed) of {ok, Value} -> {ok, Value}; {error, _} -> {error, {archive_invalid, <<"invalid decimal ar field"/utf8>>}} end end end ) end ). -file("src/packkit/ar.gleam", 589). -spec read_octal_field(bitstring(), integer(), integer()) -> {ok, integer()} | {error, packkit@error:archive_error()}. read_octal_field(Block, Offset, Width) -> gleam@result:'try'( slice_or_error(Block, Offset, Width), fun(Slice) -> gleam@result:'try'( bytes_to_string(Slice), fun(Raw) -> Trimmed = gleam@string:trim(Raw), case Trimmed of <<""/utf8>> -> {ok, 0}; _ -> case gleam@int:base_parse(Trimmed, 8) of {ok, Value} -> {ok, Value}; {error, _} -> {error, {archive_invalid, <<"invalid octal ar field"/utf8>>}} end end end ) end ). -file("src/packkit/ar.gleam", 628). -spec entry_error_to_archive_error(packkit@entry:entry_error(), binary()) -> packkit@error:archive_error(). entry_error_to_archive_error(Err, Path) -> case Err of empty_path -> {archive_entry_rejected, Path, <<"empty path"/utf8>>}; {absolute_path, _} -> {archive_entry_rejected, Path, <<"absolute path"/utf8>>}; {path_traversal, _} -> {archive_entry_rejected, Path, <<"path traversal"/utf8>>}; {windows_path, _} -> {archive_entry_rejected, Path, <<"windows path"/utf8>>}; {empty_segment, _} -> {archive_entry_rejected, Path, <<"empty segment"/utf8>>}; {dot_segment, _} -> {archive_entry_rejected, Path, <<"dot segment"/utf8>>}; {contains_nul, _} -> {archive_entry_rejected, Path, <<"nul byte"/utf8>>} end. -file("src/packkit/ar.gleam", 650). -spec strip_trailing_slash(binary()) -> binary(). strip_trailing_slash(Value) -> case gleam_stdlib:string_ends_with(Value, <<"/"/utf8>>) of true -> gleam@string:drop_end(Value, 1); false -> Value end. -file("src/packkit/ar.gleam", 662). -spec strip_trailing_nul_loop(bitstring(), integer()) -> bitstring(). strip_trailing_nul_loop(Bytes, Size) -> case Size of 0 -> <<>>; _ -> case gleam_stdlib:bit_array_slice(Bytes, Size - 1, 1) of {ok, <<0>>} -> strip_trailing_nul_loop(Bytes, Size - 1); _ -> Slice@1 = case gleam_stdlib:bit_array_slice(Bytes, 0, Size) of {ok, Slice} -> Slice; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/ar"/utf8>>, function => <<"strip_trailing_nul_loop"/utf8>>, line => 669, value => _assert_fail, start => 19250, 'end' => 19304, pattern_start => 19261, pattern_end => 19270}) end, Slice@1 end end. -file("src/packkit/ar.gleam", 657). -spec strip_trailing_nul(bitstring()) -> bitstring(). strip_trailing_nul(Bytes) -> Size = erlang:byte_size(Bytes), strip_trailing_nul_loop(Bytes, Size). -file("src/packkit/ar.gleam", 212). -spec resolve_entry_name( parsed_record(), bitstring(), integer(), gleam@option:option(bitstring()) ) -> {ok, binary()} | {error, packkit@error:archive_error()}. resolve_entry_name(Record, Bytes, After_header_offset, String_table) -> case {erlang:element(3, Record), erlang:element(4, Record)} of {N, _} when N > 0 -> gleam@result:'try'( slice_or_error( Bytes, After_header_offset, erlang:element(3, Record) ), fun(Ext_bits) -> bytes_to_string(strip_trailing_nul(Ext_bits)) end ); {_, {some, Offset}} -> case String_table of none -> {error, {archive_invalid, <<"ar entry references missing GNU string table"/utf8>>}}; {some, Table} -> gnu_string_at(Table, Offset) end; {_, none} -> {ok, erlang:element(2, Record)} end. -file("src/packkit/ar.gleam", 676). -spec min(integer(), integer()) -> integer(). min(A, B) -> case A < B of true -> A; false -> B end. -file("src/packkit/ar.gleam", 305). -spec parse_header(bitstring()) -> {ok, parsed_record()} | {error, packkit@error:archive_error()}. parse_header(Block) -> gleam@result:'try'( slice_or_error(Block, 0, 16), fun(Raw_name_bits) -> gleam@result:'try'( bytes_to_string(Raw_name_bits), fun(Raw_name) -> Trimmed_name = gleam@string:trim_end(Raw_name), gleam@result:'try'( read_decimal_field(Block, 16, 12), fun(Mtime) -> gleam@result:'try'( read_decimal_field(Block, 28, 6), fun(Uid) -> gleam@result:'try'( read_decimal_field(Block, 34, 6), fun(Gid) -> gleam@result:'try'( read_octal_field(Block, 40, 8), fun(Mode) -> gleam@result:'try'( read_decimal_field( Block, 48, 10 ), fun(Size) -> gleam@result:'try'( slice_or_error( Block, 58, 2 ), fun(Ending_bits) -> gleam@bool:guard( Ending_bits /= <<16#60, 16#0A>>, {error, {archive_invalid, <<"ar header marker missing"/utf8>>}}, fun() -> case Trimmed_name of <<"/"/utf8>> -> {ok, {parsed_record, Trimmed_name, 0, none, symbol_table, Mtime, Uid, Gid, Mode, Size}}; <<"/SYM64/"/utf8>> -> {ok, {parsed_record, Trimmed_name, 0, none, symbol_table, Mtime, Uid, Gid, Mode, Size}}; <<"//"/utf8>> -> {ok, {parsed_record, Trimmed_name, 0, none, string_table, Mtime, Uid, Gid, Mode, Size}}; <<"ARFILENAMES/"/utf8>> -> {ok, {parsed_record, Trimmed_name, 0, none, string_table, Mtime, Uid, Gid, Mode, Size}}; _ -> case gleam_stdlib:string_starts_with( Trimmed_name, <<"#1/"/utf8>> ) of true -> Len_string = gleam@string:drop_start( Trimmed_name, 3 ), case gleam_stdlib:parse_int( Len_string ) of {ok, Len} -> {ok, {parsed_record, <<""/utf8>>, Len, none, regular_entry, Mtime, Uid, Gid, Mode, Size}}; {error, _} -> {error, {archive_invalid, <<"invalid BSD long name length in ar header"/utf8>>}} end; false -> case gleam_stdlib:string_starts_with( Trimmed_name, <<"/"/utf8>> ) of true -> Offset_string = gleam@string:drop_start( Trimmed_name, 1 ), case gleam_stdlib:parse_int( Offset_string ) of {ok, Offset} -> {ok, {parsed_record, <<""/utf8>>, 0, {some, Offset}, regular_entry, Mtime, Uid, Gid, Mode, Size}}; {error, _} -> {error, {archive_invalid, <<"invalid GNU long name offset in ar header"/utf8>>}} end; false -> {ok, {parsed_record, strip_trailing_slash( Trimmed_name ), 0, none, regular_entry, Mtime, Uid, Gid, Mode, Size}} end end end end ) end ) end ) end ) end ) end ) end ) end ) end ). -file("src/packkit/ar.gleam", 104). -spec decode_loop( bitstring(), list(packkit@entry:entry()), integer(), gleam@option:option(bitstring()), packkit@limit:limits() ) -> {ok, list(packkit@entry:entry())} | {error, packkit@error:archive_error()}. decode_loop(Bytes, Acc, Count, String_table, Limits) -> case erlang:byte_size(Bytes) of 0 -> {ok, Acc}; _ -> case erlang:byte_size(Bytes) < 60 of true -> {error, {archive_invalid, <<"ar entry header truncated"/utf8>>}}; false -> Header_bits@1 = case gleam_stdlib:bit_array_slice( Bytes, 0, 60 ) of {ok, Header_bits} -> Header_bits; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/ar"/utf8>>, function => <<"decode_loop"/utf8>>, line => 118, value => _assert_fail, start => 3520, 'end' => 3587, pattern_start => 3531, pattern_end => 3546}) end, gleam@result:'try'( parse_header(Header_bits@1), fun(Record) -> After_header_offset = 60, Payload_offset = After_header_offset + erlang:element( 3, Record ), Payload_size = erlang:element(10, Record) - erlang:element( 3, Record ), Total_size = 60 + erlang:element(10, Record), Padded_size = case Total_size rem 2 of 0 -> Total_size; _ -> Total_size + 1 end, gleam@bool:guard( erlang:byte_size(Bytes) < (Payload_offset + Payload_size), {error, {archive_invalid, <<"ar entry truncated"/utf8>>}}, fun() -> Advance = min( Padded_size, erlang:byte_size(Bytes) ), Remaining@1 = case gleam_stdlib:bit_array_slice( Bytes, Advance, erlang:byte_size(Bytes) - Advance ) of {ok, Remaining} -> Remaining; _assert_fail@1 -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/ar"/utf8>>, function => <<"decode_loop"/utf8>>, line => 136, value => _assert_fail@1, start => 4294, 'end' => 4459, pattern_start => 4305, pattern_end => 4318} ) end, case erlang:element(5, Record) of symbol_table -> decode_loop( Remaining@1, Acc, Count, String_table, Limits ); string_table -> Table_body@1 = case gleam_stdlib:bit_array_slice( Bytes, Payload_offset, Payload_size ) of {ok, Table_body} -> Table_body; _assert_fail@2 -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/ar"/utf8>>, function => <<"decode_loop"/utf8>>, line => 147, value => _assert_fail@2, start => 4634, 'end' => 4730, pattern_start => 4645, pattern_end => 4659} ) end, decode_loop( Remaining@1, Acc, Count, {some, Table_body@1}, Limits ); regular_entry -> gleam@result:'try'( check_member_limit( Count + 1, Limits ), fun(_) -> gleam@result:'try'( resolve_entry_name( Record, Bytes, After_header_offset, String_table ), fun(Name) -> gleam@bool:guard( erlang:byte_size( Name ) > packkit@limit:max_entry_name_bytes( Limits ), {error, {archive_limit_exceeded, <<"max_entry_name_bytes"/utf8>>, erlang:byte_size( Name )}}, fun() -> Body@1 = case gleam_stdlib:bit_array_slice( Bytes, Payload_offset, Payload_size ) of {ok, Body} -> Body; _assert_fail@3 -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/ar"/utf8>>, function => <<"decode_loop"/utf8>>, line => 176, value => _assert_fail@3, start => 5559, 'end' => 5649, pattern_start => 5570, pattern_end => 5578} ) end, gleam@result:'try'( begin _pipe = packkit@entry:file_checked( Name, Body@1 ), gleam@result:map_error( _pipe, fun( _capture ) -> entry_error_to_archive_error( _capture, Name ) end ) end, fun( Base_entry ) -> Depth = packkit@entry:depth( packkit@entry:path( Base_entry ) ), gleam@bool:guard( Depth > packkit@limit:max_entry_depth( Limits ), {error, {archive_limit_exceeded, <<"max_entry_depth"/utf8>>, Depth}}, fun( ) -> Entry_value = begin _pipe@1 = Base_entry, _pipe@2 = packkit@entry:with_mode( _pipe@1, erlang:element( 9, Record ) ), _pipe@3 = packkit@entry:with_owner( _pipe@2, erlang:element( 7, Record ), erlang:element( 8, Record ) ), packkit@entry:with_modified_at( _pipe@3, erlang:element( 6, Record ) ) end, decode_loop( Remaining@1, [Entry_value | Acc], Count + 1, String_table, Limits ) end ) end ) end ) end ) end ) end end ) end ) end end. -file("src/packkit/ar.gleam", 78). ?DOC(" Decode an `ar` byte stream using explicit limits.\n"). -spec decode_with_limits(bitstring(), packkit@limit:limits()) -> {ok, packkit@archive:archive()} | {error, packkit@error:archive_error()}. decode_with_limits(Bytes, 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'( slice_or_error(Bytes, 0, 8), fun(Header_bits) -> gleam@result:'try'( bytes_to_string(Header_bits), fun(Header_string) -> gleam@bool:guard( Header_string /= <<"!\n"/utf8>>, {error, {archive_invalid, <<"missing ! magic"/utf8>>}}, fun() -> Body_size = erlang:byte_size(Bytes) - 8, Rest@1 = case gleam_stdlib:bit_array_slice( Bytes, 8, Body_size ) of {ok, Rest} -> Rest; _assert_fail -> erlang:error( #{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"packkit/ar"/utf8>>, function => <<"decode_with_limits"/utf8>>, line => 98, value => _assert_fail, start => 2872, 'end' => 2939, pattern_start => 2883, pattern_end => 2891} ) end, _pipe = decode_loop( Rest@1, [], 0, none, Limits ), _pipe@1 = gleam@result:map( _pipe, fun lists:reverse/1 ), gleam@result:map( _pipe@1, fun(_capture) -> packkit@archive:from_entries( format(), _capture ) end ) end ) end ) end ) end ). -file("src/packkit/ar.gleam", 71). ?DOC(" Decode an `ar` byte stream using default limits.\n"). -spec decode(bitstring()) -> {ok, packkit@archive:archive()} | {error, packkit@error:archive_error()}. decode(Bytes) -> decode_with_limits(Bytes, packkit@limit:default()). -file("src/packkit/ar.gleam", 409). -spec encode_entry(packkit@entry:entry()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode_entry(Value) -> Kind = packkit@entry:kind(Value), gleam@bool:guard( Kind /= file, {error, {archive_entry_rejected, packkit@entry:to_string(packkit@entry:path(Value)), <<"ar only supports regular file entries"/utf8>>}}, fun() -> Path = packkit@entry:to_string(packkit@entry:path(Value)), Metadata = packkit@entry:metadata(Value), Body = packkit@entry:body(Value), Body_size = erlang:byte_size(Body), Name_bytes = gleam_stdlib:identity(Path), Name_size = erlang:byte_size(Name_bytes), Needs_long_name = ((Name_size > 16) orelse gleam_stdlib:contains_string( Path, <<" "/utf8>> )) orelse gleam_stdlib:contains_string(Path, <<"/"/utf8>>), {Name_field, Name_extension_bytes, Total_size} = case Needs_long_name of true -> Extension_size = Name_size, Label = <<"#1/"/utf8, (erlang:integer_to_binary(Extension_size))/binary>>, {text_field(Label, 16), Name_bytes, Body_size + Extension_size}; false -> {text_field(Path, 16), <<>>, Body_size} end, gleam@result:'try'( checked_decimal_field( packkit@entry:modified_at_unix(Metadata), 12, <<"mtime"/utf8>> ), fun(Mtime_field) -> gleam@result:'try'( checked_decimal_field( packkit@entry:user_id(Metadata), 6, <<"uid"/utf8>> ), fun(Uid_field) -> gleam@result:'try'( checked_decimal_field( packkit@entry:group_id(Metadata), 6, <<"gid"/utf8>> ), fun(Gid_field) -> gleam@result:'try'( checked_octal_field( packkit@entry:mode(Metadata), 8, <<"mode"/utf8>> ), fun(Mode_field) -> gleam@result:'try'( checked_decimal_field( Total_size, 10, <<"size"/utf8>> ), fun(Size_field) -> Header = gleam_stdlib:bit_array_concat( [Name_field, Mtime_field, Uid_field, Gid_field, Mode_field, Size_field, <<16#60, 16#0A>>] ), Combined = gleam_stdlib:bit_array_concat( [Header, Name_extension_bytes, Body] ), Padded = case Total_size rem 2 of 0 -> Combined; _ -> gleam_stdlib:bit_array_concat( [Combined, <<16#0A>>] ) end, {ok, Padded} end ) end ) end ) end ) end ) end ). -file("src/packkit/ar.gleam", 48). ?DOC(" Encode the logical archive to an `ar` byte stream.\n"). -spec encode(packkit@archive:archive()) -> {ok, bitstring()} | {error, packkit@error:archive_error()}. encode(Archive_value) -> gleam@result:'try'( reject_comment(Archive_value), fun(_) -> _pipe = Archive_value, _pipe@1 = packkit@archive:entries(_pipe), _pipe@2 = gleam@list:try_map(_pipe@1, fun encode_entry/1), gleam@result:map( _pipe@2, fun(Records) -> _pipe@3 = [gleam_stdlib:identity(<<"!\n"/utf8>>), gleam_stdlib:bit_array_concat(Records)], gleam_stdlib:bit_array_concat(_pipe@3) end ) end ).