Module:IP: Difference between revisions

From the Croc Wiki, the Croc encyclopedia
Jump to navigationJump to search
1,474 bytes added ,  7 years ago
need to use __index to have a unique key which is really private - if outside code gets uniqueKey with getmetatable then they can set it in another table's __eq metamethod, thus foiling isSubnetObject
(use getmetatable to implement isSubnetObject)
(need to use __index to have a unique key which is really private - if outside code gets uniqueKey with getmetatable then they can set it in another table's __eq metamethod, thus foiling isSubnetObject)
 
(10 intermediate revisions by 2 users not shown)
Line 8:
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local makeCheckSelfFunction = libraryUtil.makeCheckSelfFunction
 
-- Constants
Line 17 ⟶ 18:
--------------------------------------------------------------------------------
 
local function makeCheckSelfFuncmakeValidationFunction(className, objectName, isSelfFuncisObjectFunc)
-- Makes a function for classes to check that their methods have a valid
-- self parameter.
return function (methodName, selfObject)
if not isSelfFunc(selfObject) then
error(string.format(
'invalid %s object. Did you call %s with a dot instead of a colon, i.e. %s.%s() instead of %s:%s()?',
className, methodName, objectName, methodName, objectName, methodName
), 3)
end
end
end
 
local function makeValidationFunc(className, isObjectFunc)
-- Make a function for validating a specific object.
return function (methodName, argIdx, arg)
Line 368 ⟶ 356:
end
 
validateIPAddress = makeValidationFunction('IPAddress', isIPAddressObject)
-- A function to check whether methods are called with a valid self
-- parameter.
local checkSelf = makeCheckSelfFunc(
'IPAddress',
'ipAddress',
isIPAddressObject
)
 
validateIPAddress = makeValidationFunc('IPAddress', isIPAddressObject)
 
-- Metamethods that don't need upvalues
Line 407 ⟶ 387:
local data = {}
data.rawIP = rawIP
 
-- A function to check whether methods are called with a valid self
-- parameter.
local checkSelf = makeCheckSelfFunction(
'IP',
'ipAddress',
obj,
'IPAddress object'
)
 
-- Public methods
function obj:getIP()
checkSelf(self, 'getIP', self)
return tostring(data.rawIP)
end
 
function obj:getVersion()
checkSelf(self, 'getVersion', self)
return data.rawIP:getVersion()
end
 
function obj:isIPv4()
checkSelf(self, 'isIPv4', self)
return data.rawIP:isIPv4()
end
 
function obj:isIPv6()
checkSelf(self, 'isIPv6', self)
return data.rawIP:isIPv6()
end
 
function obj:isInSubnet(subnet)
checkSelf(self, 'isInSubnet', self)
local tp = type(subnet)
if tp == 'string' then
Line 443 ⟶ 432:
 
function obj:getSubnet(bitLength)
checkSelf(self, 'getSubnet', self)
checkType('getSubnet', 1, bitLength, 'number')
return makeSubnetFromRaw(data.rawIP, bitLength)
Line 449 ⟶ 438:
 
function obj:getNextIP()
checkSelf(self, 'getNextIP', self)
return makeIPAddressFromRaw(data.rawIP:getAdjacent())
end
 
function obj:getPreviousIP()
checkSelf(self, 'getPreviousIP', self)
return makeIPAddressFromRaw(data.rawIP:getAdjacent(true))
end
Line 471 ⟶ 460:
end
end,
__metatable = false, -- Don't allow access to the metatable
})
end
Line 496 ⟶ 486:
 
do
-- uniqueKey is a unique, private key used to test whether a given object
-- Metatable
-- is a Subnet object.
local mt = {
local uniqueKey = setmetatable({}, {__metatable = false})
__eq = function (self, obj)
return self:getCIDR() == obj:getCIDR()
end,
__tostring = function (self)
return self:getCIDR()
end,
}
 
-- Private static methods
local function isSubnetObject(val)
-- Return true if val is a Subnet object, and false otherwise.
return getmetatable(val) == mt
return getmetatable(val) == uniqueKey
end
 
-- Function to validate subnet objects.
validateSubnet = makeValidationFunc('Subnet', isSubnetObject)
-- Params:
-- methodName (string) - the name of the method being validated
-- argIdx (number) - the position of the argument in the argument list
-- arg - the argument to be validated
validateSubnet = makeValidationFunction('Subnet', isSubnetObject)
 
-- Metamethods that don't need upvalues
local function subnetEquals(subnet1, subnet2)
return subnet1:getCIDR() == subnet2:getCIDR()
end
 
local function concatenateSubnets(subnet1, subnet2)
return tostring(subnet1) .. tostring(subnet2)
end
 
local function subnetToString(subnet)
return subnet:getCIDR()
end
 
-- Constructors
makeSubnetFromRaw = function (rawIP, bitLength)
-- Set up structure
local obj = setmetatable({}, mt)
local data = {
rawIP = rawIP,
bitLength = bitLength,
}
 
-- A function to check whether methods are called with a valid self
-- parameter.
local checkSelf = makeCheckSelfFunction(
'IP',
'subnet',
obj,
'Subnet object'
)
 
-- Public methods
function obj:getPrefix()
checkSelf(self, 'getPrefix')
if not data.prefix then
data.prefix = makeIPAddressFromRaw(
Line 533 ⟶ 546:
 
function obj:getHighestIP()
checkSelf(self, 'getHighestIP')
if not data.highestIP then
data.highestIP = makeIPAddressFromRaw(
Line 542 ⟶ 556:
 
function obj:getBitLength()
checkSelf(self, 'getBitLength')
return data.bitLength
end
 
function obj:getCIDR()
checkSelf(self, 'getCIDR')
return string.format(
'%s/%d',
Line 553 ⟶ 569:
 
function obj:getVersion()
checkSelf(self, 'getVersion')
return data.rawIP:getVersion()
end
 
function obj:isIPv4()
checkSelf(self, 'isIPv4')
return data.rawIP:isIPv4()
end
 
function obj:isIPv6()
checkSelf(self, 'isIPv6')
return data.rawIP:isIPv6()
end
 
function obj:containsIP(ip)
checkSelf(self, 'containsIP')
local tp = type(ip)
if tp == 'string' then
ip = makeIPAddress(ip)
elseif tp == 'table' then
validateIPAddress('containsIP', 1, ip)
else
checkTypeMulti('containsIP', 1, ip, {'string', 'table'})
end
if self:getVersion() == ip:getVersion() then
return self:getPrefix() <= ip and ip <= self:getHighestIP()
Line 572 ⟶ 600:
 
function obj:overlapsSubnet(subnet)
checkSelf(self, 'overlapsSubnet')
local tp = type(subnet)
if tp == 'string' then
subnet = makeSubnet(subnet)
elseif tp == 'table' then
validateSubnet('overlapsSubnet', 1, subnet)
else
checkTypeMulti('overlapsSubnet', 1, subnet, {'string', 'table'})
end
if self:getVersion() == subnet:getVersion() then
return (
Line 582 ⟶ 619:
 
function obj:walk()
checkSelf(self, 'walk')
local started
local current = self:getPrefix()
Line 597 ⟶ 635:
end
 
return setmetatable(obj, {
__index = function (self, key)
if key == uniqueKey then
return true
end
end,
__eq = subnetEquals,
__concat = concatenateSubnets,
__tostring = subnetToString,
__metatable = false,
})
end
 
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu