47 lines
1.5 KiB
Elixir
47 lines
1.5 KiB
Elixir
defmodule UkraineTaxidEx.BaseParser do
|
|
@typedoc """
|
|
Options for parsing:
|
|
- `:normalize?` - if true, pad the string to the right length (8 for EDRPOU, 10 for ITIN)
|
|
- `:clean?` - if true, remove non-digit characters
|
|
"""
|
|
@type options :: [normalize?: boolean, clean?: boolean]
|
|
|
|
@callback parse(code :: String.t(), options :: options()) :: {:ok, term} | {:error, atom}
|
|
|
|
defmacro __using__(_) do
|
|
quote do
|
|
@behaviour UkraineTaxidEx.BaseParser
|
|
|
|
alias UkraineTaxidEx.BaseParser
|
|
|
|
@type string_or_ok() :: String.t() | {:ok, String.t()}
|
|
@type struct_or_error() :: {:ok, term} | {:error, atom()}
|
|
|
|
@struct_module Module.split(__MODULE__) |> Enum.slice(0..-2//1) |> Module.concat()
|
|
# def struct_module(), do: @struct_module
|
|
|
|
defp to_struct(map), do: struct(@struct_module, map)
|
|
|
|
@impl BaseParser
|
|
@spec parse(data :: string_or_ok, options :: BaseParser.options()) :: struct_or_error()
|
|
def parse(data, options \\ [normalize?: false, clean?: true])
|
|
def parse({:ok, string}, options), do: parse(string, options)
|
|
def parse({:error, error}, _options), do: {:error, error}
|
|
|
|
def parse(string, options) do
|
|
length = (Keyword.get(options, :normalize?, false) && length()) || 0
|
|
clean? = Keyword.get(options, :clean?, false)
|
|
|
|
string
|
|
|> digits(length, clean?)
|
|
|> undigits()
|
|
|> validate()
|
|
|> generate()
|
|
end
|
|
|
|
defp generate({:error, error}), do: {:error, error}
|
|
defp generate({:ok, string}), do: generate(string)
|
|
end
|
|
end
|
|
end
|