summaryrefslogtreecommitdiffstats
path: root/acf/model/net.lua
diff options
context:
space:
mode:
Diffstat (limited to 'acf/model/net.lua')
-rw-r--r--acf/model/net.lua88
1 files changed, 88 insertions, 0 deletions
diff --git a/acf/model/net.lua b/acf/model/net.lua
new file mode 100644
index 0000000..725c543
--- /dev/null
+++ b/acf/model/net.lua
@@ -0,0 +1,88 @@
+--[[
+Copyright (c) 2012-2013 Kaarle Ritvanen
+See LICENSE file for license details
+--]]
+
+module(..., package.seeall)
+
+local raise = require('acf.error').raise
+local Union = require('acf.model.combination').Union
+
+local fld = require('acf.model.field')
+local String = fld.String
+
+local object = require('acf.object')
+local class = object.class
+local super = object.super
+
+local update = require('acf.util').update
+
+
+require 'stringy'
+
+
+IPv4Address = class(String)
+
+function IPv4Address:validate(context, value)
+ super(self, IPv4Address):validate(context, value)
+ local function test(...)
+ if #arg ~= 4 then return true end
+ for _, octet in ipairs(arg) do
+ if tonumber(octet) > 255 then return true end
+ end
+ end
+ if test(string.match(value, '^(%d+)%.(%d+)%.(%d+)%.(%d+)$')) then
+ raise(context.path, 'Invalid IPv4 address')
+ end
+end
+
+
+IPv6Address = class(String)
+
+function IPv6Address:validate(context, value)
+ super(self, 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 string.match(comp, '^%x%x?%x?%x?$') then invalid() end
+ end
+ if not short and #comps < 8 then invalid() end
+end
+
+
+IPAddress = class(Union)
+
+function IPAddress:init(params)
+ super(self, IPAddress):init(
+ update(
+ params, {types={IPv4Address, IPv6Address}, error='Invalid IP address'}
+ )
+ )
+end
+
+
+Port = class(fld.Integer)
+
+function Port:validate(context, value)
+ super(self, Port):validate(context, value)
+ if value < 0 or value > 65535 then raise(context.path, 'Invalid port') end
+end