104 lines
3.2 KiB
Elixir
104 lines
3.2 KiB
Elixir
|
defmodule IP.Sigil do
|
||
|
alias IP.{Prefix, Address}
|
||
|
alias IP.Sigil.InvalidValue
|
||
|
|
||
|
@moduledoc """
|
||
|
Provides the `~i` sigil.
|
||
|
|
||
|
You can use with `import IP.Sigil` or `use IP`.
|
||
|
|
||
|
Valid modifiers are `f` to parse specifically as an IPv4 value, and `s` to
|
||
|
parse specifically as an IPv6 value. As a side note, digits can't be used as
|
||
|
sigil modifiers. Ask me how I know.
|
||
|
|
||
|
`~i` will raise `IP.Sigil.InvalidValue` in the event of a parsing failure.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> ~i(192.0.2.1/32)
|
||
|
#IP.Prefix<192.0.2.1/32 DOCUMENTATION>
|
||
|
|
||
|
iex> ~i(192.0.2.1)f
|
||
|
#IP.Address<192.0.2.1 DOCUMENTATION>
|
||
|
|
||
|
iex> ~i(2001:db8::/32)
|
||
|
#IP.Prefix<2001:db8::/32 DOCUMENTATION>
|
||
|
|
||
|
iex> ~i(2001:db8::/32)s
|
||
|
#IP.Prefix<2001:db8::/32 DOCUMENTATION>
|
||
|
"""
|
||
|
|
||
|
@doc """
|
||
|
Implements `sigil_i` for parsing IP addresses and prefixes.
|
||
|
|
||
|
* `value` is a string which will be passed to `IP.Prefix.from_string` and
|
||
|
`IP.Address.from_string` sequentially.
|
||
|
|
||
|
* `options` is a charlist of flags provided to the sigil. Valid flags are:
|
||
|
- `f` parse string specifically as an IPv4 value.
|
||
|
- `s` parse string specifically as an IPv6 value.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> IP.Sigil.sigil_i("192.0.2.1", '')
|
||
|
#IP.Address<192.0.2.1 DOCUMENTATION>
|
||
|
|
||
|
iex> IP.Sigil.sigil_i("192.0.2.0/24", '')
|
||
|
#IP.Prefix<192.0.2.0/24 DOCUMENTATION>
|
||
|
|
||
|
iex> IP.Sigil.sigil_i("2001:db8::/32", '')
|
||
|
#IP.Prefix<2001:db8::/32 DOCUMENTATION>
|
||
|
|
||
|
iex> IP.Sigil.sigil_i("2001:db8::", '')
|
||
|
#IP.Address<2001:db8:: DOCUMENTATION>
|
||
|
|
||
|
iex> IP.Sigil.sigil_i("Marty McFly", '')
|
||
|
** (IP.Sigil.InvalidValue) Unable to parse "Marty McFly" as an IP address or prefix.
|
||
|
|
||
|
iex> IP.Sigil.sigil_i("192.0.2.1", 'f')
|
||
|
#IP.Address<192.0.2.1 DOCUMENTATION>
|
||
|
|
||
|
iex> IP.Sigil.sigil_i("2001:db8::/32", 'f')
|
||
|
** (IP.Sigil.InvalidValue) Unable to parse "2001:db8::/32" as an IPv4 address or prefix.
|
||
|
|
||
|
iex> IP.Sigil.sigil_i("192.0.2.1", 's')
|
||
|
** (IP.Sigil.InvalidValue) Unable to parse "192.0.2.1" as an IPv6 address or prefix.
|
||
|
|
||
|
iex> IP.Sigil.sigil_i("2001:db8::/32", 's')
|
||
|
#IP.Prefix<2001:db8::/32 DOCUMENTATION>
|
||
|
"""
|
||
|
@spec sigil_i(binary, [non_neg_integer]) :: Prefix.t | Address.t
|
||
|
def sigil_i(value, '' = _options) do
|
||
|
case Prefix.from_string(value) do
|
||
|
{:ok, prefix} -> prefix
|
||
|
{:error, _} ->
|
||
|
case Address.from_string(value) do
|
||
|
{:ok, address} -> address
|
||
|
{:error, _} -> raise(InvalidValue, message: "Unable to parse #{inspect value} as an IP address or prefix.")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def sigil_i(value, 'f' = _options) do
|
||
|
case Prefix.from_string(value, 4) do
|
||
|
{:ok, prefix} -> prefix
|
||
|
{:error, _} ->
|
||
|
case Address.from_string(value, 4) do
|
||
|
{:ok, address} -> address
|
||
|
{:error, _} -> raise(InvalidValue, message: "Unable to parse #{inspect value} as an IPv4 address or prefix.")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def sigil_i(value, 's' = _options) do
|
||
|
case Prefix.from_string(value, 6) do
|
||
|
{:ok, prefix} -> prefix
|
||
|
{:error, _} ->
|
||
|
case Address.from_string(value, 6) do
|
||
|
{:ok, address} -> address
|
||
|
{:error, _} -> raise(InvalidValue, message: "Unable to parse #{inspect value} as an IPv6 address or prefix.")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|