defmodule Wobserver.Table do @moduledoc ~S""" Table (ets) information and listing. """ import Wobserver.Util.Helper, only: [string_to_module: 1] @doc ~S""" Lists all tables with basic information. Note: data is not included. """ @spec list :: list(map) def list do :ets.all() |> Enum.map(&info/1) end @doc """ Creates an overview of table information based on the given `table` atom or number. If `include_data` is set to `true`, it will also contain the table data. """ @spec info(table :: :ets.table(), include_data :: boolean) :: map def info(table, include_data \\ false) def info(table, false) do %{ id: table, name: :ets.info(table, :name) |> otherwise(:code), type: :ets.info(table, :type) |> otherwise(:set), size: :ets.info(table, :size), memory: :ets.info(table, :memory), owner: :ets.info(table, :owner), protection: :ets.info(table, :protection) |> otherwise(:private), meta: %{ read_concurrency: :ets.info(table, :read_concurrency) |> otherwise(false), write_concurrency: :ets.info(table, :write_concurrency) |> otherwise(false), compressed: :ets.info(table, :compressed) |> otherwise(false) } } end def info(table, true) do table |> info(false) |> Map.put(:data, data(table)) end @doc ~S""" Sanitizes a `table` name and returns either the table id or name. Example: ```bash iex> Wobserver.Table.sanitize :code :code ``` ```bash iex> Wobserver.Table.sanitize 1 1 ``` ```bash iex> Wobserver.Table.sanitize "code" :code ``` ```bash iex> Wobserver.Table.sanitize "1" 1 ``` """ @spec sanitize(table :: atom | integer | String.t()) :: atom | integer def sanitize(table) when is_atom(table), do: table def sanitize(table) when is_integer(table), do: table def sanitize(table) when is_binary(table) do case Integer.parse(table) do {nr, ""} -> nr _ -> table |> string_to_module() end end # Helpers defp otherwise(value1, value2) do case value1 do :undefined -> value2 _ -> value1 end end defp data(table) do case :ets.info(table, :protection) do :undefined -> [] :private -> [] _ -> table |> :ets.match(:"$1") |> Enum.map(&data_row/1) end end defp data_row([row]) do row |> Tuple.to_list() |> Enum.map(&to_string(:io_lib.format("~tp", [&1]))) end end