summaryrefslogtreecommitdiffstats
path: root/acf2/model/net.lua
diff options
context:
space:
mode:
Diffstat (limited to 'acf2/model/net.lua')
-rw-r--r--acf2/model/net.lua96
1 files changed, 96 insertions, 0 deletions
diff --git a/acf2/model/net.lua b/acf2/model/net.lua
new file mode 100644
index 0000000..27ab262
--- /dev/null
+++ b/acf2/model/net.lua
@@ -0,0 +1,96 @@
+--[[
+Copyright (c) 2012-2013 Kaarle Ritvanen
+See LICENSE file for license details
+--]]
+
+local M = {}
+
+local raise = require('acf2.error').raise
+local Union = require('acf2.model.combination').Union
+
+local fld = require('acf2.model.field')
+local String = fld.String
+
+local object = require('acf2.object')
+local class = object.class
+local super = object.super
+
+local update = require('acf2.util').update
+
+
+local stringy = require('stringy')
+
+
+M.IPv4Address = class(String)
+
+function M.IPv4Address:validate(context, value)
+ super(self, M.IPv4Address):validate(context, value)
+ local function test(...)
+ if #{...} ~= 4 then return true end
+ for _, octet in ipairs{...} do
+ if tonumber(octet) > 255 then return true end
+ end
+ end
+ if test(value:match('^(%d+)%.(%d+)%.(%d+)%.(%d+)$')) then
+ raise(context.path, 'Invalid IPv4 address')
+ end
+end
+
+
+M.IPv6Address = class(String)
+
+function M.IPv6Address:validate(context, value)
+ super(self, M.IPv6Address):validate(context, value)
+
+ local function invalid() raise(context.path, 'Invalid IPv6 address') end
+
+ if value == '' then invalid() end
+
+ local comps = stringy.split(value, ':')
+ if #comps < 3 then invalid() end
+
+ local function collapse(i, ofs)
+ if comps[i] > '' then return end
+ if comps[i + ofs] > '' then invalid() end
+ table.remove(comps, i)
+ end
+ collapse(1, 1)
+ collapse(#comps, -1)
+ if #comps > 8 then invalid() end
+
+ local short = false
+ for _, comp in ipairs(comps) do
+ if comp == '' then
+ if short then invalid() end
+ short = true
+ elseif not comp:match('^%x%x?%x?%x?$') then invalid() end
+ end
+ if (
+ short and #comps == 3 and comps[2] == ''
+ ) or (not short and #comps < 8) then
+ invalid()
+ end
+end
+
+
+M.IPAddress = class(Union)
+
+function M.IPAddress:init(params)
+ super(self, M.IPAddress):init(
+ update(
+ params,
+ {types={M.IPv4Address, M.IPv6Address}, error='Invalid IP address'}
+ )
+ )
+end
+
+
+M.Port = class(fld.Integer)
+
+function M.Port:validate(context, value)
+ super(self, M.Port):validate(context, value)
+ if value < 0 or value > 65535 then raise(context.path, 'Invalid port') end
+end
+
+
+return M