Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions lib/hpax/table.ex
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ defmodule HPAX.Table do
]

@static_table_size length(@static_table)
@static_table_by_index @static_table |> Enum.map(&{:ok, &1}) |> List.to_tuple()
@dynamic_table_start @static_table_size + 1

@doc """
Expand Down Expand Up @@ -155,24 +156,23 @@ defmodule HPAX.Table do
@spec lookup_by_index(t(), pos_integer()) :: {:ok, {binary(), binary()}} | :error
def lookup_by_index(table, index)

# Static table
for {header, index} <- Enum.with_index(@static_table, 1) do
def lookup_by_index(%__MODULE__{}, unquote(index)), do: {:ok, unquote(header)}
end

def lookup_by_index(%__MODULE__{length: 0}, _index) do
:error
def lookup_by_index(%__MODULE__{}, index) when index in 1..@static_table_size do
elem(@static_table_by_index, index - 1)
end

def lookup_by_index(%__MODULE__{entries: entries, length: length}, index)
when index >= @dynamic_table_start and index <= @dynamic_table_start + length - 1 do
{:ok, Enum.at(entries, index - @dynamic_table_start)}
{:ok, get_dynamic_entry(entries, index - @dynamic_table_start)}
end

def lookup_by_index(%__MODULE__{}, _index) do
:error
end

@compile {:inline, get_dynamic_entry: 2}
defp get_dynamic_entry([entry | _], 0), do: entry
defp get_dynamic_entry([_ | rest], n), do: get_dynamic_entry(rest, n - 1)

@doc """
Looks up the index of a header by its name and value.

Expand Down
25 changes: 19 additions & 6 deletions test/hpax/table_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,28 @@ defmodule HPAX.TableTest do
end

test "with an index in the static table" do
assert Table.lookup_by_index(Table.new(100, :never), 1) == {:ok, {":authority", ""}}
table = Table.new(100, :never)

for {header, index} <- Enum.with_index(Table.__static_table__(), 1) do
assert Table.lookup_by_index(table, index) == {:ok, header}
end
end

test "with an index in the dynamic table" do
table = Table.new(100, :never)
table = Table.add(table, "my-header", "my-value")
test "with shallow and deep indices in the dynamic table" do
dynamic_table_start = length(Table.__static_table__()) + 1

table =
Enum.reduce(1..64, Table.new(10_000, :never), fn index, table ->
Table.add(table, "header-#{index}", "value-#{index}")
end)

assert Table.lookup_by_index(table, dynamic_table_start) ==
{:ok, {"header-64", "value-64"}}

assert Table.lookup_by_index(table, dynamic_table_start + 63) ==
{:ok, {"header-1", "value-1"}}

assert Table.lookup_by_index(table, length(Table.__static_table__()) + 1) ==
{:ok, {"my-header", "my-value"}}
assert Table.lookup_by_index(table, dynamic_table_start + 64) == :error
end
end

Expand Down
Loading