Created
April 6, 2018 12:27
-
-
Save seivan/f3b7ef2792ffc0024f76f7e0e1ae91c3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Tiled.Utils.Decoder do | |
@moduledoc false | |
defmodule InternalDecoder do | |
@moduledoc false | |
defmacro __before_compile__(_env) do | |
quote do | |
@spec decode_key_value({:type, String.t()}) :: atom() | nil | |
defp decode_key_value({:type, ""}), do: nil | |
defp decode_key_value({:type, type}) when is_binary(type), do: type |> String.to_atom() | |
@spec decode_key_value({:name, String.t()}) :: atom() | nil | |
defp decode_key_value({:name, ""}), do: nil | |
defp decode_key_value({:name, name}) when is_binary(name), do: name |> String.to_atom() | |
@spec decode_key_value({:properties, map() | nil}) :: Tiled.property_values() | |
defp decode_key_value({:properties, properties}), do: properties || %{} | |
@spec decode_key_value({:property_types, map() | nil}) :: Tiled.property_types() | |
defp decode_key_value({:property_types, types}), do: types || %{} | |
defp decode_key_value({key, _} = key_value) when is_atom(key), do: key_value | |
end | |
end | |
end | |
defmacro __using__(_) do | |
quote do | |
@before_compile InternalDecoder | |
@spec decode(map(), ({atom(), term()} -> {atom(), term()} | term())) :: struct() | |
defp decode(map, transformer \\ & &1) when is_map(map) and is_function(transformer, 1) do | |
module = __MODULE__ | |
module | |
|> struct | |
|> Map.from_struct() | |
|> Map.keys() | |
|> Enum.reduce(%{}, fn key, memo -> | |
json_key = downcase_key(key) | |
case transformer.({key, map[json_key]}) do | |
{new_key, value} -> Map.put(memo, new_key, value) | |
value -> Map.put(memo, key, value) | |
end | |
end) | |
|> (fn map -> struct(module, map) end).() | |
end | |
@spec downcase_key(atom() | String.t()) :: atom() | |
defp downcase_key(key) when is_atom(key), | |
do: key |> Atom.to_string() |> Macro.camelize() |> String.downcase() |> String.to_atom() | |
defp downcase_key(key) when is_binary(key), | |
do: key |> Macro.camelize() |> String.downcase() |> String.to_atom() | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Tiled.TileMap do | |
alias Tiled.Utils.{Decoder, TypedStruct} | |
use Decoder | |
use TypedStruct, | |
background_color: String.t() | nil, | |
height: integer, | |
infinite: boolean, | |
layers: list(Tiled.Layer.TileLayer), | |
next_object_id: integer, | |
orientation: :orthogonal | :isometric, | |
properties: Tiled.property_values(), | |
property_types: Tiled.property_types(), | |
render_order: :left_up | :right_up | :right_down | :left_down, | |
tiled_version: String.t(), | |
tile_height: integer, | |
tile_sets: list(Tiled.TileSet.File | Tiled.TileSet.Embedded | Tiled.TileSet.ImageLayer), | |
tile_width: integer, | |
type: :map, | |
version: integer, | |
width: integer | |
@spec new(map()) :: t() | |
def new(raw_map) when is_map(raw_map), do: raw_map |> decode(&decode_key_value/1) | |
defp decode_key_value({:tile_sets, tilesets}) when is_list(tilesets), | |
do: tilesets |> Enum.map(&Tiled.TileSet.new/1) | |
defp decode_key_value({:layers, layers}) when is_list(layers), | |
do: layers |> Enum.map(&Tiled.Layer.new/1) | |
defp decode_key_value({:orientation, orientation}) when is_binary(orientation), | |
do: orientation |> String.to_atom() | |
defp decode_key_value({:render_order, render_order}) when is_binary(render_order), | |
do: render_order |> String.replace("-", "_") |> String.to_atom() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment