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 :: atom | integer, include_data :: boolean) :: map def info(table, include_data \\ false) def info(table, false) do %{ id: table, name: :ets.info(table, :name), type: :ets.info(table, :type), size: :ets.info(table, :size), memory: :ets.info(table, :memory), owner: :ets.info(table, :owner), protection: :ets.info(table, :protection), meta: %{ read_concurrency: :ets.info(table, :read_concurrency), write_concurrency: :ets.info(table, :write_concurrency), compressed: :ets.info(table, :compressed), }, } 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 data(table) do case :ets.info(table, :protection) do :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