Skip to content

Commit

Permalink
Utilities for converting Lua tables into Elixir datastructures (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
davydog187 authored Mar 18, 2024
1 parent ce8fdf7 commit f4023aa
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
76 changes: 76 additions & 0 deletions lib/lua/table.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
defmodule Lua.Table do
@moduledoc """
In Lua, [tables](https://www.lua.org/pil/2.5.html) are the fundamental datastructure,
which are used both as associative arrays (maps), and arrays (lists).
`Lua.Table` provides some utilities for working with Lua tables when passed back to
Elixir.
"""

@doc """
Converts a Lua table into a list. Assumes that the
table is correctly ordered.
iex> Lua.Table.as_list([{1, "a"}, {2, "b"}, {3, "c"}])
["a", "b", "c"]
To ensure the list is ordered, you can pass the `:sort` option
iex> Lua.Table.as_list([{2, "b"}, {1, "a"}, {3, "c"}])
["b", "a", "c"]
iex> Lua.Table.as_list([{2, "b"}, {1, "a"}, {3, "c"}], sort: true)
["a", "b", "c"]
"""
def as_list(values, opts \\ []) do
opts = Keyword.validate!(opts, sort: false)

sorter =
if Keyword.fetch!(opts, :sort) do
&List.keysort(&1, 0)
else
&Function.identity/1
end

values
|> sorter.()
|> Enum.map(fn {_, v} -> v end)
end

@doc """
Converts a Lua table into a map
iex> Lua.Table.as_map([{"a", 1}, {"b", 2}])
%{"a" => 1, "b" => 2}
"""
def as_map(values) do
Map.new(values)
end

@doc """
Converts a Lua table into more "native" feeling lists and
maps, deeply traversing any sub-tables.
It uses the heuristic that maps with integer keys starting
as 1 will be auto-cast into lists
iex> Lua.Table.deep_cast([{"a", 1}, {"b", [{1, 3}, {2, 4}]}])
%{"a" => 1, "b" => [3, 4]}
"""
def deep_cast(value) do
case value do
[{1, _val} | _rest] = list ->
Enum.map(list, fn
{_, v} when is_list(v) -> deep_cast(v)
{_, v} -> v
end)

map ->
Map.new(map, fn
{k, v} when is_list(v) -> {k, deep_cast(v)}
{k, v} -> {k, v}
end)
end
end
end
2 changes: 1 addition & 1 deletion test/lua/api_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Lua.APITest do
use ExUnit.Case
use ExUnit.Case, async: true

alias Lua

Expand Down
5 changes: 5 additions & 0 deletions test/lua/table_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule Lua.TableTest do
use ExUnit.Case, async: true

doctest Lua.Table
end
2 changes: 1 addition & 1 deletion test/lua/util_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Lua.UtilTest do
use ExUnit.Case
use ExUnit.Case, async: true

doctest Lua.Util, import: true

Expand Down

0 comments on commit f4023aa

Please sign in to comment.