-module(slabs). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/slabs.gleam"). -export([new/0, insert/2, insert_many/2, remove/2, remove_many/2, get/2, get_values/1, length/1]). -export_type([entry/1, slab/1, slab_error/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(DTX) :: {vacant, gleam@option:option(integer())} | {occupied, DTX}. -opaque slab(DTY) :: {slab, list(entry(DTY)), gleam@option:option(integer()), integer()}. -type slab_error() :: {bad_index, integer()}. -file("src/slabs.gleam", 18). ?DOC(" Create a new slab container\n"). -spec new() -> slab(any()). new() -> {slab, [], none, 0}. -file("src/slabs.gleam", 23). ?DOC(" Insert an item into the slab\n"). -spec insert(slab(DUB), DUB) -> {slab(DUB), integer()}. insert(Slab, Value) -> case erlang:element(3, Slab) of {some, Slot_index} -> Index = (erlang:element(4, Slab) - 1) - Slot_index, {Left, Right} = begin _pipe = erlang:element(2, Slab), gleam@list:split(_pipe, Index) end, Next_id@1 = case begin _pipe@1 = Right, gleam@list:first(_pipe@1) end of {ok, {vacant, Next_id}} -> Next_id; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"slabs"/utf8>>, function => <<"insert"/utf8>>, line => 32, value => _assert_fail, start => 639, 'end' => 707, pattern_start => 650, pattern_end => 669}) end, Right@1 = case Right of [_ | Rest] -> Rest; [] -> [] end, Inner = lists:append(Left, [{occupied, Value} | Right@1]), {{slab, Inner, Next_id@1, erlang:element(4, Slab)}, Slot_index}; none -> Index@1 = erlang:length(erlang:element(2, Slab)), {{slab, [{occupied, Value} | erlang:element(2, Slab)], erlang:element(3, Slab), erlang:element(4, Slab) + 1}, Index@1} end. -file("src/slabs.gleam", 60). -spec insert_accum(slab(DUE), list(DUE), list(integer())) -> {slab(DUE), list(integer())}. insert_accum(Slab, Values, Acc) -> case Values of [V | Rest] -> {Slab@1, Index} = insert(Slab, V), insert_accum(Slab@1, Rest, [Index | Acc]); [] -> {Slab, Acc} end. -file("src/slabs.gleam", 75). ?DOC(" Insert several items into the slab\n"). -spec insert_many(slab(DUK), list(DUK)) -> {slab(DUK), list(integer())}. insert_many(Slab, Values) -> insert_accum(Slab, Values, []). -file("src/slabs.gleam", 80). ?DOC(" Remove an entry from the slab\n"). -spec remove(slab(DUP), integer()) -> {ok, {slab(DUP), DUP}} | {error, slab_error()}. remove(Slab, Index) -> case (Index >= 0) andalso (Index < erlang:element(4, Slab)) of true -> {Left, Right} = begin _pipe = erlang:element(2, Slab), gleam@list:split(_pipe, (erlang:element(4, Slab) - 1) - Index) end, Entry@1 = case begin _pipe@1 = Right, gleam@list:first(_pipe@1) end of {ok, Entry} -> Entry; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"slabs"/utf8>>, function => <<"remove"/utf8>>, line => 87, value => _assert_fail, start => 1840, 'end' => 1898, pattern_start => 1851, pattern_end => 1860}) end, Right@1 = case Right of [_ | Rest] -> Rest; [] -> [] end, Inner = lists:append( Left, [{vacant, erlang:element(3, Slab)} | Right@1] ), Value@1 = case Entry@1 of {occupied, Value} -> Value; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"slabs"/utf8>>, function => <<"remove"/utf8>>, line => 99, value => _assert_fail@1, start => 2135, 'end' => 2169, pattern_start => 2146, pattern_end => 2161}) end, {ok, {{slab, Inner, {some, Index}, erlang:element(4, Slab)}, Value@1}}; false -> {error, {bad_index, Index}} end. -file("src/slabs.gleam", 107). -spec remove_many_accum(slab(DUU), list(integer()), list(DUU)) -> {slab(DUU), list(DUU)}. remove_many_accum(Slab, Indexes, Acc) -> case Indexes of [Index | Rest] -> case remove(Slab, Index) of {ok, {Slab@1, Value}} -> remove_many_accum(Slab@1, Rest, [Value | Acc]); {error, _} -> remove_many_accum(Slab, Rest, Acc) end; [] -> {Slab, Acc} end. -file("src/slabs.gleam", 124). ?DOC(" Remove several items from a slab at once\n"). -spec remove_many(slab(DVA), list(integer())) -> {slab(DVA), list(DVA)}. remove_many(Slab, Indexes) -> remove_many_accum(Slab, Indexes, []). -file("src/slabs.gleam", 128). -spec get_items(list(entry(DVF)), integer(), integer()) -> gleam@option:option(DVF). get_items(Items, Acc, Index) -> case Items of [V, _] when Acc =:= Index -> case V of {vacant, _} -> none; {occupied, V@1} -> {some, V@1} end; [V] when Acc =:= Index -> case V of {vacant, _} -> none; {occupied, V@1} -> {some, V@1} end; [_ | Rest] -> get_items(Rest, Acc - 1, Index); [] -> none end. -file("src/slabs.gleam", 144). ?DOC(" Index into the slab and retrieve a value\n"). -spec get(slab(DVJ), integer()) -> gleam@option:option(DVJ). get(Slab, Index) -> get_items(erlang:element(2, Slab), erlang:element(4, Slab) - 1, Index). -file("src/slabs.gleam", 148). -spec get_values_accum(list(entry(DVM)), integer(), list({integer(), DVM})) -> list({integer(), DVM}). get_values_accum(Entries, Index, Acc) -> case Entries of [{occupied, Value} | Rest] -> get_values_accum(Rest, Index - 1, [{Index, Value} | Acc]); [_ | Rest@1] -> get_values_accum(Rest@1, Index - 1, Acc); _ -> Acc end. -file("src/slabs.gleam", 162). ?DOC(" Retrieve a list of the occupied values and their corresponding indexes\n"). -spec get_values(slab(DVR)) -> list({integer(), DVR}). get_values(Slab) -> get_values_accum(erlang:element(2, Slab), erlang:element(4, Slab), []). -file("src/slabs.gleam", 167). ?DOC(" Returns the amount of items in the slab (including vacant slots)\n"). -spec length(slab(any())) -> integer(). length(Slab) -> erlang:element(4, Slab).