Browse Source

Add macaddr and macaddr8 types. #109

Сергей Прохоров 7 years ago
parent
commit
c56ce4a788
4 changed files with 23 additions and 6 deletions
  1. 14 5
      src/datatypes/epgsql_codec_net.erl
  2. 2 0
      src/epgsql_binary.erl
  3. 1 0
      test/data/test_schema.sql
  4. 6 1
      test/epgsql_SUITE.erl

+ 14 - 5
src/datatypes/epgsql_codec_net.erl

@@ -6,7 +6,6 @@
 %%% TIP: use `inet:ntoa/1' to convert `ip()' to string.
 %%% @end
 %%% Created : 12 Oct 2017 by Sergey Prokhorov <me@seriyps.ru>
-%% TODO: `macaddr', `macaddr8' `mac.c`
 -module(epgsql_codec_net).
 -behaviour(epgsql_codec).
 
@@ -14,11 +13,13 @@
 
 -export_type([data/0]).
 
--type data() :: ip() | ip_mask().
+-type data() :: ip() | ip_mask() | macaddr() | macaddr8().
 
 -type ip() :: inet:ip_address().
 -type mask() :: 0..32.
 -type ip_mask() :: {ip(), mask()}.
+-type macaddr() :: {byte(), byte(), byte(), byte(), byte(), byte()}.
+-type macaddr8() :: {byte(), byte(), byte(), byte(), byte(), byte(), byte(), byte()}.
 
 -define(INET, 2).
 -define(INET6, 3).
@@ -30,15 +31,23 @@
 init(_, _) -> [].
 
 names() ->
-    [inet, cidr].
+    [inet, cidr, macaddr, macaddr8].
 
+encode({B1, B2, B3, B4, B5, B6}, macaddr, _) ->
+    <<B1, B2, B3, B4, B5, B6>>;
+encode({B1, B2, B3, B4, B5, B6, B7, B8}, macaddr8, _) ->
+    <<B1, B2, B3, B4, B5, B6, B7, B8>>;
 encode(IpMask, _, _) ->
     encode_net(IpMask).
 
+decode(<<B1, B2, B3, B4, B5, B6>>, macaddr, _) ->
+    {B1, B2, B3, B4, B5, B6};
+decode(<<B1, B2, B3, B4, B5, B6, B7, B8>>, macaddr8, _) ->
+    {B1, B2, B3, B4, B5, B6, B7, B8};
 decode(Bin, _, _) ->
     decode_net(Bin).
 
--spec encode_net(data()) -> binary().
+-spec encode_net(ip() | ip_mask()) -> binary().
 encode_net({{_, _, _, _} = IP, Mask}) ->
     Bin = list_to_binary(tuple_to_list(IP)),
     <<?INET, Mask:8, 1, ?IP_SIZE, Bin/binary>>;
@@ -52,7 +61,7 @@ encode_net({_, _, _, _, _, _, _, _} = IP) ->
     Bin = << <<X:16>> || X <- tuple_to_list(IP) >>,
     <<?INET6, ?MAX_IP6_MASK, 0, ?IP6_SIZE, Bin/binary>>.
 
--spec decode_net(binary()) -> data().
+-spec decode_net(binary()) -> ip() | ip_mask().
 decode_net(<<?INET, Mask:8, 1, ?IP_SIZE, Bin/binary>>) ->
     {list_to_tuple(binary_to_list(Bin)), Mask};
 decode_net(<<?INET6, Mask:8, 1, ?IP6_SIZE, Bin/binary>>) ->

+ 2 - 0
src/epgsql_binary.erl

@@ -283,6 +283,8 @@ default_oids() ->
      {interval, 1186, 1187},
      {json, 114, 199},
      {jsonb, 3802, 3807},
+     {macaddr, 829, 1040},
+     {macaddr8, 774, 775},
      {point, 600, 1017},
      {text, 25, 1009},
      {time, 1083, 1183},

+ 1 - 0
test/data/test_schema.sql

@@ -60,6 +60,7 @@ CREATE TABLE test_table2 (
   c_geometry geometry,
   c_cidr cidr,
   c_inet inet,
+  c_macaddr macaddr,
   c_int4range int4range,
   c_int8range int8range,
   c_json json,

+ 6 - 1
test/epgsql_SUITE.erl

@@ -766,7 +766,12 @@ hstore_type(Config) ->
 
 net_type(Config) ->
     check_type(Config, cidr, "'127.0.0.1/32'", {{127,0,0,1}, 32}, [{{127,0,0,1}, 32}, {{0,0,0,0,0,0,0,1}, 128}]),
-    check_type(Config, inet, "'127.0.0.1'", {127,0,0,1}, [{127,0,0,1}, {0,0,0,0,0,0,0,1}]).
+    check_type(Config, inet, "'127.0.0.1'", {127,0,0,1}, [{127,0,0,1}, {0,0,0,0,0,0,0,1}]),
+    %% macaddr8 available only on PG>=10
+    check_type(Config, macaddr,
+               "'FF:FF:FF:FF:FF:FF'", {255, 255, 255, 255, 255, 255},
+               [{255, 255, 255, 255, 255, 255},
+                {6, 0, 0, 0, 0, 0}]).
 
 array_type(Config) ->
     Module = ?config(module, Config),