-
Notifications
You must be signed in to change notification settings - Fork 19
/
macaddr.ex
69 lines (55 loc) · 1.91 KB
/
macaddr.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
defmodule EctoNetwork.MACADDR do
@moduledoc ~S"""
Support for using Ecto with `:macaddr` fields.
"""
@behaviour Ecto.Type
@type t :: Postgrex.MACADDR.t()
def type, do: :macaddr
@doc "Handle embedding format for CIDR records."
def embed_as(_), do: :self
@doc "Handle equality testing for CIDR records."
def equal?(left, right), do: left == right
@doc "Handle casting to Postgrex.MACADDR."
def cast(%Postgrex.MACADDR{} = address), do: {:ok, address}
def cast(address) when is_binary(address) do
with [a, b, c, d, e, f] <- parse_address(address) do
{:ok, %Postgrex.MACADDR{address: {a, b, c, d, e, f}}}
end
end
@doc "Load from the native Ecto representation."
def load(%Postgrex.MACADDR{} = address), do: {:ok, address}
def load(_), do: :error
@doc "Convert to the native Ecto representation."
def dump(%Postgrex.MACADDR{} = address), do: {:ok, address}
def dump(_), do: :error
@doc "Convert from native Ecto representation to a binary."
def decode(%Postgrex.MACADDR{address: {a, b, c, d, e, f}}) do
[a, b, c, d, e, f]
|> Enum.map(&Integer.to_string(&1, 16))
|> Enum.map(&String.pad_leading(&1, 2, "0"))
|> Enum.join(":")
end
defp parse_address(address) do
with split when length(split) == 6 <- String.split(address, ":"),
[_ | _] = parsed <- Enum.reduce_while(split, [], &parse_octet/2) do
Enum.reverse(parsed)
else
_ -> :error
end
end
defp parse_octet(octet, acc) do
with {int, ""} <- Integer.parse(octet, 16) do
{:cont, [int | acc]}
else
_ -> {:halt, :error}
end
end
end
defimpl String.Chars, for: Postgrex.MACADDR do
def to_string(%Postgrex.MACADDR{} = address), do: EctoNetwork.MACADDR.decode(address)
end
if Code.ensure_loaded?(Phoenix.HTML) do
defimpl Phoenix.HTML.Safe, for: Postgrex.MACADDR do
def to_iodata(%Postgrex.MACADDR{} = address), do: EctoNetwork.MACADDR.decode(address)
end
end