# `Macaw.Plug.Ip`
[🔗](https://github.com/dcoai/macaw_plug/blob/v0.1.4/lib/macaw/plug/ip.ex#L1)

IP addresses and CIDR blocks: parsing, membership and normalization.

An IPv4 address that arrives in IPv4-mapped IPv6 form (`::ffff:203.0.113.5`,
as a dual-stack listener can report its peer) is normalized to its IPv4
form, so a trusted IPv4 proxy matches however the socket reported it.

# `cidr`

```elixir
@type cidr() :: {ip(), 0..128}
```

# `ip`

```elixir
@type ip() :: :inet.ip_address()
```

# `in_any?`

```elixir
@spec in_any?(ip(), [cidr()]) :: boolean()
```

Whether `ip` is in any of the CIDRs.

# `in_cidr?`

```elixir
@spec in_cidr?(ip(), cidr()) :: boolean()
```

Whether `ip` is in the CIDR `{network, prefix}`. Families never match each other.

# `normalize`

```elixir
@spec normalize(ip()) :: ip()
```

An IPv4-mapped IPv6 address as its IPv4 form; any other address unchanged.

# `parse`

```elixir
@spec parse(String.t()) :: ip() | nil
```

Parses an address string to a normalized tuple, or returns nil.

# `parse_cidr`

```elixir
@spec parse_cidr(String.t()) :: {:ok, cidr()} | {:error, String.t()}
```

Parses a CIDR (`"10.0.0.0/8"`, `"2001:db8::/32"`) or a single address
(`"192.0.2.1"`, a /32 or /128) to `{network, prefix}`, or returns an error
naming what is wrong.

# `to_string`

```elixir
@spec to_string(ip()) :: String.t()
```

Formats an address.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
