Packages

Simple in-memory tarball extraction in pure Gleam.

Current section

Files

Jump to
tartiflette src tartiflette.erl
Raw

src/tartiflette.erl

-module(tartiflette).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/tartiflette.gleam").
-export([extract/1]).
-export_type([entry/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.
-type entry() :: {file, binary(), bitstring()} |
{hard_link, binary(), binary()} |
{symbolic_link, binary(), binary()} |
{character_device, binary(), integer(), integer()} |
{block_device, binary(), integer(), integer()} |
{directory, binary()} |
{fifo, binary()}.
-file("src/tartiflette.gleam", 124).
-spec null_terminated_string(bitstring(), bitstring()) -> {ok, binary()} |
{error, nil}.
null_terminated_string(Bytes, Out) ->
case Bytes of
<<>> ->
gleam@bit_array:to_string(Out);
<<0>> ->
gleam@bit_array:to_string(Out);
<<0, _/bitstring>> ->
gleam@bit_array:to_string(Out);
<<Char, Rest/bitstring>> ->
null_terminated_string(Rest, <<Out/bitstring, Char>>);
_ ->
{error, nil}
end.
-file("src/tartiflette.gleam", 136).
-spec octal_string(bitstring()) -> {ok, integer()} | {error, nil}.
octal_string(Bytes) ->
_pipe = null_terminated_string(Bytes, <<>>),
_pipe@1 = gleam@result:map(_pipe, fun gleam@string:trim/1),
gleam@result:'try'(
_pipe@1,
fun(_capture) -> gleam@int:base_parse(_capture, 8) end
).
-file("src/tartiflette.gleam", 32).
-spec do_extract(bitstring(), list(entry())) -> {ok, list(entry())} |
{error, nil}.
do_extract(Tarball, Files) ->
case Tarball of
<<>> ->
{ok, lists:reverse(Files)};
<<0:1024>> ->
{ok, lists:reverse(Files)};
<<File_path:100/binary,
_:8/binary,
_:8/binary,
_:8/binary,
File_size:12/binary,
_:12/binary,
_:8/binary,
File_type:1/binary,
Link_path:100/binary,
_:6/binary,
_:2/binary,
_:32/binary,
_:32/binary,
Device_major_number:8/binary,
Device_minor_number:8/binary,
_:155/binary,
_:12/binary,
Rest/bitstring>> ->
gleam@result:'try'(
null_terminated_string(File_path, <<>>),
fun(Name) ->
gleam@bool:guard(
Name =:= <<""/utf8>>,
{ok, lists:reverse(Files)},
fun() ->
gleam@result:'try'(
octal_string(File_size),
fun(Size) ->
Padding = 512 + (- Size rem 512),
gleam@result:'try'(case Rest of
<<Content:Size/binary,
_:Padding/binary,
Rest@1/bitstring>> ->
{ok, {Content, Rest@1}};
_ ->
{error, nil}
end, fun(_use0) ->
{Content@1, Rest@2} = _use0,
case File_type of
<<"0"/utf8>> ->
do_extract(
Rest@2,
[{file, Name, Content@1} |
Files]
);
<<0>> ->
do_extract(
Rest@2,
[{file, Name, Content@1} |
Files]
);
<<"1"/utf8>> ->
gleam@result:'try'(
null_terminated_string(
Link_path,
<<>>
),
fun(Target) ->
do_extract(
Rest@2,
[{hard_link,
Name,
Target} |
Files]
)
end
);
<<"2"/utf8>> ->
gleam@result:'try'(
null_terminated_string(
Link_path,
<<>>
),
fun(Target@1) ->
do_extract(
Rest@2,
[{symbolic_link,
Name,
Target@1} |
Files]
)
end
);
<<"3"/utf8>> ->
gleam@result:'try'(
octal_string(
Device_major_number
),
fun(Major) ->
gleam@result:'try'(
octal_string(
Device_minor_number
),
fun(Minor) ->
do_extract(
Rest@2,
[{character_device,
Name,
Major,
Minor} |
Files]
)
end
)
end
);
<<"4"/utf8>> ->
gleam@result:'try'(
octal_string(
Device_major_number
),
fun(Major@1) ->
gleam@result:'try'(
octal_string(
Device_minor_number
),
fun(Minor@1) ->
do_extract(
Rest@2,
[{block_device,
Name,
Major@1,
Minor@1} |
Files]
)
end
)
end
);
<<"5"/utf8>> ->
do_extract(
Rest@2,
[{directory, Name} |
Files]
);
<<"6"/utf8>> ->
do_extract(
Rest@2,
[{fifo, Name} | Files]
);
<<"7"/utf8>> ->
do_extract(
Rest@2,
[{file, Name, Content@1} |
Files]
);
_ ->
{error, nil}
end
end)
end
)
end
)
end
);
_ ->
{error, nil}
end.
-file("src/tartiflette.gleam", 28).
?DOC(" Synchronously extract an uncompressed tar archive in-memory.\n").
-spec extract(bitstring()) -> {ok, list(entry())} | {error, nil}.
extract(Tarball) ->
do_extract(Tarball, []).