From 0c0039ab3a46899539bea616512e57933a37c889 Mon Sep 17 00:00:00 2001 From: Dave Lucia Date: Wed, 4 Jun 2025 07:34:43 -0400 Subject: [PATCH 1/2] feat(table): function for choosing how to encode empty table values --- lib/lua/table.ex | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/lua/table.ex b/lib/lua/table.ex index e1acd0d..fc2fe38 100644 --- a/lib/lua/table.ex +++ b/lib/lua/table.ex @@ -157,19 +157,47 @@ defmodule Lua.Table do iex> Lua.Table.deep_cast([{"a", 1}, {"b", [{1, 3}, {2, 4}]}]) %{"a" => 1, "b" => [3, 4]} + + iex> Lua.Table.deep_cast([{"a", []}], empty_as: :map) + %{"a" => %{}} + + iex> Lua.Table.deep_cast([{"a", []}], empty_as: :list) + %{"a" => %{}} + + ## Opts + * `:empty_encoder` - a function that receives a key and decides how it should be encoded. Top level + keys are passed as nil. Defaults to a function that returns maps """ - def deep_cast(value) do + def deep_cast(value, opts \\ []) do + do_deep_cast(value, Keyword.get(opts, :empty_encoder, fn _ -> %{} end)) + end + + defp do_deep_cast(value, empty_encoder) do case value do [{1, _val} | _rest] = list -> Enum.map(list, fn - {_, v} when is_list(v) -> deep_cast(v) - {_, v} -> v + {k, v} when is_list(v) -> + case v do + [] -> empty_encoder.(k) + v -> do_deep_cast(v, empty_encoder) + end + + {_, v} -> + v end) map -> Map.new(map, fn - {k, v} when is_list(v) -> {k, deep_cast(v)} - {k, v} -> {k, v} + {k, v} when is_list(v) -> + {k, deep_cast(v)} + + case v do + [] -> {k, empty_encoder.(k)} + v -> {k, do_deep_cast(v, empty_encoder)} + end + + {k, v} -> + {k, v} end) end end From 581938bd9b48198d69145c9ace17e27e6c832aac Mon Sep 17 00:00:00 2001 From: Dave Lucia Date: Wed, 4 Jun 2025 07:42:05 -0400 Subject: [PATCH 2/2] fix docs --- lib/lua/table.ex | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/lua/table.ex b/lib/lua/table.ex index fc2fe38..1c8a739 100644 --- a/lib/lua/table.ex +++ b/lib/lua/table.ex @@ -158,18 +158,20 @@ defmodule Lua.Table do iex> Lua.Table.deep_cast([{"a", 1}, {"b", [{1, 3}, {2, 4}]}]) %{"a" => 1, "b" => [3, 4]} - iex> Lua.Table.deep_cast([{"a", []}], empty_as: :map) - %{"a" => %{}} + iex> Lua.Table.deep_cast([{"a", []}], empty_encoder: fn _ -> [] end) + %{"a" => []} - iex> Lua.Table.deep_cast([{"a", []}], empty_as: :list) - %{"a" => %{}} + iex> Lua.Table.deep_cast([{"a", []}, {"b", []}], empty_encoder: fn "a" -> []; "b" -> %{} end) + %{"a" => [], "b" => %{}} ## Opts * `:empty_encoder` - a function that receives a key and decides how it should be encoded. Top level keys are passed as nil. Defaults to a function that returns maps """ def deep_cast(value, opts \\ []) do - do_deep_cast(value, Keyword.get(opts, :empty_encoder, fn _ -> %{} end)) + opts = Keyword.validate!(opts, empty_encoder: fn _ -> %{} end) + + do_deep_cast(value, Keyword.fetch!(opts, :empty_encoder)) end defp do_deep_cast(value, empty_encoder) do