Skip to content

Commit 004abcc

Browse files
committed
Simplify Cast.Enum by generalizing equivalent?/2 function
Enum.find a value in the Schema.enum that satisfies equivalent?
1 parent 72bb633 commit 004abcc

File tree

1 file changed

+14
-32
lines changed

1 file changed

+14
-32
lines changed

lib/open_api_spex/cast/enum.ex

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,29 @@ defmodule OpenApiSpex.Cast.Enum do
22
@moduledoc false
33
alias OpenApiSpex.Cast
44

5-
def cast(%Cast{schema: %{enum: []}} = ctx) do
6-
Cast.error(ctx, {:invalid_enum})
7-
end
8-
9-
def cast(%Cast{schema: %{enum: [value | _]}, value: value}) do
10-
{:ok, value}
11-
end
12-
13-
# Special case: convert binary to atom enum
14-
def cast(ctx = %Cast{schema: schema = %{enum: [atom_value | tail]}, value: value})
15-
when is_binary(value) and is_atom(atom_value) do
16-
if value == to_string(atom_value) do
17-
{:ok, atom_value}
18-
else
19-
cast(%{ctx | schema: %{schema | enum: tail}})
5+
def cast(ctx = %Cast{schema: %{enum: enum}, value: value}) do
6+
case Enum.find(enum, {:error, :invalid_enum}, &equivalent?(&1, value)) do
7+
{:error, :invalid_enum} -> Cast.error(ctx, {:invalid_enum})
8+
found -> {:ok, found}
209
end
2110
end
2211

23-
# Special case: convert string-keyed map to atom-keyed map enum
24-
def cast(ctx = %Cast{schema: schema = %{enum: [enum_map = %{} | tail]}, value: value = %{}}) do
25-
if maps_equivalent?(value, enum_map) do
26-
{:ok, enum_map}
27-
else
28-
cast(%{ctx | schema: %{schema | enum: tail}})
29-
end
30-
end
12+
defp equivalent?(x, x), do: true
3113

32-
def cast(ctx = %Cast{schema: schema = %{enum: [_ | tail]}}) do
33-
cast(%{ctx | schema: %{schema | enum: tail}})
14+
# Special case: atoms are equivalent to their stringified representation
15+
defp equivalent?(left, right) when is_atom(left) and is_binary(right) do
16+
to_string(left) == right
3417
end
3518

36-
defp maps_equivalent?(x, x), do: true
37-
3819
# an explicit schema should be used to cast to enum of structs
39-
defp maps_equivalent?(_left, %_struct{}), do: false
20+
defp equivalent?(_x, %_struct{}), do: false
4021

41-
defp maps_equivalent?(left = %{}, right = %{}) when map_size(left) == map_size(right) do
42-
Enum.all?(right, fn {k, v} ->
43-
maps_equivalent?(Map.get(left, to_string(k)), v)
22+
# Special case: Atom-keyed maps are equivalent to their string-keyed representation
23+
defp equivalent?(left, right) when is_map(left) and is_map(right) do
24+
Enum.all?(left, fn {k, v} ->
25+
equivalent?(v, Map.get(right, to_string(k)))
4426
end)
4527
end
4628

47-
defp maps_equivalent?(_left, _right), do: false
29+
defp equivalent?(_left, _right), do: false
4830
end

0 commit comments

Comments
 (0)