defmodule Irc.Mask do alias Irc.Addressable @type t :: %__MODULE__{nick: nil | String.t(), user: nil | String.t(), host: nil | String.t(), server: nil | String.t()} defstruct [:nick, :user, :host, :server, {:__private__, %{owner: nil, owner_module: nil}}] @spec parse(String.t) :: {:ok, t()} | {:error, :invalid_mask} def parse(string) do cond do String.contains?(string, "!") -> parse_user_mask(string) String.contains?(string, ".") -> parse_server_mask(string) true -> {:error, :invalid_mask} end end def parse(string, module, pid) do case parse(string) do {:ok, x} -> {:ok, set_owner(x, module, pid)} error -> error end end @spec equal?(Addressable.t(), Addressable.t()) :: boolean def equal?(a, b) do import Addressable (owner(a) == owner(b)) && (nick(a) == nick(b)) end def from_addressable(addressable) do import Addressable new(nick(addressable), user(addressable), host(addressable) ) |> set_owner(owner_module(addressable), owner(addressable)) end def new(nick, user, host) do %__MODULE__{nick: nick, user: user, host: host} end def set_owner(t = %{__private__: private = %{owner: nil, owner_module: nil}}, module, pid) when is_atom(module) and is_pid(pid) do private = private |> Map.put(:owner, pid) |> Map.put(:owner_module, module) %{t | __private__: private} end def to_string(%__MODULE__{server: nil, nick: nick, user: user, host: host}) do Enum.join([nick, "!", user, "@", host]) end def to_string(%__MODULE__{server: server}), do: server defp parse_user_mask(string) do case String.split(string, ~r/[!@]/, parts: 3) do [nick, user, host] -> {:ok, %__MODULE__{nick: nick, user: user, host: host}} _ -> {:error, :invalid_mask} end end defp parse_server_mask(string) do {:ok, %__MODULE__{server: string}} end defimpl String.Chars, for: __MODULE__ do @moduledoc false defdelegate to_string(struct), to: Irc.Mask end defimpl Irc.Addressable, for: __MODULE__ do def nick(%{nick: nick}), do: nick def user(%{user: user}), do: user def host(%{host: host}), do: host end defimpl Inspect, for: __MODULE__ do @moduledoc false import Inspect.Algebra def inspect(struct, _opts) do concat(["#Irc.Mask<", Irc.Mask.to_string(struct), ">"]) end end end