diff options
author | Asbjørn Sloth Tønnesen <ast@2e8.dk> | 2023-04-03 17:30:14 +0000 |
---|---|---|
committer | Asbjørn Sloth Tønnesen <ast@2e8.dk> | 2023-04-03 17:30:14 +0000 |
commit | 7d6bae27cc46c2a587e8e8c3515b1322c8271ed2 (patch) | |
tree | 368ce6747552b722003f5ef802a883c24c23f9fb /lua/inet/core.lua | |
parent | 2910e546f11b556d0f9c3013d4f74957c808bd27 (diff) | |
download | lua-inet-7d6bae27cc46c2a587e8e8c3515b1322c8271ed2.tar.gz lua-inet-7d6bae27cc46c2a587e8e8c3515b1322c8271ed2.tar.xz lua-inet-7d6bae27cc46c2a587e8e8c3515b1322c8271ed2.zip |
expose LPeg patterns
Signed-off-by: Asbjørn Sloth Tønnesen <ast@2e8.dk>
Diffstat (limited to 'lua/inet/core.lua')
-rw-r--r-- | lua/inet/core.lua | 121 |
1 files changed, 76 insertions, 45 deletions
diff --git a/lua/inet/core.lua b/lua/inet/core.lua index 2b36543..a12a036 100644 --- a/lua/inet/core.lua +++ b/lua/inet/core.lua @@ -79,13 +79,42 @@ function inet:full_family() return format('ipv%d', self:family()) end +local function build_bip(o1, o2, o3, o4) + return lshift(o1, 24) + lshift(o2, 16) + lshift(o3, 8) + o4 +end + +local function make_inet4(bip, mask) + return setmetatable({ + bip = bip, + mask = mask or 32, + }, inet4) +end + +local function make_inet6(pcs, mask) + local r = setmetatable({ + pcs = pcs, + mask = mask or 128, + }, inet6) + + -- ensure that the result is balanced + if not r:is_balanced() then + r:balance() + return nil, tostring(r)..' unbalanced' + end + + return r +end + +local ipv4_peg local ipv4_parser +local ipv6_peg local ipv6_parser do local lpeg = require 'lpeg' local C, Ct = lpeg.C, lpeg.Ct local S, R = lpeg.S, lpeg.R local B, Cc = lpeg.B, lpeg.Cc + local Cmt = lpeg.Cmt local digit = R('09') @@ -105,7 +134,13 @@ do local mask12 = R('12') * digit local mask3 = S('3') * R('02') local netmask = S('/') * C(mask12 + mask3 + digit) - ipv4_parser = ipv4addr * (netmask + Cc()) * -1 + local ipv4_base = ipv4addr * (netmask + Cc()) / + function (o1, o2, o3, o4, mask) + local bip = build_bip(o1, o2, o3, o4) + return bip, tonumber(mask) + end + ipv4_parser = ipv4_base * -1 + ipv4_peg = ipv4_base / make_inet4 end do @@ -124,20 +159,43 @@ do local partial = (piece * (colpi^-6))^-1 * colcol * ((picol^-6)*(ipv4embed+piece))^-1 local netmask = S('/') * C((digit^-3)) / tonumber local pieces = full + partial - ipv6_parser = Ct(pieces) * ((netmask + Cc())^-1) * -1 - end -end + local function check_pcs(_, _, pcs, mask) + if #pcs > 8 then return false end + if mask ~= nil and mask > 128 then return false end + return true, pcs, mask + end -local function build_bip(o1, o2, o3, o4) - return lshift(o1, 24) + lshift(o2, 16) + lshift(o3, 8) + o4 + local function expand_pieces(pcs) + local zero_pieces = 8 - #pcs + for i=1,#pcs do + if pcs[i] == '::' then + pcs[i] = 0 + for j=#pcs,i,-1 do + pcs[j+zero_pieces] = pcs[j] + end + for j=1,zero_pieces do + pcs[i+j] = 0 + end + end + end + assert(#pcs == 8, 'incorrect number of pieces') + return pcs + end + + local ipv6_base = Cmt(Ct(pieces) * ((netmask + Cc())^-1), check_pcs) / + function (pcs, mask) + expand_pieces(pcs) + return pcs, mask + end + ipv6_parser = ipv6_base * -1 + ipv6_peg = ipv6_base / make_inet6 + end end local function inet4_from_string(ipstr) - local o1, o2, o3, o4, mask = ipv4_parser:match(ipstr) - if not o1 then return nil, 'parse error' end - - local bip = build_bip(o1, o2, o3, o4) - return bip, tonumber(mask) + local bip, mask = ipv4_parser:match(ipstr) + if not bip then return nil, 'parse error' end + return bip, mask end local function inet4_from_number(bip) @@ -166,23 +224,6 @@ local inet4_constructors = { local function inet6_from_string(ipstr) local pcs, netmask = ipv6_parser:match(ipstr) if not pcs then return nil, 'parse error' end - if #pcs > 8 then return nil, 'too many pieces' end - local zero_pieces = 8 - #pcs - for i=1,#pcs do - if pcs[i] == '::' then - pcs[i] = 0 - for j=#pcs,i,-1 do - pcs[j+zero_pieces] = pcs[j] - end - for j=1,zero_pieces do - pcs[i+j] = 0 - end - end - end - if #pcs > 8 then return nil, 'too many pieces' end - if netmask ~= nil and netmask > 128 then - return nil, 'invalid netmask' - end return pcs, netmask end @@ -239,28 +280,13 @@ end local function new_inet4(ip, mask) local bip, outmask = generic_new(inet4_constructors, 32, ip, mask) if not bip then return nil, outmask end - return setmetatable({ - bip = bip, - mask = outmask, - }, inet4) + return make_inet4(bip, outmask) end local function new_inet6(ip, mask) local pcs, outmask = generic_new(inet6_constructors, 128, ip, mask) if not pcs then return nil, outmask end - - local r = setmetatable({ - pcs = pcs, - mask = outmask, - }, inet6) - - -- ensure that the result is balanced - if not r:is_balanced() then - r:balance() - return nil, tostring(r)..' unbalanced' - end - - return r + return make_inet6(pcs, outmask) end local function new_inet(ip, mask) @@ -877,5 +903,10 @@ M.is_inet4 = is_inet4 M.is_inet6 = is_inet6 M.is_inet = is_inet M.new_inet = new_inet +M.lpeg = { + ipv4 = ipv4_peg, + ipv6 = ipv6_peg, + ip = ipv4_peg + ipv6_peg, +} return M |