|
| 1 | +defmodule AtomicMap.Opts do |
| 2 | + @moduledoc ~S""" |
| 3 | + Set any value to `false` to disable checking for that kind of key. |
| 4 | + """ |
| 5 | + defstruct safe: true, |
| 6 | + underscore: true |
| 7 | +end |
| 8 | + |
1 | 9 | defmodule AtomicMap do |
| 10 | + def convert(v, opts \\ %{}) |
2 | 11 |
|
3 | | - def convert(v, opts \\ []) |
4 | | - def convert(struct=%{__struct__: type}, opts) do |
| 12 | + def convert(struct=%{__struct__: type}, opts=%AtomicMap.Opts{}) do |
5 | 13 | struct |
6 | 14 | |> Map.from_struct |
7 | 15 | |> convert(opts) |
8 | 16 | |> Map.put(:__struct__, type) |
9 | 17 | end |
10 | | - def convert(map, opts) when is_map(map) do |
11 | | - safe = Keyword.get(opts, :safe, true) |
| 18 | + def convert(map, opts=%AtomicMap.Opts{}) when is_map(map) do |
12 | 19 | map |> Enum.reduce(%{}, fn({k,v}, acc)-> |
13 | | - k = as_atom(k, safe) |
14 | | - v = convert(v, opts) |
| 20 | + k = k |> convert_key(opts) |
| 21 | + v = v |> convert(opts) |
15 | 22 | acc |> Map.put(k, v) |
16 | 23 | end) |
17 | 24 | end |
18 | | - def convert(list, opts) when is_list(list) do |
| 25 | + def convert(list, opts=%AtomicMap.Opts{}) when is_list(list) do |
19 | 26 | list |> Enum.map(fn(x)-> convert(x, opts) end) |
20 | 27 | end |
21 | | - def convert(tuple, opts) when is_tuple(tuple) do |
| 28 | + def convert(tuple, opts=%AtomicMap.Opts{}) when is_tuple(tuple) do |
22 | 29 | tuple |> Tuple.to_list |> convert(opts) |> List.to_tuple |
23 | 30 | end |
24 | | - def convert(v, _opts), do: v |
| 31 | + def convert(v, _opts=%AtomicMap.Opts{}), do: v |
| 32 | + |
| 33 | + # if you pass a plain map or keyword list as opts, those will match and convert it to struct |
| 34 | + def convert(v, opts=%{}), do: convert(v, struct(AtomicMap.Opts, opts)) |
| 35 | + def convert(v, opts) when is_list(opts), do: convert(v, Enum.into(opts, %{})) |
| 36 | + |
| 37 | + defp convert_key(k, opts) do |
| 38 | + k |
| 39 | + |> as_underscore(opts.underscore) |
| 40 | + |> as_atom(opts.safe) |
| 41 | + end |
| 42 | + |
| 43 | + defp as_atom(s, true) when is_binary(s), do: s |> String.to_existing_atom |
| 44 | + defp as_atom(s, false) when is_binary(s), do: s |> String.to_atom |
| 45 | + defp as_atom(s, _), do: s |
25 | 46 |
|
26 | | - defp as_atom(s, true) when is_binary(s), do: s |> String.to_existing_atom |
27 | | - defp as_atom(s, false) when is_binary(s), do: s |> String.to_atom |
28 | | - defp as_atom(s, _), do: s |
| 47 | + def as_underscore(s, true) when is_binary(s), do: s |> Macro.underscore |
| 48 | + def as_underscore(s, true) when is_atom(s), do: s |> Atom.to_string |> as_underscore(true) |
| 49 | + def as_underscore(s, false), do: s |
29 | 50 | end |
0 commit comments