-module(packkit@lzw).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/packkit/lzw.gleam").
-export([codec/0, encode_with_options/3, decode_with_limits/2, decode/1, encode/1]).
-export_type([encode_state/0, decode_state/0, writer/0, reader/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 `compress(1)` LZW codec — `.Z` stream encoder and decoder.\n"
"\n"
" The stream begins with the two-byte magic `1F 9D` followed by a\n"
" flag byte whose low five bits hold the maximum code width\n"
" (9..16) and whose top bit toggles block-compress mode. Codes\n"
" are packed LSB-first across bytes, the dictionary starts with\n"
" the 256 byte literals (plus a clear-table marker when block mode\n"
" is on), and each new entry maps the previous code plus the\n"
" current character to the next free code. When the dictionary\n"
" fills the current width, the encoder pads to the next\n"
" `width * 8` bit boundary before promoting to the next width or\n"
" emitting a clear-table code.\n"
).
-type encode_state() :: {encode_state,
gleam@dict:dict(integer(), integer()),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
boolean(),
writer(),
integer()}.
-type decode_state() :: {decode_state,
list(integer()),
integer(),
gleam@dict:dict(integer(), {integer(), integer()}),
integer(),
integer(),
integer(),
integer(),
integer(),
boolean(),
integer(),
boolean(),
integer()}.
-type writer() :: {writer, list(integer()), integer(), integer(), integer()}.
-type reader() :: {reader,
bitstring(),
integer(),
integer(),
integer(),
boolean()}.
-file("src/packkit/lzw.gleam", 36).
?DOC(" LZW codec smart constructor (Unix `.Z` family).\n").
-spec codec() -> packkit@codec:codec().
codec() ->
packkit@codec:lzw().
-file("src/packkit/lzw.gleam", 200).
-spec dictionary_key(integer(), integer()) -> integer().
dictionary_key(Prefix, Byte) ->
erlang:'bor'(erlang:'bsl'(Prefix, 8), Byte).
-file("src/packkit/lzw.gleam", 222).
-spec max_max_code(integer()) -> integer().
max_max_code(Max_bits) ->
erlang:'bsl'(1, Max_bits).
-file("src/packkit/lzw.gleam", 204).
-spec max_code_for(integer(), integer()) -> integer().
max_code_for(N_bits, Max_bits) ->
case N_bits >= Max_bits of
true ->
max_max_code(Max_bits);
false ->
erlang:'bsl'(1, N_bits)
end.
-file("src/packkit/lzw.gleam", 425).
?DOC(
" The decoder must promote one iteration \"earlier\" than the encoder\n"
" because of the classical LZW insertion off-by-one: encoder inserts\n"
" the `(prefix, byte)` pair at the iter that writes the OLD prefix's\n"
" code, while the decoder inserts `(prev_code, first_of_current_code)`\n"
" at the iter that reads the current code — same final entries, but\n"
" the decoder's `free_ent` lags one bump behind the encoder's view\n"
" of the stream. We check `free_ent >= max_code` so the decoder\n"
" promotes between codes 254 and 255 (when the encoder pads), instead\n"
" of between codes 255 and 256 (when the decoder's own free_ent would\n"
" naturally exceed max_code). Without this, a 256-unique-byte stream\n"
" reads the encoder's 9-bit pad as a phantom literal code 0.\n"
).
-spec promote_decoder_width(decode_state(), reader()) -> decode_state().
promote_decoder_width(State, _) ->
case (erlang:element(5, State) >= erlang:element(7, State)) andalso (erlang:element(
6,
State
)
< erlang:element(11, State)) of
true ->
{decode_state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
-1,
erlang:element(9, State),
erlang:element(10, State),
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)};
false ->
State
end.
-file("src/packkit/lzw.gleam", 462).
-spec check_output_limit(integer(), packkit@limit:limits()) -> {ok, nil} |
{error, packkit@error:codec_error()}.
check_output_limit(Size, Limits) ->
case Size > packkit@limit:max_output_bytes(Limits) of
true ->
{error, {codec_limit_exceeded, <<"max_output_bytes"/utf8>>, Size}};
false ->
{ok, nil}
end.
-file("src/packkit/lzw.gleam", 480).
-spec expand_loop(
integer(),
gleam@dict:dict(integer(), {integer(), integer()}),
list(integer()),
integer()
) -> {ok, {list(integer()), integer()}} | {error, packkit@error:codec_error()}.
expand_loop(Code, Table, Acc, Count) ->
case Code < 256 of
true ->
{ok, {[Code | Acc], Count + 1}};
false ->
case gleam_stdlib:map_get(Table, Code) of
{ok, {Prev, Char}} ->
expand_loop(Prev, Table, [Char | Acc], Count + 1);
{error, _} ->
{error,
{codec_invalid_data, <<"lzw code lookup failed"/utf8>>}}
end
end.
-file("src/packkit/lzw.gleam", 473).
-spec expand_code(integer(), gleam@dict:dict(integer(), {integer(), integer()})) -> {ok,
{list(integer()), integer()}} |
{error, packkit@error:codec_error()}.
expand_code(Code, Table) ->
expand_loop(Code, Table, [], 0).
-file("src/packkit/lzw.gleam", 497).
-spec first_char(integer(), gleam@dict:dict(integer(), {integer(), integer()})) -> {ok,
integer()} |
{error, packkit@error:codec_error()}.
first_char(Code, Table) ->
case Code < 256 of
true ->
{ok, Code};
false ->
case gleam_stdlib:map_get(Table, Code) of
{ok, {Prev, _}} ->
first_char(Prev, Table);
{error, _} ->
{error,
{codec_invalid_data,
<<"lzw first-char lookup failed"/utf8>>}}
end
end.
-file("src/packkit/lzw.gleam", 512).
-spec first_char_of_chars(list(integer())) -> {ok, integer()} |
{error, packkit@error:codec_error()}.
first_char_of_chars(Chars) ->
case Chars of
[Head | _] ->
{ok, Head};
[] ->
{error,
{codec_invalid_data, <<"lzw expansion produced no bytes"/utf8>>}}
end.
-file("src/packkit/lzw.gleam", 520).
-spec prepend_chars(list(integer()), list(integer())) -> list(integer()).
prepend_chars(Chars, Acc) ->
case Chars of
[] ->
Acc;
[Head | Rest] ->
prepend_chars(Rest, [Head | Acc])
end.
-file("src/packkit/lzw.gleam", 432).
-spec emit_code(
integer(),
list(integer()),
integer(),
gleam@dict:dict(integer(), {integer(), integer()}),
integer(),
boolean(),
integer(),
packkit@limit:limits()
) -> {ok,
{list(integer()),
integer(),
gleam@dict:dict(integer(), {integer(), integer()}),
integer()}} |
{error, packkit@error:codec_error()}.
emit_code(Code, Out_rev, Out_len, Table, Prev_code, Has_prev, Free_ent, Limits) ->
case (Code =:= Free_ent) andalso Has_prev of
true ->
gleam@result:'try'(
first_char(Prev_code, Table),
fun(First) ->
Extended_table = gleam@dict:insert(
Table,
Code,
{Prev_code, First}
),
gleam@result:'try'(
expand_code(Code, Extended_table),
fun(_use0) ->
{Chars, Count} = _use0,
gleam@result:'try'(
check_output_limit(Out_len + Count, Limits),
fun(_) ->
{ok,
{prepend_chars(Chars, Out_rev),
Out_len + Count,
Table,
First}}
end
)
end
)
end
);
false ->
gleam@result:'try'(
expand_code(Code, Table),
fun(_use0@1) ->
{Chars@1, Count@1} = _use0@1,
gleam@result:'try'(
first_char_of_chars(Chars@1),
fun(First@1) ->
gleam@result:'try'(
check_output_limit(Out_len + Count@1, Limits),
fun(_) ->
{ok,
{prepend_chars(Chars@1, Out_rev),
Out_len + Count@1,
Table,
First@1}}
end
)
end
)
end
)
end.
-file("src/packkit/lzw.gleam", 527).
-spec reverse_to_bit_array(list(integer()), bitstring()) -> bitstring().
reverse_to_bit_array(Values, Acc) ->
case Values of
[] ->
Acc;
[Head | Rest] ->
reverse_to_bit_array(Rest, <<Head, Acc/bitstring>>)
end.
-file("src/packkit/lzw.gleam", 540).
-spec new_writer() -> writer().
new_writer() ->
{writer, [], 0, 0, 0}.
-file("src/packkit/lzw.gleam", 568).
-spec mask_for(integer()) -> integer().
mask_for(Count) ->
erlang:'bsl'(1, Count) - 1.
-file("src/packkit/lzw.gleam", 572).
-spec flush_full_bytes(writer()) -> writer().
flush_full_bytes(Writer) ->
case erlang:element(4, Writer) >= 8 of
false ->
Writer;
true ->
flush_full_bytes(
{writer,
[erlang:'band'(erlang:element(3, Writer), 16#FF) |
erlang:element(2, Writer)],
erlang:'bsr'(erlang:element(3, Writer), 8),
erlang:element(4, Writer) - 8,
erlang:element(5, Writer)}
)
end.
-file("src/packkit/lzw.gleam", 548).
-spec write_bits(writer(), integer(), integer()) -> writer().
write_bits(Writer, Value, Count) ->
case Count of
0 ->
Writer;
_ ->
Masked = erlang:'band'(Value, mask_for(Count)),
Buffer = erlang:'bor'(
erlang:element(3, Writer),
erlang:'bsl'(Masked, erlang:element(4, Writer))
),
flush_full_bytes(
{writer,
erlang:element(2, Writer),
Buffer,
erlang:element(4, Writer) + Count,
erlang:element(5, Writer) + Count}
)
end.
-file("src/packkit/lzw.gleam", 275).
-spec pad_zero_bits(writer(), integer()) -> writer().
pad_zero_bits(Writer, Count) ->
case Count of
0 ->
Writer;
N when N >= 32 ->
pad_zero_bits(write_bits(Writer, 0, 32), N - 32);
N@1 ->
write_bits(Writer, 0, N@1)
end.
-file("src/packkit/lzw.gleam", 266).
-spec pad_writer_to_block(writer(), integer()) -> writer().
pad_writer_to_block(Writer, N_bits) ->
Group_bits = 8 * N_bits,
Leftover = case Group_bits of
0 -> 0;
Gleam@denominator -> erlang:element(5, Writer) rem Gleam@denominator
end,
case Leftover of
0 ->
Writer;
_ ->
pad_zero_bits(Writer, Group_bits - Leftover)
end.
-file("src/packkit/lzw.gleam", 226).
-spec promote_width(encode_state()) -> encode_state().
promote_width(State) ->
case (erlang:element(4, State) > erlang:element(6, State)) andalso (erlang:element(
5,
State
)
< erlang:element(8, State)) of
true ->
Writer = pad_writer_to_block(
erlang:element(10, State),
erlang:element(5, State)
),
New_n_bits = erlang:element(5, State) + 1,
{encode_state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
New_n_bits,
max_code_for(New_n_bits, erlang:element(8, State)),
0,
erlang:element(8, State),
erlang:element(9, State),
Writer,
erlang:element(11, State)};
false ->
State
end.
-file("src/packkit/lzw.gleam", 544).
-spec write_code(writer(), integer(), integer()) -> writer().
write_code(Writer, Code, N_bits) ->
write_bits(Writer, Code, N_bits).
-file("src/packkit/lzw.gleam", 262).
-spec write_code_with_padding(encode_state(), integer()) -> writer().
write_code_with_padding(State, Code) ->
write_code(erlang:element(10, State), Code, erlang:element(5, State)).
-file("src/packkit/lzw.gleam", 599).
-spec list_reverse_to_bit_array(list(integer()), bitstring()) -> bitstring().
list_reverse_to_bit_array(Values, Acc) ->
case Values of
[] ->
Acc;
[Head | Rest] ->
list_reverse_to_bit_array(Rest, <<Head, Acc/bitstring>>)
end.
-file("src/packkit/lzw.gleam", 585).
-spec flush_writer(writer()) -> bitstring().
flush_writer(Writer) ->
Writer@1 = case erlang:element(4, Writer) of
0 ->
Writer;
_ ->
{writer,
[erlang:'band'(erlang:element(3, Writer), 16#FF) |
erlang:element(2, Writer)],
0,
0,
erlang:element(5, Writer)}
end,
list_reverse_to_bit_array(erlang:element(2, Writer@1), <<>>).
-file("src/packkit/lzw.gleam", 618).
-spec new_reader(bitstring()) -> reader().
new_reader(Source) ->
{reader, Source, 0, 0, 0, false}.
-file("src/packkit/lzw.gleam", 622).
-spec refill(reader(), integer()) -> reader().
refill(Reader, Needed) ->
case (erlang:element(4, Reader) >= Needed) orelse erlang:element(6, Reader) of
true ->
Reader;
false ->
case erlang:element(2, Reader) of
<<B, Rest/binary>> ->
refill(
{reader,
Rest,
erlang:'bor'(
erlang:element(3, Reader),
erlang:'bsl'(B, erlang:element(4, Reader))
),
erlang:element(4, Reader) + 8,
erlang:element(5, Reader),
false},
Needed
);
_ ->
{reader,
<<>>,
erlang:element(3, Reader),
erlang:element(4, Reader),
erlang:element(5, Reader),
true}
end
end.
-file("src/packkit/lzw.gleam", 653).
-spec read_code(reader(), integer()) -> {ok, {integer(), reader()}} |
{error, nil}.
read_code(Reader, N_bits) ->
Reader@1 = refill(Reader, N_bits),
case erlang:element(4, Reader@1) >= N_bits of
false ->
{error, nil};
true ->
Mask = mask_for(N_bits),
Value = erlang:'band'(erlang:element(3, Reader@1), Mask),
{ok,
{Value,
{reader,
erlang:element(2, Reader@1),
erlang:'bsr'(erlang:element(3, Reader@1), N_bits),
erlang:element(4, Reader@1) - N_bits,
erlang:element(5, Reader@1) + N_bits,
erlang:element(6, Reader@1)}}}
end.
-file("src/packkit/lzw.gleam", 683).
-spec drop_bits(reader(), integer()) -> reader().
drop_bits(Reader, Count) ->
case Count of
0 ->
Reader;
_ ->
Reader@1 = refill(Reader, 1),
case erlang:element(4, Reader@1) >= 1 of
false ->
Reader@1;
true ->
drop_bits(
{reader,
erlang:element(2, Reader@1),
erlang:'bsr'(erlang:element(3, Reader@1), 1),
erlang:element(4, Reader@1) - 1,
erlang:element(5, Reader@1) + 1,
erlang:element(6, Reader@1)},
Count - 1
)
end
end.
-file("src/packkit/lzw.gleam", 674).
-spec skip_to_block_boundary(reader(), integer()) -> reader().
skip_to_block_boundary(Reader, N_bits) ->
Group_bits = 8 * N_bits,
Leftover = case Group_bits of
0 -> 0;
Gleam@denominator -> erlang:element(5, Reader) rem Gleam@denominator
end,
case Leftover of
0 ->
Reader;
_ ->
drop_bits(Reader, Group_bits - Leftover)
end.
-file("src/packkit/lzw.gleam", 106).
-spec build_header(integer(), boolean()) -> bitstring().
build_header(Max_bits, Block_mode) ->
Flag = case Block_mode of
true ->
erlang:'bor'(Max_bits, 16#80);
false ->
Max_bits
end,
<<16#1F, 16#9D, Flag>>.
-file("src/packkit/lzw.gleam", 243).
-spec maybe_emit_clear(encode_state()) -> encode_state().
maybe_emit_clear(State) ->
case erlang:element(9, State) andalso (erlang:element(4, State) > max_max_code(
erlang:element(8, State)
)) of
true ->
Writer = write_code(
erlang:element(10, State),
256,
erlang:element(5, State)
),
Writer@1 = pad_writer_to_block(Writer, erlang:element(5, State)),
{encode_state,
maps:new(),
erlang:element(3, State),
erlang:element(11, State),
9,
max_code_for(9, erlang:element(8, State)),
0,
erlang:element(8, State),
erlang:element(9, State),
Writer@1,
erlang:element(11, State)};
false ->
State
end.
-file("src/packkit/lzw.gleam", 160).
-spec encode_loop(bitstring(), encode_state()) -> encode_state().
encode_loop(Input, State) ->
case Input of
<<Byte, Rest/binary>> ->
Key = dictionary_key(erlang:element(3, State), Byte),
case gleam_stdlib:map_get(erlang:element(2, State), Key) of
{ok, Code} ->
encode_loop(
Rest,
{encode_state,
erlang:element(2, State),
Code,
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
erlang:element(9, State),
erlang:element(10, State),
erlang:element(11, State)}
);
{error, _} ->
Writer = write_code_with_padding(
State,
erlang:element(3, State)
),
Next_state = case erlang:element(4, State) =< max_max_code(
erlang:element(8, State)
) of
true ->
Table = gleam@dict:insert(
erlang:element(2, State),
Key,
erlang:element(4, State)
),
promote_width(
{encode_state,
Table,
Byte,
erlang:element(4, State) + 1,
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State) + 1,
erlang:element(8, State),
erlang:element(9, State),
Writer,
erlang:element(11, State)}
);
false ->
maybe_emit_clear(
{encode_state,
erlang:element(2, State),
Byte,
erlang:element(4, State),
erlang:element(5, State),
erlang:element(6, State),
erlang:element(7, State) + 1,
erlang:element(8, State),
erlang:element(9, State),
Writer,
erlang:element(11, State)}
)
end,
encode_loop(Rest, Next_state)
end;
_ ->
State
end.
-file("src/packkit/lzw.gleam", 131).
-spec encode_payload(bitstring(), integer(), boolean(), integer()) -> bitstring().
encode_payload(Bytes, Max_bits, Block_mode, First_free) ->
case Bytes of
<<First, Rest/binary>> ->
State = {encode_state,
maps:new(),
First,
First_free,
9,
max_code_for(9, Max_bits),
0,
Max_bits,
Block_mode,
new_writer(),
First_free},
State@1 = encode_loop(Rest, State),
Writer = write_code_with_padding(
State@1,
erlang:element(3, State@1)
),
flush_writer(Writer);
_ ->
flush_writer(new_writer())
end.
-file("src/packkit/lzw.gleam", 51).
?DOC(" Encode `bytes` as a `.Z` stream with explicit options.\n").
-spec encode_with_options(bitstring(), integer(), boolean()) -> {ok,
bitstring()} |
{error, packkit@error:codec_error()}.
encode_with_options(Bytes, Max_bits, Block_mode) ->
gleam@bool:guard(
(Max_bits < 9) orelse (Max_bits > 16),
{error,
{codec_invalid_data, <<"lzw max_bits out of range (9..16)"/utf8>>}},
fun() ->
Header = build_header(Max_bits, Block_mode),
First_free = case Block_mode of
true ->
257;
false ->
256
end,
Payload = encode_payload(Bytes, Max_bits, Block_mode, First_free),
{ok, gleam_stdlib:bit_array_concat([Header, Payload])}
end
).
-file("src/packkit/lzw.gleam", 333).
-spec decode_loop(reader(), decode_state(), packkit@limit:limits()) -> {ok,
{list(integer()), integer()}} |
{error, packkit@error:codec_error()}.
decode_loop(Reader, State, Limits) ->
case read_code(Reader, erlang:element(6, State)) of
{error, _} ->
{ok, {erlang:element(2, State), erlang:element(3, State)}};
{ok, {Code, Reader@1}} ->
case erlang:element(12, State) andalso (Code =:= 256) of
true ->
Reader@2 = skip_to_block_boundary(
Reader@1,
erlang:element(6, State)
),
New_state = {decode_state,
erlang:element(2, State),
erlang:element(3, State),
maps:new(),
erlang:element(13, State),
9,
max_code_for(9, erlang:element(11, State)),
0,
-1,
false,
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)},
decode_loop(Reader@2, New_state, Limits);
false ->
gleam@result:'try'(
emit_code(
Code,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(9, State),
erlang:element(10, State),
erlang:element(5, State),
Limits
),
fun(_use0) ->
{Out_rev, Out_len, Table, Prefix_first} = _use0,
{New_table, New_free_ent} = case erlang:element(
10,
State
) of
true ->
{gleam@dict:insert(
Table,
erlang:element(5, State),
{erlang:element(9, State),
Prefix_first}
),
erlang:element(5, State) + 1};
false ->
{Table, erlang:element(5, State)}
end,
New_state@1 = {decode_state,
Out_rev,
Out_len,
New_table,
New_free_ent,
erlang:element(6, State),
erlang:element(7, State),
erlang:element(8, State),
Code,
true,
erlang:element(11, State),
erlang:element(12, State),
erlang:element(13, State)},
New_state@2 = promote_decoder_width(
New_state@1,
Reader@1
),
{New_state@3, Reader@4} = case erlang:element(
8,
New_state@2
) of
-1 ->
Reader@3 = skip_to_block_boundary(
Reader@1,
erlang:element(6, State)
),
{{decode_state,
erlang:element(2, New_state@2),
erlang:element(3, New_state@2),
erlang:element(4, New_state@2),
erlang:element(5, New_state@2),
erlang:element(6, New_state@2) + 1,
max_code_for(
erlang:element(6, New_state@2) + 1,
erlang:element(11, New_state@2)
),
0,
erlang:element(9, New_state@2),
erlang:element(10, New_state@2),
erlang:element(11, New_state@2),
erlang:element(12, New_state@2),
erlang:element(13, New_state@2)},
Reader@3};
_ ->
{New_state@2, Reader@1}
end,
decode_loop(Reader@4, New_state@3, Limits)
end
)
end
end.
-file("src/packkit/lzw.gleam", 302).
-spec decode_payload(bitstring(), integer(), boolean(), packkit@limit:limits()) -> {ok,
bitstring()} |
{error, packkit@error:codec_error()}.
decode_payload(Bytes, Max_bits, Block_mode, Limits) ->
First_free = case Block_mode of
true ->
257;
false ->
256
end,
Reader = new_reader(Bytes),
State = {decode_state,
[],
0,
maps:new(),
First_free,
9,
max_code_for(9, Max_bits),
0,
-1,
false,
Max_bits,
Block_mode,
First_free},
gleam@result:'try'(
decode_loop(Reader, State, Limits),
fun(_use0) ->
{Out_rev, Out_len} = _use0,
gleam@result:'try'(
check_output_limit(Out_len, Limits),
fun(_) -> {ok, reverse_to_bit_array(Out_rev, <<>>)} end
)
end
).
-file("src/packkit/lzw.gleam", 77).
?DOC(" Decode a `.Z` stream using explicit `Limits`.\n").
-spec decode_with_limits(bitstring(), packkit@limit:limits()) -> {ok,
bitstring()} |
{error, packkit@error:codec_error()}.
decode_with_limits(Bytes, Limits) ->
gleam@bool:guard(
erlang:byte_size(Bytes) > packkit@limit:max_input_bytes(Limits),
{error,
{codec_limit_exceeded,
<<"max_input_bytes"/utf8>>,
erlang:byte_size(Bytes)}},
fun() -> case Bytes of
<<M1, M2, Flag, Rest/binary>> when (M1 =:= 16#1F) andalso (M2 =:= 16#9D) ->
Max_bits = erlang:'band'(Flag, 16#1F),
Block_mode = erlang:'band'(Flag, 16#80) /= 0,
gleam@bool:guard(
(Max_bits < 9) orelse (Max_bits > 16),
{error,
{codec_invalid_data,
<<"lzw header advertises invalid max_bits"/utf8>>}},
fun() ->
decode_payload(Rest, Max_bits, Block_mode, Limits)
end
);
_ ->
{error,
{codec_invalid_data,
<<"lzw stream missing 1F 9D magic"/utf8>>}}
end end
).
-file("src/packkit/lzw.gleam", 72).
?DOC(" Decode a `.Z` stream using the shared default `Limits`.\n").
-spec decode(bitstring()) -> {ok, bitstring()} |
{error, packkit@error:codec_error()}.
decode(Bytes) ->
decode_with_limits(Bytes, packkit@limit:default()).
-file("src/packkit/lzw.gleam", 42).
?DOC(
" Encode `bytes` as a `.Z` stream using the default 16-bit\n"
" block-mode encoder.\n"
).
-spec encode(bitstring()) -> {ok, bitstring()} |
{error, packkit@error:codec_error()}.
encode(Bytes) ->
encode_with_options(Bytes, 16, true).