From d42329c948cafec31250c8cdba028d116a76a709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Sloth=20T=C3=B8nnesen?= Date: Fri, 19 Jul 2019 21:43:02 +0000 Subject: add inet:bits() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Asbjørn Sloth Tønnesen --- README.rst | 28 ++++++++++++++++++++++++++++ lua/inet/core.lua | 33 +++++++++++++++++++++++++++++++++ test/inet.lua | 9 +++++++++ 3 files changed, 70 insertions(+) diff --git a/README.rst b/README.rst index 5698887..3bbb9c4 100644 --- a/README.rst +++ b/README.rst @@ -82,6 +82,7 @@ Operator Description ``:netmask()`` generate netmask as an address ``:hostmask()`` generate hostmask as an address ``:flip()`` flip the least significant network bit +``:bits()`` return the address bits in a table ================= ====================================== @@ -369,6 +370,33 @@ Like ``tostring(foo)``, but never uses mixed notation. inet('::ffff:192.0.2.24'):ipstring() -- returns '::ffff:192.0.2.24' inet('::ffff:192.0.2.24'):ipstring6() -- returns '::ffff:c000:218' + +``foo:bits(n)`` +~~~~~~~~~~~~~~~ + +Return the IP as a table with elements of ``n`` bits each. + +Valid values for ``n`` are ``1``, ``2``, ``4``, ``8``, ``16`` or ``32``. + +:: + + inet('192.0.2.24'):bits(32) -- returns { 3221226008 } + inet('192.0.2.24'):bits(16) -- returns { 49152, 536 } + inet('192.0.2.24'):bits(8) -- returns { 192, 0, 2, 24 } + inet('192.0.2.24'):bits(4) -- returns { 12, 0, 0, 0, 0, 2, 1, 8 } + inet('192.0.2.24'):bits(1) -- returns + { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0 } + + inet('2001:db8::42/64'):bits(32) -- returns { 536939960, 0, 0, 66 } + inet('::ffff:192.0.2.24'):bits(32) -- returns { 0, 0, 65535, 3221226008 } + inet('2001:db8::42/64'):bits(16) -- returns { 8193, 3512, 0, 0, 0, 0, 0, 66 } + inet('2001:db8::42/64'):bits(8) -- returns + { 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66 } + inet('2001:db8::42/64'):bits(4) -- returns + { 2, 0, 0, 1, 0, 13, 11, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2 } + Sets ---- diff --git a/lua/inet/core.lua b/lua/inet/core.lua index a91dacd..f1c7c49 100644 --- a/lua/inet/core.lua +++ b/lua/inet/core.lua @@ -6,10 +6,12 @@ local format = string.format local floor = math.floor local min = math.min local max = math.max +local insert = table.insert local lshift = bit32.lshift local rshift = bit32.rshift local band = bit32.band +local extract = bit32.extract local replace = bit32.replace local bxor = bit32.bxor @@ -403,6 +405,17 @@ function inet4:flip() return new_inet4(bxor(self.bip, flipbit), mask) end +function inet4:bits(n) + if type(n) ~= 'number' then return nil, 'n must be a number' end + if n < 1 or n > 32 or 32 % n ~= 0 then return nil, 'invalid value for n' end + local t = {} + local bip = self.bip + for i=32-n,0,-n do + insert(t, extract(bip, i, n)) + end + return t +end + -- each ipv6 address is stored as eight pieces -- 1111:2222:3333:4444:5555:6666:7777:8888 -- in the table pcs. @@ -789,6 +802,26 @@ function inet6:__mul(n) return new:balance() end +function inet6:bits(n) + if type(n) ~= 'number' then return nil, 'n must be a number' end + if n < 1 or n > 32 or 128 % n ~= 0 then return nil, 'invalid value for n' end + local t = {} + local pcs = self.pcs + if n == 32 then + for i=1,8,2 do + insert(t, lshift(pcs[i], 16) + pcs[i+1]) + end + else + for i=1,8 do + local p = pcs[i] + for j=16-n,0,-n do + insert(t, extract(p, j, n)) + end + end + end + return t +end + local M = {} function M.set_mixed_networks(mixed_set) diff --git a/test/inet.lua b/test/inet.lua index dd90fef..b974179 100644 --- a/test/inet.lua +++ b/test/inet.lua @@ -296,6 +296,15 @@ local function misc() assert(inet('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff') + 1 == nil) assert(inet('0.0.0.0/24') * -1 == nil) assert(inet('255.255.255.0/24') * 1 == nil) + + assert(inet('192.0.2.24'):bits(-1) == nil) + assert(inet('192.0.2.24'):bits(0) == nil) + assert(inet('192.0.2.24'):bits(3) == nil) + assert(inet('192.0.2.24'):bits(33) == nil) + assert(inet('2001:db8::42/64'):bits(-1) == nil) + assert(inet('2001:db8::42/64'):bits(0) == nil) + assert(inet('2001:db8::42/64'):bits(42) == nil) + assert(inet('2001:db8::42/64'):bits(64) == nil) end local t = test.new() -- cgit v1.2.1