From 13bf9cb6a3f7d3f4371a2f3be3e59ac3d04dad02 Mon Sep 17 00:00:00 2001 From: James Harton Date: Wed, 4 Oct 2023 10:07:03 +1300 Subject: [PATCH] improvement: Add `IP.Address.to_tuple/1`. --- lib/ip/address.ex | 61 ++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/lib/ip/address.ex b/lib/ip/address.ex index cff81f2..9971e50 100644 --- a/lib/ip/address.ex +++ b/lib/ip/address.ex @@ -289,6 +289,42 @@ defmodule IP.Address do end end + @doc """ + Convert an `address` into an Erlang-style tuple. + + ## Examples + + iex> ~i(192.0.2.1) + ...> |> IP.Address.to_tuple() + {192, 0, 2, 1} + + iex> ~i(2001:db8::1) + ...> |> IP.Address.to_tuple() + {8193, 3512, 0, 0, 0, 0, 0, 1} + """ + @spec to_tuple(t) :: :socket.in_addr() | :socket.in6_addr() + def to_tuple(%Address{version: 4, address: addr}) do + a = addr >>> 0x18 &&& 0xFF + b = addr >>> 0x10 &&& 0xFF + c = addr >>> 0x08 &&& 0xFF + d = addr &&& 0xFF + + {a, b, c, d} + end + + def to_tuple(%Address{version: 6, address: addr}) do + a = addr >>> 0x70 &&& 0xFFFF + b = addr >>> 0x60 &&& 0xFFFF + c = addr >>> 0x50 &&& 0xFFFF + d = addr >>> 0x40 &&& 0xFFFF + e = addr >>> 0x30 &&& 0xFFFF + f = addr >>> 0x20 &&& 0xFFFF + g = addr >>> 0x10 &&& 0xFFFF + h = addr &&& 0xFFFF + + {a, b, c, d, e, f, g, h} + end + @doc """ Convert an `address` into a string. @@ -303,28 +339,9 @@ defmodule IP.Address do "2001:db8::1" """ @spec to_string(t) :: binary - def to_string(%Address{version: 4, address: addr}) do - a = addr >>> 0x18 &&& 0xFF - b = addr >>> 0x10 &&& 0xFF - c = addr >>> 0x08 &&& 0xFF - d = addr &&& 0xFF - - {a, b, c, d} - |> :inet.ntoa() - |> List.to_string() - end - - def to_string(%Address{version: 6, address: addr}) do - a = addr >>> 0x70 &&& 0xFFFF - b = addr >>> 0x60 &&& 0xFFFF - c = addr >>> 0x50 &&& 0xFFFF - d = addr >>> 0x40 &&& 0xFFFF - e = addr >>> 0x30 &&& 0xFFFF - f = addr >>> 0x20 &&& 0xFFFF - g = addr >>> 0x10 &&& 0xFFFF - h = addr &&& 0xFFFF - - {a, b, c, d, e, f, g, h} + def to_string(address) do + address + |> to_tuple() |> :inet.ntoa() |> List.to_string() end